[ANN] Ocsigen Server 6.0.0

We’re delighted to announce a major new version of Ocsigen Server! This version 6.0.0 focuses on the use of Ocsigen Server as a library, without any configuration file, which is now much easier and brings the exact same features as the executable.

Example of use:

To add a Web server to your OCaml program, serving static files from directory static:

let _ = Ocsigen_server.start 
          [ Ocsigen_server.host [Staticmod.run ~dir:"static" ()]]

Install:

opam install ocsigenserver

Example of Dune file for this program:

(executable
 (public_name myproject)
 (name main)
 (libraries
  ocsigenserver
  ocsigenserver.ext.staticmod))

Compile with:

dune build

Ocsigen Server can of course still be used as an executable taking its configuration from a file. This allows for non OCaml developers to use it and make their own configurations. It also makes it possible to distribute a binary version of your Web applications.

Ocsigen Server is build in modular and extensible way. The default opam packages comes with several extensions. In the example above, we are using Staticmod for serving static files. Other extensions make it possible for example to configure redirections, to control the access to some sub-directories, to use a reverse proxy, to rewrite the request, compress the output etc.

The programming interface follows exactly the structure of the configuration file: instructions are tried in order until one generates a result, then some other instructions can be used to change the result (like compressing it or adding some headers).

Here is a more complex example of configuration:

let _ =
  Ocsigen_server.start
    ~ports:[`All, 8080]
    ~command_pipe:"local/var/run/mysite-cmd"
    ~logdir:"local/var/log/mysite"
    ~datadir:"local/var/data/mysite"
    ~default_charset:(Some "utf-8")
    [ Ocsigen_server.host
        ~regexp:"mydomain.com"
        [ Ocsigen_server.site ["subsite"]
            [ Accesscontrol.(
                if_
                  (and_
                     [ ip "122.122.122.122"
                     ; header ~name:"user-agent" ~regexp:".*FooBar.*"
                     ; method_ `POST ])
                  [forbidden] [])
            ; Authbasic.run ~realm:"myrealm"
                ~auth:(fun _u p -> Lwt.return (p = "toto"))
                ()
            ; Staticmod.run ~dir:"local/var/www/otherdir" () ]
        ; Ocsigen_server.site ["othersubsite"]
            [ Revproxy.run
                ~redirection:
                  (Revproxy.create_redirection ~full_url:false ~regexp:"(.*)"
                     ~keephost:true "http://localhost:8888/\\1")
                () ]
        ; Redirectmod.run
            ~redirection:
              (Redirectmod.create_redirection ~full_url:false ~regexp:"old(.*)"
                 "new\\1")
            ()
        ; Staticmod.run ~dir:"local/var/www/staticdir" ()
        ; Cors.run ~max_age:86400 ~credentials:true ~methods:[`POST; `GET; `HEAD]
            ~exposed_headers:
              [ "x-eliom-application"
              ; "x-eliom-location"
              ; "x-eliom-set-process-cookies"
              ; "x-eliom-set-cookie-substitutes" ]
            ()
        ; Deflatemod.run
            ~mode:
              (`Only
                [ `Type (Some "text", Some "html")
                ; `Type (Some "text", Some "javascript")
                ; `Type (Some "text", Some "css")
                ; `Type (Some "application", Some "javascript")
                ; `Type (Some "application", Some "x-javascript")
                ; `Type (Some "application", Some "xhtml+xml")
                ; `Type (Some "image", Some "svg+xml")
                ; `Type (Some "application", Some "x-eliom") ])
            () ] ]

In this example, the server defines one virtual host for domain mydomain.com. It will first check whether it is a request for directory subsite/, and if yes, will reject the request with 403 Forbidden if it is a POST request coming from user-agent FooBar at IP 122.122.122.122. If not, it will ask for a password before serving files from directory local/var/www/otherdir.
Then we define another subsite othersubsite for which the requests will be transfered to another Web server running locally on port 8888, then rewrite the answer location header accordingly.
Then, if the page is still not generated, the server will send a redirection if URLs starts with “old”.
Otherwise, it will try to serve files from directory local/var/www/staticdir.
If the page has still not been found, a 404 Not found will be sent, otherwise, some CORS headers will be added, and the result will be compressed before being sent.

Compile this example with the following dune file:

(executable
 (public_name myserver)
 (name main)
 (libraries
  ocsigenserver
  ocsigenserver.ext.staticmod
  ocsigenserver.ext.authbasic
  ocsigenserver.ext.extendconfiguration
  ocsigenserver.ext.outputfilter
  ocsigenserver.ext.cors
  ocsigenserver.ext.accesscontrol
  ocsigenserver.ext.deflatemod
  ocsigenserver.ext.redirectmod
  ocsigenserver.ext.revproxy
 ))

Alternatively you can launch the same server with command

ocsigenserver -c myserver.conf

Where myserver.conf is the following file:

<ocsigen>
  <server>
    <port>8080</port>
    <commandpipe>local/var/run/mysite-cmd</commandpipe>
    <logdir>local/var/log/mysite</logdir>
    <datadir>local/var/data/mysite</datadir>
    <charset>utf-8</charset>
    <debugmode/>
    <extension findlib-package="ocsigenserver.ext.staticmod"/>
    <extension findlib-package="ocsigenserver.ext.authbasic"/>
    <extension findlib-package="ocsigenserver.ext.extendconfiguration"/>
    <extension findlib-package="ocsigenserver.ext.outputfilter"/>
    <extension findlib-package="ocsigenserver.ext.cors"/>
    <extension findlib-package="ocsigenserver.ext.accesscontrol"/>
    <extension findlib-package="ocsigenserver.ext.deflatemod"/>
    <extension findlib-package="ocsigenserver.ext.redirectmod"/>
    <extension findlib-package="ocsigenserver.ext.revproxy"/>
    <host hostfilter="mydomain.com">
      <site dir="subsite">
        <if>
          <and>
            <ip value="122.122.122.122"/>
            <header name="user-agent" regexp=".*FooBar.*"/>
            <method value="POST"/>
          </and>
          <then>
            <forbidden/>
          </then>
        </if>
        <authbasic realm="myrealm">
          <plain login="" password="toto"/>
        </authbasic>
        <static dir="local/var/www/otherdir"/>
      </site>
      <site dir="othersite">
        <revproxy suburl="(.*)" keephost="true" dest="http://localhost:8888/otherdir/\\1"/>
        <outputfilter header="location" regexp="http://localhost:8888/(.* )" dest="http://mydomain.com/\\1"/>
      </site>
      <redirect suburl="old(.*)" dest="http://mydomain.org/new\\1"/>
      <static dir="local/var/www/staticdir"/>
      <cors max_age="86400"
       credentials="true"
       methods="POST,GET,HEAD"
       exposed_headers="x-eliom-application,x-eliom-location,x-eliom-set-process-cookies,x-eliom-set-cookie-substitutes"/>
      <deflate compress="only">
        <type>text/html</type>
        <type>text/javascript</type>
        <type>text/css</type>
        <type>application/javascript</type>
        <type>application/x-javascript</type>
        <type>application/xhtml+xml</type>
        <type>image/svg+xml</type>
        <type>application/x-eliom</type>
      </deflate>
    </host>
  </server>
</ocsigen>

Eliom and Ocsigen Start have also been updated for being used without configuration file and will be released very soon.

15 Likes