Patch title: Release 85 bulk changes
Abstract:
File: /pliant/protocol/http/index.page
Key:
    Removed line
    Added line
title "Pliant HTTP server"


header "The Pliant HTTP server design"

  image "/pliant/welcome/image/earth.jpeg" right
  box right
    image "/pliant/welcome/image/earth.jpeg"
  para
    [The Pliant ] ; link "HTTP" "http://www.ietf.org/rfc/rfc2616.txt " ; [ server is designed mainly for serving dynamic pages, but it can also be used as a classical HTTP server. ]
    [It's key difference with other HTTP servers is that it introduces a new text file format, called ] ; link ".page" "page" ; [. ]
    [The .page file format can be learned in very few time, because it's not more complicated to write .page files than to write HTML pages using a text editor, but it scales incredibly better because .page files are true Pliant programs, so adding dynamic features is easy, is done using the very consistent Pliant syntax, and you get all Pliant language power (dynamic compiling, meta programming).]
  para
    [The performances of the Pliant HTTP server as a static pages server are probably not very high, and it's not a main goal to increase this because focusing on static pages only servers is stupid: most sites are network bandwild bounded, so the only interesting goals are getting more flexibility and reasonable security.] ; eol
    [However, should your site be processor speed bounded, it's probably not due to static pages servicing but due to true dynamic pages servicing.] ; eol
    [Now, if you really are a very special site that has so much bandwild that you get processor speed bounded, the best to do is probably to run two HTTP servers in a Linux box: the Linux kernel HTTP server will fast service the most frequently accessed static pages, and the Pliant HTTP server will give you the greatest flexibility on dynamic pages. ]
    [Another even more powerfull alternative might be to use TUX (developped by the clever Ingo Molnar) as the kernel HTTP server.]
    [If you need such solutions, please keep in touch we ] ; link "me" "mailto:hubert.tonneau@pliant.cx" ; [ so that I can provide you advises on how to configure your server, and add improvements in order to increase Pliant HTTP server scalability based on real big sites experiments rather than abstract benchmark numbers.]


header "Running the Pliant HTTP server"

  [The simplest way to start Pliant HTTP server is to type in the following command at the shell prompt:]
  listing
    pliant module /pliant/protocol/http/server.pli command 'http_server configure'
  [or]
  listing
    pliant module /pliant/protocol/http/server.pli command 'http_server port 8080 configure'
  [Use the second version if another HTTP server is running on your computer or if you are running Unix and don't have root rights.] ; eol
  [If everything works fine, you should be prompted for the administrator id and password, then get a message:] ; eol
  fixed [HTTP server is running on TCP port 80.] ; eol
  [or] ; fixed [ HTTP server is running on TCP port 8080.] ; eol
  [and the program should not stop.] ; eol
  [If the program stoped (you get back to the prompt), you probably have another HTTP server already running (you can get around that changing the port value), or your TCP/IP layer is not configured properly at operating system level. ]
  [On a Unix system, you may also not be able to start the HTTP server on port 80 if you don't have 'root' rights.]
  
  para
    highlight "Important: " ; [If you specifyed 'configure' option when starting the HTTP server, then, in your browser, you have to connect to the server using] ; fixed [ http://localhost/ ] ; [or] ; fixed [ http://localhost:8080/ ] ; [but not any other server name such as the real name of your computer since the access would be rejected unless you HTTP server is already fully configured.]
  
  para
    [Now, these are all options you may select when starting the HTTP server:] ; eol
    fixed
      [pliant module /pliant/protocol/http/server.pli command 'http_server ]
      note "configure"
        title "'configure' option in the HTTP server"
        [Specifies that you want to configure the HTTP server, so it will ask you for the administrator user id and password, then assume that any local connection (the browser must on the same computer as the HTTP server) that connects though a] ; fixed [ http://localhost/ ] ; [URL is connecting as the administrator to the Pliant documentation site which is also the HTTP server configuration site.] ; eol
        [This is very important since it enables you to connect to the HTTP server even if it's not fully configured yet, or the configuration is broken, ]
        [and to setup the HTTP server using the browser through selecting the '] ; link "Configuring Pliant services" "/pliant/admin/" ; [' link.]
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server configure'
      [ ]
      note "simulate"
        title "'simulate' option in the HTTP server"
        [Specifies that you want to test a site locally.] ; eol
        para
          [Selecting] ; fixed [ http://localhost/ ] ; [ in your browser will enable to locally test and debug the site specifyed using the simulate option.] ; eol
          [Of course, this works only is the specifyed site has been ] ; link "configured" "/pliant/admin/site" ; [.]       
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server simulate "art.pliant.cx"'
      italic
        [ a_string ]
      note "name"
        title "'name' option in the HTTP server"
        ['name' option specifies the name you want to give to the HTTP server.] ; eol
        [This is not an important option.]
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server name "MYSERVER" port 8080'
      italic
        [ a_string ]
      note "port"
        title "'port' option in the HTTP server"
        ['port' option selects the TCP port that the HTTP server will use.] ; eol
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server port 8080 name "MYSERVER"'
      italic
        [ an_integer ]
      note "secured"
        title "'secured' option in the HTTP server"
        ['secured' option specifies that Pliant should also listing on another TCP port for secured connections.] ; eol
        [The default port used by Pliant secured connections is 580, or more pecisely, the port used by clear conenctions plus 500.] ; eol
        para
          [Please also notice that Pliant HTTP server does not use SSL for secured connections but the much more powerfull (and still probably less secured at the moment since it needs reviewing) ] ; link "Pliant crypto system" "/pliant/util/crypto/" ; [.]
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server secured'
      [ ]
      note "secured_port"
        title "'secured_port' option in the HTTP server"
        ['secured_port' option selects the TCP port that the HTTP server will use for secured connections.] ; eol
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server secured secured_port 580'
      italic
        [ an_integer ]
      note "channel"
        title "'channel' option in the HTTP server"
        ['channel' is a more advanced version of 'port' option that enables you to fully select what streams the HTTP server will open in order to get connected to a client.] ; eol
        [This option has been included for completeness, but I don't know if somebody will ever use it.] ; eol
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server channel { gvar Array:Str channels ; channels += "tcp:/server/6789" ; channels }'
      italic
        [ an_array_of_strings ]
      note "protocol_level"
        title "'protocol_level' option in the HTTP server"
        ['protocol_level' is the HTTP protocol level that you want Pliant HTTP server to use.] ; eol
        [The possible values are [dq]0.9[dq] [dq]1.0[dq] and [dq]1.1[dq]] ; eol
        [Default value will always be the highest version fully supported, so it's 1.0 at the moment because 1.1 implementation is still buggy.] ; eol
        [For technical users, please notice that moving to 1.1 would not improve much performances since keeping connections alive is implemented in 1.0 protocol.]
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server protocol_level "1.0" name "MYSERVER"'
      italic
        [ a_string ]
      note "send_software_release_number"
        title "'send_software_release_number' option in the HTTP server"
        ['send_software_release_number' specifies if the HTTP server will tel the client what release of Pliant it's running on.] ; eol
        [The default is true.] ; eol
        [The release number may be used to check if the HTTP server contains a known security hole, so you may want to suppress it, also the extra security it brings is really thin since changing the option will not remove the hole.]
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server port 8080 send_software_release_number false name "PARANO"'
      italic
        [ a_boolean ]
      note "maximal_form_length"
        title "'maximal_form_length' option in the HTTP server"
        ['maximal_form_length' specifies how many datas the HTTP client is allowed to send in a POST request.] ; eol
        [The default value is 2^16 (64 KB).] ; eol
        [You may want to increase this value if the client needs to send really long forms result or sets of options, but increasing the number will make your HTTP server weaker because many clients sending big POST requests will currently exhaust the server resources.]
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server port 8080 maximal_form_length 2^20 name "MYSERVER"'
      italic
        [ an_integer ]
      note "log"
        title "'log' option in the HTTP server"
        ['log' specifies where the HTTP server should log all requests and answers headers.] ; eol
        [This will enable you to make offline statistics about the clients that connect to your site.]
        para
          [An example:]
          listing
            pliant module /pliant/protocol/http/server.pli command 'http_server log "file:/tmp/http.log"'
      italic
        [ a_string]
      [']
  
  para
    [If you want the HTTP server to start faster, you can use Pliant precompiling capabilities.] ; eol
    [So, you'll simply enter something like:]
    listing
      pliant 'precompile /binary/http.dump module /pliant/protocol/http/server.pli module /pliant/protocol/http/style/default.style' module /pliant/protocol/http/server.pli command http_server


section "security"
header "Security"

  header "Overview"
    [The new Pliant security mechanism for the HTTP server is based on an infinit number of rights. ]
    [Each right is identifyed by a (case sensitive) string.] ; eol
    [When the request is received, the HTTP will look in the users database and grant rights.] ; how "server.pli" section "method assign_user" ; [ ]
    [A not logged in client will be assigned to user 'anonymous'] ; eol
    [Before sending the requested page to the client, the server will check that the user as 'read' right.] ; how "server.pli" section "method assign_site" ; [ ]
    [ which means that he has the right specifyed in the 'Read' field of the area he is trying to access.] ; eol
    [The dynamic page can also test other rights ('allowed'] ; how "style/common.style" section "method allowed" ; [ method) and so decide to hide some parts of the page and so on, or simply reject the user request if the specifyed right is not granted ('requires'] ; how "style/common.style" section "meta requires" ; [  method).]

    table columns 1 border 0
      cell color lsh 80 10 0 
      cell color (color hsl 0 10 75)
        [A .page file is something that will be executed by the Pliant server, so if you let a user upload a .page (or upload something, then rename it to .page), then it can be a torjan horse.]

  header "Predefined rights"

    table columns 2
       cell header [Right]
       cell header [Meaning]
       cell fixed:[administrator]
       cell
         [A user which is granted] ; fixed [ adminstrator ] ; [right is granted all other rights.]
       cell fixed:[read]
       cell
         [This is a special right assigned to the user when he has the right specifyed in the 'Read' field of the area of the site the request applies to.] ; eol
         [You should never use this in the web sites and users configuration tables. It's used internaly by the Pliant HTTP server.]
       cell fixed:[write]
       cell
         [This is a special right assigned to the user when he has the right specifyed in the 'Write' field of the area of the site the request applies to.]
         [You should never use this in the web sites and users configuration tables. You can use it in a .page dynamic page in order to test if the use is allowed to [dq]write[dq] in the specifyed area. What [dq]write[dq] means is left free to your application. Most of the time it should mean that the user is allowed to do some kind of upload or patch upload, but you have to keep in mind that if a user is allowed to upload a .page file that will not be displayed using ultrasafe style, then he is allowed to upload a torjan horse.]


  header "How to provide secured access to your first site"

    [If you want to use secured access to the web site you have to:]
    list
      item
        [Define the web site on the server computer, and generate a key pair for it.]
      item
        [Define the user on the client computer, and generate a key pair for it.]
      item
        [Define the web site on the client computer, and cut paste it's public key from the server.]
      item
        [Define the user on the server computer, and cut paste it's public key from the client.]
    [It means that, in order to generate the user key pair, you have to run Pliant HTTP server locally.]

  header "Involved configuration files"

    table columns 2
      cell header [File]
      cell header [Content]
      cell fixed:[site.pdb]
      cell
        [The web sites definition.] ; eol
        small
          [You can copy this file to all your systems, and don't need to keep it secret. ]
          [On the other hand, anybody that succeed to change this file can get administrator right on the HTTP server, so can probably also corrupt all your system.]
      cell fixed:[site_secret.pdb]
      cell
        [The web sites private keys in clear text.] ; eol
        color lsh 0 75 0
        font color (color hsl 0 75 50)
          [You have to keep this file secret: anybody that succeed to read it can bypass the Pliant HTTP server security mechanism, can probably also corrupt the all server content, and can make clients believe that one of his systems is this HTTP server.]
      cell fixed:[user.pdb]
      cell
        [The users definition.] ; eol
        small
          [You can copy this file to all your systems, and don't need to keep it secret. ]
          [On the other hand, anybody that succeed to change this file can get administrator right on the HTTP server, so can probably also corrupt all your system.]
      cell fixed:[user_secret.pdb]
      cell
        [The users private keys, ciphered using the users password.] ; eol
        small
          [You should keep this file secret. If somebody succeed to read this file, then he still does not have the users private keys until he can also get the user password for the key, but most of the time, it's easier to brake the user password than to brake the key.]

    module "/pliant/admin/file.pli"
    [Nb: These files are stored in Pliant] ; fixed [ security:/ ] ; [directory which is] ; fixed (text " "+file_os_name:"security:/"+" ") ; [system directory on this server.]
    
    para
      [Another solution for configuring Pliant HTTP server both on a server and on a client computer is to configure everything locally on the server computer, then copy] ; fixed [ site.pdb ] ; [,] ; fixed [ user.pdb ] ; [and] ; fixed [ user_secret.pdb ] ; [on the client, and finally remove] ; fixed [ user_secret.pdb ] ; [on the server computer (also removing is recommended, not necessary).] ; eol
      [So, on the server you end with: ] ; fixed [ site.pdb site_secret.pdb user.pdb] ; eol
      [and on the client, you end with: ] ; fixed [ site.pdb user.pdb user_secret.pdb] ; eol
      [If you do things the other way round (configure everything on the client), then copy to the server, then you should also not use the network to copy the files from the client to the server since a network sniffer could pick] ; fixed [ site_secret.pdb ] ; [content on the fly, so it's not recommended.]

header "Dynamic pages"

  [Static pages can be written either in HTML format or .page format.] ; eol
  [On the other hand, if you are using Pliant HTTP server, dynamic pages have to be written using .page format, which is translated to HTML on the fly by the Pliant HTTP server.] ; eol
  link ".page format documentation" "page"

header "Virtual tree mechanism"

  para
    [When the requested page does not point to a .page or static file, the Pliant HTTP server will look for a virtual tree.] ; eol
    [As an example, if you request] ; fixed [ /abc/def/ghi/jkl.html ] ; [and there is no ] ; fixed [ /abc/def/ghi/jkl.html ] ; [or] ; fixed [ /abc/def/ghi/jkl.page ] ; [file, then the server will successively try to execute:] ; eol
    fixed
      [/abc/def/ghi/virtual_tree.page] ; eol
      [/abc/def/virtual_tree.page] ; eol
      [/abc/virtual_tree.page] ; eol
      [/virtual_tree.page] ; eol
    [If one such page exists, while it's executed, the 'virtual_path' variable is set with the subpath that have been removed to find the virtual page.]
  para
    [You can find an example in ] ; link "virtual_tree.page" "/pliant/browse/virtual_tree.page"
    [ and ] ; link "virtual_tree_PUT.page" "/pliant/browse/virtual_tree_PUT.page"
    [ that implement Pliant files and data browser.]

  para
    [If the clients sends a PUT HTTP request, the same mechanism is applyed, but the virtual page name must be] ; fixed [ virtual_tree_PUT.page] ; eol
    [and while the virtual page is executed, the 'http_request:put_file' variable is the name of the file that has been sent.]
 
  para
    [If the clients sends a DELETE HTTP request, the same mechanism is applyed, but the virtual page name must be] ; fixed [ virtual_tree_DELETE.page]
 

header "Server side style sheets"

  para
    [This is a sample style sheet that you could call] ; fixed [ sample.style ] ; [:]
    listing
      module "/pliant/protocol/http/server.pli"
      module "/pliant/protocol/http/style/default.style"
      method p highlight msg
        arg_rw HtmlPage p ; arg Str msg
        strong_definition
        p color lsh 50 100 60
        p font color (color hsl 60 100 50)
          p small
            p text msg
      export '. highlight'
    [Please notice the 'strong_definition' that has been included in the new 'highlight' function and means that the new definition will take on existing ones.]
  para
    [Then you want to apply the new style sheet to an existing .page file, you just include the module:]
    listing
      module "sample.style"
      text "This is the text " ; highlight "with it's highlighted part"
  para
    [So, the final result is:]
  para
    execute_dynamic_page "/pliant/protocol/http/style/tiny.html"
  para
    [Instead of:]
  para
    text "This is the text " ; highlight "with it's highlighted part"    
  para
    [This sample is available in ] ; link "/pliant/protocol/http/style/" "/pliant/browse/file/pliant/protocol/http/style/" ; [ directory.]


header "Implementation details"

  header "Pliant HTTP server modules"

    table columns 2
      cell
        link "server.pli" "server.pli"
      cell
        [contains the HTTP protocol layer. It uses several common services defined in /pliant/protocol/common/]
      cell
        link "style/common.pli" "style/common.style"
      cell
        [a set of functions that will be usefull for defining styles]
      cell
        link "style/common.style" "style/common.style"
      cell
        [most styles will include this one as a submodule: it provides some basic instructions that produce nothing visible but rather drive the browser or check the environment.]
      cell
        link "style/default.style" "style/default.style"
      cell
        [is the style sheet that defines the keywords available when using ] ; link ".page format" "page"
      cell
        link "style/untrasafe.style" "style/ultrasafe.style"
      cell
        [a .page file using this style cannot corrupt the HTTP server: all the intructions defined in the ] ; link ".page format" "page" ; [ are available, but no computation can be done.]
      cell
        link "filters.pli" "filters.pli"
      cell
        [is used to define some filters that will translate some text files to .page (dynamic filter) or something else such as HTML (static filter). ]
        [The filter is selected from the extension of the file, so at the end, you get pretty displaying for several text files formats.]
  
  header "How a request is processed"

    list
      item
        [Listening for clients on the TCP ports is handled by ] ; link "tcp_server.pli" "/pliant/protocol/common/tcp_server.pli" ; [ module that will then create a new thread and call the 'service'] ; how "server.pli" section "method service" ; [ method of the HTTP server.]
      item
        [The 'service' method will mainly loop on the 'parse_then_answer'] ; how "server.pli" section "method parse_then_answer" ; [ method which is responsible for handling one request.] ; eol
        list
          item
            ['parse_then_answer' will first scan all the lines of the client request header.] ; how "server.pli" section "parse_then_answer header"
          item
            [then it will use the informations in the header to determine the user which is submitting the request, the site and area concerned by the request, and the user rights.] ; how "server.pli" section "parse_then_answer user"
          item
            [the biggest part of the 'parse_then_answer' function is the one that handles multipart POST forms. If the form is multipart, then Pliant HTTP server will store uploaded files in temporary files and convert others so that it looks as is if the form add been submitted without multipart.] ; how "server.pli" section "parse_then_answer POST" 
      item
        [Finally, most of the time, since it's a GET request, 'parse_then_answer' will call 'answer'] ; how "server.pli" section "method answer" ; [ method.] ; eol
        ['answer' method is mapping the URL to a real file using 'what_file'] ; how "server.pli" section "method what_file" ;[ method that will add the site root path in front of the URL.]
        list
          item
            ['answer' method will first check if the user is allowed to access the URL, and if not, it will send /misc/not_allowed.html page]
          item
            [then it will try to provide the requested file through calling 'send_file'] ; how "server.pli" section "method send_file" ; [ method.]
          item
            [then it will scan for a virtual tree page.]
          item
            [and if nothing succeeded, it will send /misc/not_found.html page.]
      item
        [In 'send_file' method, we first try 'send_dynamic_file'] ; how "server.pli" section "method send_dynamic_file" ; [ then 'send_static_file'] ; how "server.pli" section "method send_static_file" ; [.] ; eol
        ['send_dynamic_file' is handling dynamic files such as .page .pli .c files that translate to an executable function.] ; eol
        ['send_static_file' is handling static files that the server will translate at run time.] ; eol

    para
      [The Pliant HTTP server uses the file extension to decide how to handle it.] ; eol
      [The extensions are recorded using 3 functions:] ; eol
      ['declare_mime_type'] ; how "/pliant/protocol/common/mime.pli" section "function declare_mime_type" ; [ just specify the MIME type to associate to the file when answering a HTTP request.] ; eol
      ['declare_mime_static_filter'] ; how "/pliant/protocol/common/mime.pli" section "function declare_mime_static_filter" ; [ provides a function that will translate the file on the fly at run time.] ; eol
      ['declare_mime_dynamic_filter'] ; how "/pliant/protocol/common/mime.pli" section "function declare_mime_dynamic_filter" ; [ provides a function that will translate the file to a Pliant program at compile time.] ; eol
      [You can find sample filters in ] ; link "filters.pli" "filters.pli" options "filter_ascii"

  header "How does the server handle dynamic pages"

    para
      [Pliant HTTP server maintains the set of dynamic pages in a dictionary called 'dynamic_pages'] ; how "server.pli" section "type DynamicPage" ; eol
      [Each page is convered from a .page source file (by the 'compile_dynamic_page'] ; how "server.pli" section "method compile_dynamic_page" ; [ method) to a Pliant function that will be stored in the dictionary. ]
      [This is done using a very classical Pliant mechanism: add a small header on top of the .page source code, then compile it using the standard 'compile_text' Pliant function.] ; eol
      [When a dynamic page is called, the function is retreved from the dictionary, then checked for consitency (if the source code file has changed, then it will be automatically recompiled) and finally executed. ]

    para
      [What's stronger in this system is the subpages notion. ]
      [A subpage is what will be executed when you click on a button. ]
      [The subpage is also recorded in the dictionary when the main one is, but it's a more sophisticated thing: it also is a function that will be executed, but this function has an environment parameter, which is a Pliant type that contains one field for each local variables that is expected to be passed from the main page to the subpage.]
      [When the function is executed in 'send_dynamic_file'] ; how "server.pli" section "method send_dynamic_file" ; [ method, the environement is scanned] ; how "server.pli" section "copy context" ; [ (the HTTP form, and the URL options) for local variables values, and these will be checked against the server signature (in order to protect against the client changing them), then copyed in the instance of the subpage function context data type.]

    para
      [In simple words, if you write this in a .page:]
      listing
        var Int i := 5
        button "press me"
          text "the value of i was "+string:i
      [then it will display 'the value of i was 5' because what's under the button will be recorded as a subpage, and this one will have a context type containing a 'i' field. ]
      [So, in the main page, when reaching the button position, Pliant will encode, then sign, then send the 'i' value to the browser, and when you press the button, the browser will send it back to the server that will copy it to the context it will pass to the subpage. ]
      [As a result, Pliant HTTP server machinery has completely hidden to your application the stateless nature of the HTTP protocol.]

    para
      [Of course, there is something magic here since the code handling dynamic page is so small, and it's the 'freeze' method defined in ] ; link "freeze.pli" "/pliant/language/compiler/expression/freeze.pli" ; [ module that is responsible for deciding which variables needs to be copyed, and compile the subpart of the function as a new function that will get the variables value from the enviroment structure rather than allocating them on the stack, ]
      [but it's not at all something specific to the HTTP server. As an example, it's also used by 'thread'] ; how "/pliant/language/schedule/thread.pli" ; [ control.]

  header "More details"

    [Now you can read the code, it's only roughly 1000 lines in a single ] ; link "server.pli" "server.pli" ; [ module, so an advanced programmer might be abble to read it in a single day and that's the utltimate justification of Pliant.]
  
  header "The Pliant HTTP server implementation status"
  
    [The current status of the HTTP server is described in the ]
    link "HTTP server" "/pliant/welcome/project/http"
    [ section of the ]
    link "Pliant overall project" "/pliant/welcome/project/"
    [.]