<?xml version="1.0" encoding="UTF-8"?>

<!-- ====================================================================== -->
<!-- = chapter-1.xml                                                      = -->
<!-- = standard nwg services module guide - chapter 1                     = -->
<!-- ====================================================================== -->
<!-- = This  program  is  free  software; you  can redistribute it and/or = -->
<!-- = modify it provided that this copyright notice is kept intact.      = -->
<!-- = This program is distributed in the hope that it will be useful but = -->
<!-- = without  any  warranty;  without  even  the  implied  warranty  of = -->
<!-- = merchantability or fitness for  a  particular purpose. In no event = -->
<!-- = shall  the  copyright  holder be liable for any  direct, indirect, = -->
<!-- = incidental  or special  damages arising  in any way out of the use = -->
<!-- = of this software.                                                  = -->
<!-- ====================================================================== -->
<!-- = copyright (c) 2005-2007 - amaury darsch                            = -->
<!-- ====================================================================== -->

<chapter module="nwg" number="1">
  <title>Standard network working group object</title>
  
  <p>
  This chapter covers the fundamental objects of the <afnix/> standard
  network working group service module. This modules contain object
  that are generally defined by a RFC and used in networking
  application.
  </p>

  <p>
  All <afnix/> network working group objects are located in the
  <code>afnix-nwg</code> module. This module must be loaded prior any
  operation. Multiple calls to the module initialization routine are
  harmless. The interpreter method <code>module</code> loads a
  specific module by name. When the module has been loaded, the object
  are available in the <code>afnix:nwg</code> nameset.
  </p>
  
  <example>
  interp:library "afnix-nwg"
  </example>

  <!-- uri class -->
  <section>
    <title>The uri class</title>

    <p>
    The <code>Uri</code> class is a base class that parse a
    <em>Uniform Resource Identifier</em> or uri string and provides
    methods to access individual component of that uri. The
    implementation conforms to RFC 3986. The URI components are the
    scheme, the authority, the path, the query and the fragment. The
    class also takes care of the character escaping.
    </p>

    <example>
    const uri (afnix:www:Uri "http://www.afnix.org")
    </example>

    <p>
    An uri can be broken into several components called the
    <em>scheme</em>, the <em>authority</em>, the <em>path</em>,
    optionally the <em>query</em> and the <em>fragment</em>. The
    <code>Uri</code> class provide a method to retrieve each component
    of the parsed uri.
    </p>

    <example>
    const uri (afnix:www:Uri "http://www.afnix.org/")
    println (uri:get-scheme)    # http
    println (uri:get-authority) # www.afnix.org
    println (uri:get-path)      # /
    </example>
 
    <!-- character conversion -->
    <subsect>
      <title>Character conversion</title>

      <p>
      The <code>Uri</code> class performs automatically the character
      conversion in the input uri. For example, the <tt>+</tt>
      character is replaced by a blank. The <tt>%</tt> character
      followed by two hexadecimal values is replaced by the
      corresponding ASCII character. Note that this conversion does
      now apply to the query string.
      </p>
    </subsect>

    <!-- query string -->
    <subsect>
      <title>Query string</title>

      <p>
      The <code>get-query</code> method returns the query string of
      the uri. The query string starts after the <tt>?</tt>
      character. The query string is a series of key-pair values
      separated by the <tt>&amp;</tt> character.
      </p>

      <example>
      const uri (afnix:www:Uri 
                 "http://www.afnix.org?name=hello&amp;value=world")
      println (uri:get-query) # name=hello&amp;value=world
      </example>

      <p>
      The module also provides the <code>UriQuery</code> class that
      parses the query string and store the result in the form of a
      property list. The query string parse is particularly useful
      when writing automated scripts.
      </p>
    </subsect>

    <example>
    # create a query string object
    const qs (afnix:nwg:UriQuery (uri:get-query))
    # get the name value
    qs:get-value "name"
    </example>
  </section>

  <!-- cgi request handling -->
  <section>
    <title>Managing a cgi request</title>

    <p>
    Managing a cgi request involves primarily  the parsing of the
    requesting uri. The uri generally contains the http referrer as
    well as parameter which are stored in the form of a query
    string. However, depending on the cgi method which can be of type
    <em>GET</em> or <em>POST</em>, the treatment is somewhat
    different.
    </p>

    <!-- checkig the protocol version -->
    <subsect>
      <title>Checking the protocol version</title>

      <p>
      In the presence of a cgi protocol, it is always a good idea to
      check the protocol version, or at least to put an assertion. The
      protocol version is normally <em>CGI/1.1</em> and is stored in
      the <em>GATEWAY_INTERFACE</em> environment variable.
      </p>

      <example>
      # check the cgi protocol
      assert "CGI/1.1" (afnix:sys:get-env "GATEWAY_INTERFACE")
      </example>
    </subsect>

    <!-- getting the query string -->
    <subsect>
      <title>Getting the query string</title>

      <p>
      If the request method is <tt>GET</tt>, then the query string is
      available in the environment variable <tt>QUERY_STRING</tt>. If 
      the request method is <tt>POST</tt>, the query string is
      available in the input stream. The length of the query string is
      given by the <tt>CONTENT_LENGTH</tt> environment variable. The 
      following example illustrates the extraction of the query
      string.
      </p>

      <example>
      # check the cgi protocol
      assert "CGI/.1" (afnix:sys:get-env "GATEWAY_INTERFACE")
      # initialize the query string
      const query (afnix:sys:get-env "QUERY_STRING")
      # get the request method
      const rqm (afnix:sys:get-env "REQUEST_METHOD")
      # check for a post request and update the query string
      if (== rqm "POST") {
        # create a buffer from the content length
        const len (Integer (afnix:sys:get-env "CONTENT_LENGTH"))
        # get the standard input stream and read content
        const is  (interp:get-input-stream)
        const buf (is:read len)
        # set the query string
        query:= (buf:to-string)
      }
      </example>
    </subsect>

    <!-- parsing the query string -->
    <subsect>
      <title>Parsing the query string</title>

      <p>
      The <code>UriQuery</code> class is designed to parse a cgi query 
      string. Once the string has been parsed, it is possible to
      perform a query by key since the class operates with a property
      list.
      </p>

      <example>
      const query  (afnix:www:UriQuery "name=hello&amp;value=world")
      query:length      # 2
      query:get-value "name"  # hello
      query:get-value "value" # world
      </example>

      <p>
      The <code>UriQuery</code> class is the foundation to build
      cgi script. When the library is combined with the <em>web
      application management (wam)</em> service, powerful
      applications can be built easily.
      </p>
    </subsect>
  </section>
</chapter>

