Context
I often try to develop micro projects with Ocsigen. They are Quick and Dirty things without coplexity, just needing an admin login and deveral things.
I mostly start with this Project Template, and clean it the step after.
My Ocsigen Project template
Its composed by:
- A main file: index.ml
- An utility file: gs.ml
- A Makefile
- Some tuning to the Ocsigen cofiguration file
- Some Debian/Ubuntu packages installed
The main File
open Lwt open XHTML.M open Eliom_services open Eliom_parameters open Eliom_sessions open Eliom_predefmod.Xhtml open Gs module Ep=Eliom_parameters;; let session_table = Eliom_sessions.create_volatile_table ();; let root_service = Eliom_services.new_service ~path:[""] ~get_params:Eliom_parameters.unit () ;; let root_service_with_post = Eliom_services.new_post_service ~fallback:root_service ~post_params:((Ep.string "login")**(Ep.string "password")) () ;; let logout_service = Eliom_services.new_service ~path:["logout"] ~get_params:Eliom_parameters.unit () ;; (* Handlers *) let root_handler sp _ _ = let session_data = Eliom_sessions.get_volatile_session_data ~table:session_table ~sp:sp () in match session_data with Eliom_sessions.Data (name,password) -> return (html (head (title (pcdata "Accueil")) []) (body [(Gs.greeter_auth logout_service sp (name,password))])) ; | Eliom_sessions.Data_session_expired | Eliom_sessions.No_data -> return (Gs.login_page root_service_with_post sp "Accueil") ;; let root_handler_with_post sp _ (login,password) = let clean_login = Gs.trim login in match (Gs.ok_credentials (clean_login, password)) with | true -> Lwt.bind (Eliom_sessions.close_session ~sp:sp ()) (fun () -> Eliom_sessions.set_volatile_session_data ~table:session_table ~sp:sp (clean_login, password); return (html (head (title (pcdata "Identifié")) []) (body [Gs.greeter_auth logout_service sp (clean_login,password)]))) ; | false -> return (Gs.login_page root_service_with_post sp "Recommencez SVP");; let logout_handler sp () () = Lwt.bind (Eliom_sessions.close_session ~sp:sp ()) (fun () -> return (Gs.login_page root_service_with_post sp "Deconnecté")) ;; let () = Eliom_predefmod.Xhtml.register root_service root_handler; Eliom_predefmod.Xhtml.register root_service_with_post root_handler_with_post; Eliom_predefmod.Xhtml.register logout_service logout_handler;;
The utility File
open Lwt open XHTML.M open Eliom_services open Eliom_parameters open Eliom_sessions open Eliom_predefmod.Xhtml (* #use"topfind";; #require"mysql";; #require"str";; *) open Str open Mysql module Ep = Eliom_predefmod;; let trim the_input = let space_regexp = Str.regexp " +" and semicolumn_regexp = Str.regexp ";" and replace = Str.global_replace in replace semicolumn_regexp "" (* Remplacement des point-virgules *) (replace space_regexp "" the_input);; (* et des espaces. anti-problemes *) let semicolumn_regexp = Str.regexp ";";; let ok_credentials (u,p) = match (u,p) with | ("admin","sdlqskd6dsf") -> true; | _ -> false;; (* begin HTML constructions *) let greeter_auth close_serv server_params (login, password)= p [pcdata ("Bienvenue, titulaire de l'adresse "^login^"."); br (); (Eliom_predefmod.Xhtml.a close_serv server_params [pcdata "Se déconnecter."] ()); ] ;; let login_page attached_serv server_params titre= let login_form = Eliom_predefmod.Xhtml.post_form attached_serv server_params (fun (login, password) -> [p [pcdata "Identifiant:"; (Eliom_predefmod.Xhtml.string_input ~input_type:`Text ~name:login ()); br (); pcdata "Mot de passe"; (Eliom_predefmod.Xhtml.string_input ~input_type:`Text ~name:password ()); br (); (Eliom_predefmod.Xhtml.string_input ~value:"S'identifier" ~input_type:`Submit ())]]) () in (html (head (title (pcdata titre)) []) (body [login_form]));; (* end HTML constructions *)
The MakeFile
######## # ocamlfind ocamlc -verbose -package str,ocsigen,postgresql,mysql -linkpkg LAPTOP_FLAGS= -I /usr/lib/ocaml/pcre -ccopt -I/usr/lib/ocaml/pcre \ -I /usr/lib/ocaml/netsys -ccopt -I/usr/lib/ocaml/netsys \ -I /usr/lib/ocaml/netstring -ccopt -I/usr/lib/ocaml/netstring \ -I /usr/lib/ocaml/ssl -ccopt -I/usr/lib/ocaml/ssl \ -I /usr/lib/ocaml/lwt -ccopt -I/usr/lib/ocaml/lwt \ -I /usr/lib/ocaml/ocsigen -ccopt -I/usr/lib/ocaml/ocsigen \ -I /usr/lib/ocaml/postgresql -ccopt -I/usr/lib/ocaml/postgresql \ -I /usr/lib/ocaml/mysql -ccopt -I/usr/lib/ocaml/mysql \ -ccopt -L/usr/lib/ocaml/pcre \ -ccopt -L/usr/lib/ocaml/netsys \ -ccopt -L/usr/lib/ocaml/netstring \ -ccopt -L/usr/lib/ocaml/ssl \ -ccopt -L/usr/lib/ocaml/lwt \ -ccopt -L/usr/lib/ocaml/ocsigen \ -ccopt -L/usr/lib/ocaml/postgresql \ -ccopt -L/usr/lib/ocaml/mysql \ /usr/lib/ocaml/unix.cma \ /usr/lib/ocaml/threads/threads.cma \ /usr/lib/ocaml/str.cma \ /usr/lib/ocaml/pcre/pcre.cma \ /usr/lib/ocaml/netsys/netsys.cma \ /usr/lib/ocaml/netstring/netstring.cma \ /usr/lib/ocaml/netstring/netstring_mt.cmo \ /usr/lib/ocaml/netstring/netaccel.cma \ /usr/lib/ocaml/netstring/netaccel_link.cmo \ /usr/lib/ocaml/ssl/ssl_threads.cma \ /usr/lib/ocaml/dynlink.cma \ /usr/lib/ocaml/lwt/lwt.cma \ /usr/lib/ocaml/postgresql/postgresql.cma \ /usr/lib/ocaml/mysql/mysql.cma OCAMLC = ocamlc -c -thread gs: $(OCAMLC) $(LAPTOP_FLAGS) gs.ml index: gs $(OCAMLC) $(LAPTOP_FLAGS) gs.cmo index.ml all: gs index echo "all OK"
The Ocsigen configuration file
Load the modules listed in the Makefile<<extension module="/usr/lib/ocaml/str.cma"/>> <<extension module="/usr/lib/ocaml/pcre/pcre.cma"/>> <<extension module="/usr/lib/ocaml/netsys/netsys.cma"/>> <<extension module="/usr/lib/ocaml/netstring/netstring.cma"/>> <<extension module="/usr/lib/ocaml/netstring/netstring_mt.cmo"/>> <<extension module="/usr/lib/ocaml/netstring/netaccel.cma"/>> <<extension module="/usr/lib/ocaml/netstring/netaccel_link.cmo"/>> <<extension module="/usr/lib/ocaml/ssl/ssl.cma"/>> <<extension module="/usr/lib/ocaml/ssl/ssl_threads.cma"/>> <<extension module="/usr/lib/ocaml/dynlink.cma"/>> <<extension module="/usr/lib/ocaml/react/react.cmo"/>> <<extension module="/usr/lib/ocaml/lwt/lwt.cma"/>> <<extension module="/usr/lib/ocaml/nums.cma"/>> <<extension module="/usr/lib/ocaml/toplevellib.cma"/>> <<extension module="/usr/lib/ocaml/ocamldap/ocamldap.cma"/>> <<extension module="/usr/lib/ocaml/mysql/mysql.cma"/>> <<extension module="/usr/lib/ocaml/postgresql/postgresql.cma"/>>Declare the host
<<host defaulthostname="xxxxxxx">> <<site path="">> <<static dir="/home/mihamina/XXXXXXXX/static/" />> <<eliom module="/home/mihamina/XXXXXXX/index.cmo" />> <</site>> <</host>>
Installed packages
Got with:dpkg -l | awk '/^ii.+(ocaml|make|ocsigen)/{print $2}'
automake libcryptgps-ocaml-dev libcryptokit-ocaml libcryptokit-ocaml-dev libfindlib-ocaml libfindlib-ocaml-dev libldap-ocaml-dev liblwt-ocaml liblwt-ocaml-dev liblwt-ocaml-doc liblwt-ssl-ocaml-dev libmysql-ocaml libmysql-ocaml-dev libnethttpd-ocaml-dev libobrowser-ocaml-dev libocamlnet-ocaml libocamlnet-ocaml-dev libocamlnet-ocaml-doc libocsigen-ocaml libocsigen-ocaml-dev libocsigen-ocaml-doc libocsigen-xhtml-ocaml-dev libpcre-ocaml libpcre-ocaml-dev libpostgresql-ocaml libpostgresql-ocaml-dev libreact-ocaml libreact-ocaml-dev libsqlite3-ocaml libsqlite3-ocaml-dev libssl-ocaml libssl-ocaml-dev libtext-ocaml libtext-ocaml-dev libzip-ocaml libzip-ocaml-dev make makedev ocaml-base-nox ocaml-findlib ocaml-interp ocaml-nox ocamlduce ocamlduce-base ocsigen ocsigen-dev