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 :
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 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.