You are currently browsing the archives for the cgi tag.

Using OCaml to write web scripts - 2

Yesterday I have explained how to use an OCaml .ml script as an executable, and how to display a web page written in OCaml. I'll explain here how to parse a querystring.

The querystring is passed as the environment variable QUERY_STRING. I'll use the following module to fetch the querystring and parse it :

module Get =
  struct
    let query_string = try String.lowercase (Sys.getenv "QUERY_STRING") with
    Not_found -> ""

    let _Hash =
      let return = Hashtbl.create 23 in
      let rec split c = function
          "" -> []
        |s when s.[0] = c -> ""::(split c (String.sub s 1 ((String.length s)-1)))
        |s ->
          begin
            match (split c (String.sub s 1 ((String.length s)-1))) with
               [] -> [String.make 1 (s.[0])]
            |t::q -> ((String.make 1 (s.[0]))^t)::q
          end
      in
      let query_list = split ‘&’ query_string in
      let rec q2h = function
        [] -> ()
       |t::q ->  (
         q2h q;
         match (split ‘=’ t) with
            [] -> ()
          | arg::[] -> Hashtbl.add return arg ""
          | arg::value::_ -> Hashtbl.add return arg value;) in
      q2h query_list;
      return
    let arg x = try Hashtbl.find _Hash x with Not_found -> ""
    let iter f = Hashtbl.iter f _Hash
  end

This is a simple module which allows us to do some simple stuff. Speeking of which, here is a simple example :

let e s = print_string s

let print_arg_val x y = e ("<i>"^x^"</i> : "^y^"<br/>\n")

let fibo n =
  try
    let rec fibo = function
      0 -> 1
     |1 -> 1
     |n -> fibo (n-1) + fibo (n-2)
    in
    string_of_int (fibo (int_of_string n))
  with _ -> ""

let _ =
  e "Content-type: text/html\n\n";

  e "<a href=\"test.ml?arg1=val1&arg2=val2&arg3=val3&n=15\">Examples</a><br/><br/>\n";
 
  e "<b>Get.query_string</b> : <br/>\n";
  e (Get.query_string^"<br/>\n");
  e "<br/>\n";

  e "<b>Get.arg \"arg2\"</b> : <br/>\n ";
  e ((Get.arg "arg2")^"<br/>\n");
  e "<br/>\n";

  e "<b>fibo (Get.arg \"n\")</b> :<br/>\n";
  e (fibo (Get.arg "n"));
  e "<br/>\n";
  e "<br/>\n";

  e "<b>Get.iter print_arg_val</b> : <br/>\n";
  Get.iter print_arg_val;

Those are only simple examples, and there are a lot of things to improve in order to use this in a real website (for example the conversion of url encoded characters, etc.).

But as I stated previously, I did not aim to write a CGI module for OCaml : use ocamlcgi instead, this one was really written to be used in real life.

Moreover, the following module might be useful if you want to plug a MySQL database to a web app writtent in ocaml : ocaml-mysql.

Last, by using camlp4, it should be possible to write scripts which look more like some PHP, using (for example) this kind of syntax : <?caml () ?> (everything which is not between those should just be sent of the output).

As a conclusion, it is possible to write dynamic web pages in OCaml, but is it really useful ? OCaml's strong typing can be a real pain in such context (no

echo

function ala PHP, etc.) but someone might find something useful to it.

Downloaded : 77 times
File : ocaml_script_cgi.tar.gz
Size: 1.3 ko

Using OCaml to write web scripts

OCaml is a language in which you can do anyything. That's why I decided to use it to write CGI scripts. While it is really easy to use compiled code as a CGI, it is far less simple to use scripts.

Executable ML

Let's start with a very simple script :

print_endline "Hello OCaml !";

Basically, a ml file is not an executable, this can be is achieved in two phases, first a chmod + x on the file, and then we add the following lines in the header file:

#!/bin/sh
#(*
exec ocaml "$0" "$@"
*)
warnings "A";;

print_endline "Hello OCaml !";;

The shabang indicates that the interpreter to be used is /bin/sh (nothing new here).

The following three lines are an elegant trick: on the second line, # tells bash that the line is a comment, so it jumps to the new line and calls the toplevel, passing as arguments the name of the script and the rest of the command line.

On the OCaml side, everything which is between (* *) is considered as a comment : OCaml understands the second line as #warnings "A" which is used to display all warnings (alternatively, one can use #wargins "a" to hide all warnings)

Now one can test it by calling ./test.ml

A page saying "Hello OCaml"

The first thing to do is to tell Apache how .ml file should be dealt with, which is achieved by adding the following line to the .htaccess :

AddType cgi-script ml

Those know Python or Perl won't be suprised, we have to modify slightly our script in order to send the correct headers :

#!/bin/sh
#(*
exec ocaml "$0" "$@"
*)
warnings "A";;

print_string "Content-type: text/html\n\n";
print_endline "Hello OCaml !";;

Just check it in your browser ;)