1 (* Eliom test suite, part 1 *)
2 (* TODO: extract the tests from the manual or vice versa.
3 Take the code in the manual, not here! (and remove duplicates here) *)
4 (* TODO: include some missing parts in the manual *)
12 open Eliom_output.Xhtml
21 (head
(title
(pcdata
"")) [])
22 (body
[h1
[pcdata
"Hallo!"]])))
25 Eliom_output.Xhtml.register_service
27 ~get_params
:Eliom_parameters.unit
31 <head
><title
></title
></head
>
32 <body
><h1
>Coucou
</h1
></body
>
36 Eliom_output.HtmlText.register_service
38 ~get_params
:Eliom_parameters.unit
41 ("<html>n'importe quoi "^
42 (Eliom_output.HtmlText.a
coucou "clic" ())^
46 Page generation may have side-effects:
54 (fun () -> c := !c + 1; !c)
62 (head
(title
(pcdata
"counter")) [])
63 (body
[p
[pcdata
(string_of_int
(next ()))]])))
65 As usual in OCaml, you can forget labels when the application
71 ["dir";"hello"] (* the url dir/hello *)
76 (head
(title
(pcdata
"Hello")) [])
77 (body
[h1
[pcdata
"Hello"]])))
80 The following example shows how to define the default page for
81 a directory. (Note that %<span class="code"|["rep";""]>% means
82 the default page of the directory %<span class="code"|rep/>%)
85 let default = register_service
["rep";""] unit
89 (head
(title
(pcdata
"")) [])
90 (body
[p
[pcdata
"default page. rep is redirected to rep/"]])))
94 let writeparams (i1
, (i2
, s1
)) () =
97 (head
(title
(pcdata
"")) [])
98 (body
[p
[pcdata
"You sent: ";
99 strong
[pcdata
(string_of_int i1
)];
101 strong
[pcdata
(string_of_int i2
)];
103 strong
[pcdata s1
]]]))
104 (*zap* you can register twice the same service, with different parameter names
106 let coucou_params = register_service
108 ~get_params
:(int "i" ** (int "ii" ** string "s"))
110 (*zap* If you register twice exactly the same URL, the server won't start
120 ~get_params
:(suffix
(int "year" ** int "month"))
121 (fun (year
, month
) () ->
124 (head
(title
(pcdata
"")) [])
126 [p
[pcdata
"The suffix of the url is ";
127 strong
[pcdata
((string_of_int year
)^
"/"
128 ^
(string_of_int month
))];
129 pcdata
", your user-agent is ";
130 strong
[pcdata
(Eliom_request_info.get_user_agent
())];
131 pcdata
", your IP is ";
132 strong
[pcdata
(Eliom_request_info.get_remote_ip
())]]])))
139 ~get_params
:(suffix_prod
(int "suff" ** all_suffix
"endsuff") (int "i"))
140 (fun ((suff
, endsuff
), i
) () ->
143 (head
(title
(pcdata
"")) [])
145 [p
[pcdata
"The suffix of the url is ";
146 strong
[pcdata
(string_of_int suff
)];
147 pcdata
" followed by ";
148 strong
[pcdata
(Url.string_of_url_path ~encode
:false endsuff
)];
149 pcdata
" and i is equal to ";
150 strong
[pcdata
(string_of_int i
)]]])))
158 ~get_params
:(suffix
(string "s1" ** (Eliom_parameters.suffix_const
"toto" ** string "s2")))
159 (fun (s1
, ((), s2
)) () ->
162 (head
(title
(pcdata
"")) [])
164 [pcdata
"Suffix with constants"];
165 p
[pcdata
("Parameters are "^s1^
" and "^s2
)]])))
171 let mysum_of_string = function
174 | _
-> raise
(Failure
"mysum_of_string")
175 let string_of_mysum = function
180 Eliom_output.Xhtml.register_service
183 (Eliom_parameters.user_type
mysum_of_string string_of_mysum "valeur")
185 let v = string_of_mysum x
in
188 (head
(title
(pcdata
"")) [])
189 (body
[p
[pcdata
(v^
" is valid. Now try with another value.")]])))
194 let raw_serv = register_service
196 ~get_params
:Eliom_parameters.any
200 (fun (a
,s
) -> <:xhtml
< <strong
>($str
:a$
, $str
:s$
)</strong
> >>) l
204 <head
><title
></title
></head
>
216 let catch = register_service
218 ~get_params
:(int "i")
219 ~error_handler
:(fun l
->
222 (head
(title
(pcdata
"")) [])
223 (body
[p
[pcdata
("i is not an integer.")]])))
225 let v = string_of_int i
in
228 (head
(title
(pcdata
"")) [])
229 (body
[p
[pcdata
("i is an integer: "^
v)]])))
234 let links = register_service
["rep";"links"] unit
238 (head
(title
(pcdata
"Links")) [])
241 [Eliom_output.Xhtml.a
coucou [pcdata
"coucou"] (); br
();
242 Eliom_output.Xhtml.a
hello [pcdata
"hello"] (); br
();
243 Eliom_output.Xhtml.a
default
244 [pcdata
"default page of the dir"] (); br
();
245 Eliom_output.Xhtml.a
uasuffix
246 [pcdata
"uasuffix"] (2007,06); br
();
247 Eliom_output.Xhtml.a
coucou_params
248 [pcdata
"coucou_params"] (42,(22,"ciao")); br
();
249 Eliom_output.Xhtml.a
raw_serv
250 [pcdata
"raw_serv"] [("sun","yellow");("sea","blue and pink")]; br
();
253 ~prefix
:"http://fr.wikipedia.org"
255 ~get_params
:(suffix
(all_suffix
"suff"))
257 [pcdata
"OCaml on wikipedia"]
260 ~a
:[a_href
(Uri.uri_of_string
"http://en.wikipedia.org/wiki/OCaml")]
261 [pcdata
"OCaml on wikipedia"]
264 Note that to create a link we need to know the current url, because:
265 the link from toto/titi to toto/tata is "tata" and not "toto/tata"
272 let linkrec = Eliom_services.service
["linkrec"] unit ()
274 let _ = Eliom_output.Xhtml.register
linkrec
278 (head
(title
(pcdata
"")) [])
279 (body
[p
[a
linkrec [pcdata
"click"] ()]])))
280 (*zap* If some url are not registered, the server will not start:
284 ~server_params:no_server_param
285 ~get_params:no_get_param
288 (*zap* pour les reload : le serveur ne s'éteint pas mais ajoute un message sur les services non enregistrés dans son log *zap*)
294 (fun (number_name
, (number2_name
, string_name
)) ->
295 [p
[pcdata
"Write an int: ";
296 Eliom_output.Xhtml.int_input ~input_type
:`Text ~name
:number_name
();
297 pcdata
"Write another int: ";
298 Eliom_output.Xhtml.int_input ~input_type
:`Text ~name
:number2_name
();
299 pcdata
"Write a string: ";
300 Eliom_output.Xhtml.string_input ~input_type
:`Text ~name
:string_name
();
301 Eliom_output.Xhtml.string_input ~input_type
:`Submit ~
value:"Click" ()]])
303 let form = register_service
["form"] unit
305 let f = Eliom_output.Xhtml.get_form
coucou_params create_form in
308 (head
(title
(pcdata
"")) [])
313 let raw_form = register_service
319 (head
(title
(pcdata
"")) [])
321 [h1
[pcdata
"Any Form"];
322 Eliom_output.Xhtml.get_form
raw_serv
324 [p
[pcdata
"Form to raw_serv: ";
325 Eliom_output.Xhtml.raw_input ~input_type
:`Text ~name
:"plop" ();
326 Eliom_output.Xhtml.raw_input ~input_type
:`Text ~name
:"plip" ();
327 Eliom_output.Xhtml.raw_input ~input_type
:`Text ~name
:"plap" ();
328 Eliom_output.Xhtml.string_input ~input_type
:`Submit ~
value:"Click" ()]])
335 let no_post_param_service =
342 (head
(title
(pcdata
"")) [])
344 "Version of the page without POST parameters"]])))
346 let my_service_with_post_params =
347 register_post_service
348 ~fallback
:no_post_param_service
349 ~post_params
:(string "value")
353 (head
(title
(pcdata
"")) [])
354 (body
[h1
[pcdata
value]])))
360 Services may take both GET and POST parameters:
364 let get_no_post_param_service =
367 ~get_params
:(int "i")
371 (head
(title
(pcdata
"")) [])
372 (body
[p
[pcdata
"No POST parameter, i:";
373 em
[pcdata
(string_of_int i
)]]])))
375 let my_service_with_get_and_post = register_post_service
376 ~fallback
:get_no_post_param_service
377 ~post_params
:(string "value")
381 (head
(title
(pcdata
"")) [])
382 (body
[p
[pcdata
"Value: ";
385 em
[pcdata
(string_of_int i
)]]])))
391 let form2 = register_service
["form2"] unit
394 (Eliom_output.Xhtml.post_form
my_service_with_post_params
396 [p
[pcdata
"Write a string: ";
397 string_input ~input_type
:`Text ~name
:chaine
()]]) ()) in
400 (head
(title
(pcdata
"form")) [])
403 let form3 = register_service
["form3"] unit
406 (Eliom_output.Xhtml.post_form
my_service_with_get_and_post
408 <:xhtmllist
< <p
> Write a
string:
409 $string_input ~input_type
:`Text ~name
:chaine
()$
</p
> >>)
413 <head
><title
></title
></head
>
414 <body
>$
f$
</body
></html
> >>)
416 let form4 = register_service
["form4"] unit
419 (Eliom_output.Xhtml.post_form
420 (external_post_service
421 ~prefix
:"http://www.petizomverts.com"
423 ~get_params
:(int "i")
424 ~post_params
:(string "chaine") ())
426 <:xhtmllist
< <p
> Write a
string:
427 $string_input ~input_type
:`Text ~name
:chaine
()$
</p
> >>)
431 (head
(title
(pcdata
"form")) [])
438 %<code language="ocaml"|let looong =
446 (head (title (pcdata "")) [])
447 (body [h1 [pcdata "Ok now, you can read the page."]])))
458 Lwt_unix.sleep
5.0 >>= fun () ->
461 (head
(title
(pcdata
"")) [])
463 "Ok now, you can read the page."]])))
472 Lwt_preemptive.detach
Unix.sleep
5 >>= fun () ->
475 (head
(title
(pcdata
"")) [])
477 "Ok now, you can read the page."]])))
482 (************************************************************)
483 (************ Connection of users, version 1 ****************)
484 (************************************************************)
487 let scope_name = Eliom_common.create_scope_name
"session_data"
488 let session = `Session
scope_name
491 (* "my_table" will be the structure used to store
492 the session data (namely the login name): *)
494 let my_table = Eliom_state.create_volatile_table
(*zap* *) ~scope
:session (* *zap*) ()
497 (* -------------------------------------------------------- *)
498 (* Create services, but do not register them yet: *)
500 let session_data_example =
501 Eliom_services.service
503 ~get_params
:Eliom_parameters.unit
506 let session_data_example_with_post_params =
507 Eliom_services.post_service
508 ~fallback
:session_data_example
509 ~post_params
:(Eliom_parameters.string "login")
512 let session_data_example_close =
513 Eliom_services.service
515 ~get_params
:Eliom_parameters.unit
520 (* -------------------------------------------------------- *)
521 (* Handler for the "session_data_example" service: *)
523 let session_data_example_handler _ _ =
524 let sessdat = Eliom_state.get_volatile_data ~table
:my_table () in
527 (head
(title
(pcdata
"")) [])
531 | Eliom_state.Data name
->
532 p
[pcdata
("Hello "^name
);
535 session_data_example_close
536 [pcdata
"close session"] ()]
537 | Eliom_state.Data_session_expired
538 | Eliom_state.No_data
->
539 Eliom_output.Xhtml.post_form
540 session_data_example_with_post_params
542 [p
[pcdata
"login: ";
543 Eliom_output.Xhtml.string_input
544 ~input_type
:`Text ~name
:login
()]]) ()
547 (* -------------------------------------------------------- *)
548 (* Handler for the "session_data_example_with_post_params" *)
549 (* service with POST params: *)
551 let session_data_example_with_post_params_handler _ login
=
552 lwt
() = Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) () in
553 Eliom_state.set_volatile_data ~table
:my_table login
;
556 (head
(title
(pcdata
"")) [])
558 [p
[pcdata
("Welcome " ^ login ^
". You are now connected.");
560 Eliom_output.Xhtml.a
session_data_example
561 [pcdata
"Try again"] ()
566 (* -------------------------------------------------------- *)
567 (* Handler for the "session_data_example_close" service: *)
569 let session_data_example_close_handler () () =
570 let sessdat = Eliom_state.get_volatile_data ~table
:my_table () in
571 lwt
() = Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) () in
574 (head
(title
(pcdata
"Disconnect")) [])
577 | Eliom_state.Data_session_expired
-> p
[pcdata
"Your session has expired."]
578 | Eliom_state.No_data
-> p
[pcdata
"You were not connected."]
579 | Eliom_state.Data
_ -> p
[pcdata
"You have been disconnected."]);
580 p
[Eliom_output.Xhtml.a
session_data_example [pcdata
"Retry"] () ]]))
583 (* -------------------------------------------------------- *)
584 (* Registration of main services: *)
587 Eliom_output.Xhtml.register
588 session_data_example_close session_data_example_close_handler;
589 Eliom_output.Xhtml.register
590 session_data_example session_data_example_handler;
591 Eliom_output.Xhtml.register
592 session_data_example_with_post_params
593 session_data_example_with_post_params_handler
601 let () = set_default_global_service_state_timeout ~cookie_scope
:`Session
(Some
600.)
602 let () = set_default_global_persistent_data_state_timeout ~cookie_scope
:`Session
(Some
3600.)
604 (************************************************************)
605 (************ Connection of users, version 2 ****************)
606 (************************************************************)
609 let scope_name = Eliom_common.create_scope_name
"session_services"
610 let session = `Session
scope_name
612 (* -------------------------------------------------------- *)
613 (* Create services, but do not register them yet: *)
615 let session_services_example =
616 Eliom_services.service
617 ~path
:["sessionservices"]
618 ~get_params
:Eliom_parameters.unit
621 let session_services_example_with_post_params =
622 Eliom_services.post_service
623 ~fallback
:session_services_example
624 ~post_params
:(Eliom_parameters.string "login")
627 let session_services_example_close =
628 Eliom_services.service
630 ~get_params
:Eliom_parameters.unit
634 (* ------------------------------------------------------------- *)
635 (* Handler for the "session_services_example" service: *)
636 (* It displays the main page of our site, with a login form. *)
638 let session_services_example_handler () () =
640 Eliom_output.Xhtml.post_form
641 session_services_example_with_post_params
643 [p
[pcdata
"login: ";
644 string_input ~input_type
:`Text ~name
:login
()]]) ()
648 (head
(title
(pcdata
"")) [])
652 (* ------------------------------------------------------------- *)
653 (* Handler for the "session_services_example_close" service: *)
655 let session_services_example_close_handler () () =
656 lwt
() = Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) () in
659 (head
(title
(pcdata
"Disconnect")) [])
660 (body
[p
[pcdata
"You have been disconnected. ";
661 a
session_services_example
668 When the page is called with login parameters,
669 it runs the function %<span class="code"|launch_session>%
670 that replaces some services already defined by new ones:
675 (* ------------------------------------------------------------- *)
676 (* Handler for the "session_services_example_with_post_params" *)
679 let launch_session () login
=
681 (* New handler for the main page: *)
682 let new_main_page () () =
685 (head
(title
(pcdata
"")) [])
686 (body
[p
[pcdata
"Welcome ";
689 a
coucou [pcdata
"coucou"] (); br
();
690 a
hello [pcdata
"hello"] (); br
();
691 a
links [pcdata
"links"] (); br
();
692 a
session_services_example_close
693 [pcdata
"close session"] ()]]))
696 (* If a session was opened, we close it first! *)
697 lwt
() = Eliom_state.discard ~scope
:session () in
699 (* Now we register new versions of main services in the
700 session service table: *)
701 Eliom_output.Xhtml.register ~scope
:session
702 ~service
:session_services_example
703 (* service is any public service already registered,
704 here the main page of our site *)
707 Eliom_output.Xhtml.register ~scope
:session
712 (head
(title
(pcdata
"")) [])
713 (body
[p
[pcdata
"Coucou ";
717 Eliom_output.Xhtml.register ~scope
:session
722 (head
(title
(pcdata
"")) [])
723 (body
[p
[pcdata
"Ciao ";
729 (* -------------------------------------------------------- *)
730 (* Registration of main services: *)
733 Eliom_output.Xhtml.register
734 ~service
:session_services_example
735 session_services_example_handler;
736 Eliom_output.Xhtml.register
737 ~service
:session_services_example_close
738 session_services_example_close_handler;
739 Eliom_output.Xhtml.register
740 ~service
:session_services_example_with_post_params
742 (*zap* Registering for session during initialisation is forbidden:
743 let _ = register ~scope:`Session
746 <head><title></title></head>
747 <body><h1>humhum</h1></body>
754 (************************************************************)
755 (************** Coservices. Basic examples ******************)
756 (************************************************************)
758 (* -------------------------------------------------------- *)
759 (* We create one main service and two coservices: *)
761 let coservices_example =
762 Eliom_services.service
764 ~get_params
:Eliom_parameters.unit
767 let coservices_example_post =
768 Eliom_services.post_coservice
769 ~fallback
:coservices_example
770 ~post_params
:Eliom_parameters.unit
773 let coservices_example_get =
774 Eliom_services.coservice
775 ~fallback
:coservices_example
776 ~get_params
:Eliom_parameters.unit
780 (* -------------------------------------------------------- *)
781 (* The three of them display the same page, *)
782 (* but the coservices change the counter. *)
787 let l3 = Eliom_output.Xhtml.post_form
coservices_example_post
788 (fun _ -> [p
[Eliom_output.Xhtml.string_input
790 ~
value:"incr i (post)" ()]]) ()
792 let l4 = Eliom_output.Xhtml.get_form
coservices_example_get
793 (fun _ -> [p
[Eliom_output.Xhtml.string_input
795 ~
value:"incr i (get)" ()]])
799 (head
(title
(pcdata
"")) [])
800 (body
[p
[pcdata
"i is equal to ";
801 pcdata
(string_of_int
!c); br
();
802 a
coservices_example [pcdata
"reload"] (); br
();
803 a
coservices_example_get [pcdata
"incr i"] ()];
807 Eliom_output.Xhtml.register
coservices_example page;
808 let f () () = c := !c + 1; page () () in
809 Eliom_output.Xhtml.register
coservices_example_post f;
810 Eliom_output.Xhtml.register
coservices_example_get f
815 %<div class="encadre"|
819 While designing a Web site, think carefully about the URLs you
820 want to use. URLs are the entry points of your site. Think that
821 they may be bookmarked. If you create a link, you want to go to
822 another URL, and you want a page to be generated. That page may be
823 the default page for the URL (the one you get when you go back
824 to a bookmarked page), or another page, that depends on the precise
825 link or form you used to go to that URL (link to a coservice,
826 or page depending on post data).
827 Sometimes, you want that clicking
828 a link or submitting a form does something without changing the URL.
829 You can do this using //non-attached coservices// (see below).
834 %<div class="encadre"|
838 Eliom is using the concept of //continuation//.
839 A continuation represents the future of a program (what to do after).
840 When a user clicks on a link or a form, he chooses the future of the
841 computation. When he uses the "back" button of the browser, he chooses
842 to go back to an old continuation. Continuations for Web programming
843 have been introduced by
844 [[http://www-spi.lip6.fr/%7Equeinnec/PDF/www.pdf| Christian Queinnec]],
845 and are a big step in
846 the understanding of Web interaction.
850 Some programming languages (Scheme...) allow to manipulate
851 continuations using //control operators// (like
852 %<span class="code"|call/cc>%). The style of programming used by Eliom
853 is closer to //Continuation Passing Style// (CPS), and has the
854 advantage that it does not need control operators, and fits
855 very well Web programming.
860 Coservices allow to create dynamically
861 new continuations that depend on previous interactions with users
862 ([[manual/dev/2#p2calc|See the %<span class="code"|calc>% example below]]).
863 Such a behaviour is difficult to simulate with traditional Web
871 (*zap* Queinnec example: *zap*)
872 (************************************************************)
873 (*************** calc: sum of two integers ******************)
874 (************************************************************)
877 let calc_example_scope_name = Eliom_common.create_scope_name
"calc_example"
878 let session = `Session
calc_example_scope_name
879 let session_group = `Session_group
calc_example_scope_name
881 (* -------------------------------------------------------- *)
882 (* We create two main services on the same URL, *)
883 (* one with a GET integer parameter: *)
894 ~get_params
:(int "i")
898 (* -------------------------------------------------------- *)
899 (* The handler for the service without parameter. *)
900 (* It displays a form where you can write an integer value: *)
902 let calc_handler () () =
903 let create_form intname
=
904 [p
[pcdata
"Write a number: ";
905 Eliom_output.Xhtml.int_input ~input_type
:`Text ~name
:intname
();
907 Eliom_output.Xhtml.string_input ~input_type
:`Submit ~
value:"Send" ()]]
909 let f = Eliom_output.Xhtml.get_form
calc_i create_form in
912 (head
(title
(pcdata
"")) [])
916 (* -------------------------------------------------------- *)
917 (* The handler for the service with parameter. *)
918 (* It creates dynamically and registers a new coservice *)
919 (* with one GET integer parameter. *)
920 (* This new coservice depends on the first value (i) *)
921 (* entered by the user. *)
923 let calc_i_handler i
() =
926 [p
[pcdata
(is^
" + ");
927 int_input ~input_type
:`Text ~name
:entier
();
929 string_input ~input_type
:`Submit ~
value:"Sum" ()]])
931 let is = string_of_int i
in
933 register_coservice ~scope
:Eliom_common.session
935 ~get_params
:(int "j")
937 let js = string_of_int j
in
938 let ijs = string_of_int
(i
+j
) in
941 (head
(title
(pcdata
"")) [])
943 [p
[pcdata
(is^
" + "^
js^
" = "^
ijs)]])))
945 let f = get_form
calc_result (create_form is) in
948 (head
(title
(pcdata
"")) [])
952 (* -------------------------------------------------------- *)
953 (* Registration of main services: *)
956 Eliom_output.Xhtml.register
calc calc_handler;
957 Eliom_output.Xhtml.register
calc_i calc_i_handler
962 (************************************************************)
963 (************ Connection of users, version 3 ****************)
964 (************************************************************)
967 let connect_example3_scope_name = Eliom_common.create_scope_name
"connect_example3"
968 let session = `Session
connect_example3_scope_name
969 let session_group = `Session_group
connect_example3_scope_name
970 let my_table = Eliom_state.create_volatile_table
(*zap* *) ~scope
:session (* *zap*) ()
972 (* -------------------------------------------------------- *)
973 (* We create one main service and two (POST) actions *)
974 (* (for connection and disconnection) *)
976 let connect_example3 =
977 Eliom_services.service
979 ~get_params
:Eliom_parameters.unit
983 Eliom_services.post_coservice'
985 ~post_params
:(Eliom_parameters.string "login")
988 (* As the handler is very simple, we register it now: *)
989 let disconnect_action =
990 Eliom_output.Action.register_post_coservice'
992 ~post_params
:Eliom_parameters.unit
994 Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) ())
997 (* -------------------------------------------------------- *)
998 (* login ang logout boxes: *)
1000 let disconnect_box s
=
1001 Eliom_output.Xhtml.post_form
disconnect_action
1002 (fun _ -> [p
[Eliom_output.Xhtml.string_input
1003 ~input_type
:`Submit ~
value:s
()]]) ()
1006 Eliom_output.Xhtml.post_form
connect_action
1009 (let l = [pcdata
"login: ";
1010 Eliom_output.Xhtml.string_input
1011 ~input_type
:`Text ~name
:loginname
()]
1017 (* -------------------------------------------------------- *)
1018 (* Handler for the "connect_example3" service (main page): *)
1020 let connect_example3_handler () () =
1021 let sessdat = Eliom_state.get_volatile_data ~table
:my_table () in
1024 (head
(title
(pcdata
"")) [])
1027 | Eliom_state.Data name
->
1028 [p
[pcdata
("Hello "^name
); br
()];
1029 disconnect_box "Close session"]
1030 | Eliom_state.Data_session_expired
1031 | Eliom_state.No_data
-> [login_box ()]
1035 (* -------------------------------------------------------- *)
1036 (* Handler for connect_action (user logs in): *)
1038 let connect_action_handler () login
=
1039 lwt
() = Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) () in
1040 Eliom_state.set_volatile_data ~table
:my_table login
;
1044 (* -------------------------------------------------------- *)
1045 (* Registration of main services: *)
1048 Eliom_output.Xhtml.register ~service
:connect_example3 connect_example3_handler;
1049 Eliom_output.Action.register ~service
:connect_action connect_action_handler
1055 Eliom_output.Blocks.register_service
1060 [div
[h2
[pcdata
"Hallo"];
1061 p
[pcdata
"Blablablabla"] ]])
1066 let redir1 = Eliom_output.Redirection.register_service
1069 ~get_params
:Eliom_parameters.unit
1070 (fun () () -> Lwt.return
coucou)
1074 let redir = Eliom_output.Redirection.register_service
1077 ~get_params
:(int "o")
1080 (Eliom_services.preapply
coucou_params (o
,(22,"ee"))))
1086 Eliom_output.Any.register_service
1088 ~get_params
:(string "type")
1092 Eliom_output.Xhtml.send
1094 (head
(title
(pcdata
"")) [])
1096 "This page has been statically typechecked.
1097 If you change the parameter in the URL you will get an unchecked text page"]]))
1099 Eliom_output.HtmlText.send
1100 "<html><body><p>It is not a valid page. Put type=\"valid\" in the URL to get a typechecked page.</p></body></html>"
1107 let cookiename = "mycookie"
1109 let cookies = service
["cookies"] unit ()
1111 let _ = Eliom_output.Xhtml.register
cookies
1113 Eliom_state.set_cookie
1114 ~name
:cookiename ~
value:(string_of_int
(Random.int 100)) ();
1117 (head
(title
(pcdata
"")) [])
1118 (body
[p
[pcdata
(try
1121 cookiename (Eliom_request_info.get_cookies
()))
1122 with _ -> "<cookie not set>");
1124 a
cookies [pcdata
"send other cookie"] ()]])))
1131 let mystore = Ocsipersist.open_store
"eliomexamplestore2"
1135 let cthr = Ocsipersist.make_persistent
mystore "countpage" 0 in
1136 let mutex = Lwt_mutex.create
() in
1139 Lwt_mutex.lock
mutex >>= fun () ->
1140 Ocsipersist.get
c >>= fun oldc
->
1141 let newc = oldc
+ 1 in
1142 Ocsipersist.set
c newc >>= fun () ->
1143 Lwt_mutex.unlock
mutex;
1154 (head
(title
(pcdata
"counter")) [])
1155 (body
[p
[pcdata
(string_of_int n
)]]))))
1161 (************************************************************)
1162 (************ Connection of users, version 4 ****************)
1163 (**************** (persistent sessions) *********************)
1164 (************************************************************)
1167 let persistent_sessions_scope_name = Eliom_common.create_scope_name
"persistent_sessions"
1168 let session = `Session
persistent_sessions_scope_name
1169 let session_group = `Session_group
persistent_sessions_scope_name
1170 let persistent_session_scope = session
1172 let my_persistent_table =
1173 create_persistent_table
(*zap* *) ~scope
:session (* *zap*) "eliom_example_table"
1175 (* -------------------------------------------------------- *)
1176 (* We create one main service and two (POST) actions *)
1177 (* (for connection and disconnection) *)
1179 let persist_session_example =
1180 Eliom_services.service
1185 let persist_session_connect_action =
1186 Eliom_services.post_coservice'
1188 ~post_params
:(string "login")
1191 (* disconnect_action, login_box and disconnect_box have been
1192 defined in the section about actions *)
1196 (* -------------------------------------------------------- *)
1197 (* Actually, no. It's a lie because we don't use the
1198 same session name :-) *)
1199 (* new disconnect action and box: *)
1201 let disconnect_action =
1202 Eliom_output.Action.register_post_coservice'
1204 ~post_params
:Eliom_parameters.unit
1206 Eliom_state.discard ~scope
:session ())
1208 let disconnect_box s
=
1209 Eliom_output.Xhtml.post_form
disconnect_action
1210 (fun _ -> [p
[Eliom_output.Xhtml.string_input
1211 ~input_type
:`Submit ~
value:s
()]]) ()
1213 let bad_user_key = Polytables.make_key
()
1214 let get_bad_user table
=
1215 try Polytables.get ~table ~key
:bad_user_key with Not_found
-> false
1217 (* -------------------------------------------------------- *)
1218 (* new login box: *)
1220 let login_box session_expired action
=
1221 Eliom_output.Xhtml.post_form action
1225 string_input ~input_type
:`Text ~name
:loginname
()]
1227 [p
(if get_bad_user (Eliom_request_info.get_request_cache
())
1228 then (pcdata
"Wrong user")::(br
())::l
1231 then (pcdata
"Session expired")::(br
())::l
1238 (* ----------------------------------------------------------- *)
1239 (* Handler for "persist_session_example" service (main page): *)
1241 let persist_session_example_handler () () =
1242 Eliom_state.get_persistent_data
1243 ~table
:my_persistent_table () >>= fun sessdat ->
1246 (head
(title
(pcdata
"")) [])
1249 | Eliom_state.Data name
->
1250 [p
[pcdata
("Hello "^name
); br
()];
1251 disconnect_box "Close session"]
1252 | Eliom_state.Data_session_expired
->
1253 [login_box true persist_session_connect_action;
1254 p
[em
[pcdata
"The only user is 'toto'."]]]
1255 | Eliom_state.No_data
->
1256 [login_box false persist_session_connect_action;
1257 p
[em
[pcdata
"The only user is 'toto'."]]]
1261 (* ----------------------------------------------------------- *)
1262 (* Handler for persist_session_connect_action (user logs in): *)
1264 let persist_session_connect_action_handler () login
=
1265 lwt
() = Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) () in
1266 if login
= "toto" (* Check user and password :-) *)
1268 Eliom_state.set_persistent_data ~table
:my_persistent_table login
1269 else ((*zap* *)Polytables.set
(Eliom_request_info.get_request_cache
()) bad_user_key true;(* *zap*)return
())
1272 (* -------------------------------------------------------- *)
1273 (* Registration of main services: *)
1276 Eliom_output.Xhtml.register
1277 ~service
:persist_session_example
1278 persist_session_example_handler;
1279 Eliom_output.Action.register
1280 ~service
:persist_session_connect_action
1281 persist_session_connect_action_handler
1286 (************************************************************)
1287 (************ Connection of users, version 6 ****************)
1288 (************************************************************)
1290 let scope_name = Eliom_common.create_scope_name
"connect_example6"
1291 let session = `Session
scope_name
1292 let session_group = `Session_group
scope_name
1294 (* -------------------------------------------------------- *)
1295 (* We create one main service and two (POST) actions *)
1296 (* (for connection and disconnection) *)
1298 let connect_example6 =
1299 Eliom_services.service
1304 let connect_action =
1305 Eliom_services.post_coservice'
1307 ~post_params
:(string "login")
1310 (* new disconnect action and box: *)
1312 let disconnect_action =
1313 Eliom_output.Action.register_post_coservice'
1315 ~post_params
:Eliom_parameters.unit
1317 Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) ())
1319 let disconnect_box s
=
1320 Eliom_output.Xhtml.post_form
disconnect_action
1321 (fun _ -> [p
[Eliom_output.Xhtml.string_input
1322 ~input_type
:`Submit ~
value:s
()]]) ()
1325 let bad_user_key = Polytables.make_key
()
1326 let get_bad_user table
=
1327 try Polytables.get ~table ~key
:bad_user_key with Not_found
-> false
1329 (* -------------------------------------------------------- *)
1330 (* new login box: *)
1332 let login_box session_expired action
=
1333 Eliom_output.Xhtml.post_form action
1337 string_input ~input_type
:`Text ~name
:loginname
()]
1339 [p
(if get_bad_user (Eliom_request_info.get_request_cache
())
1340 then (pcdata
"Wrong user")::(br
())::l
1343 then (pcdata
"Session expired")::(br
())::l
1348 (* -------------------------------------------------------- *)
1349 (* Handler for the "connect_example6" service (main page): *)
1351 let connect_example6_handler () () =
1352 let status = Eliom_state.volatile_data_state_status
(*zap* *) ~scope
:session (* *zap*) ()
1355 Eliom_state.get_volatile_data_session_group
(*zap* *) ~scope
:session (* *zap*) ()
1359 (head
(title
(pcdata
"")) [])
1361 (match group, status with
1363 [p
[pcdata
("Hello "^name
); br
()];
1364 disconnect_box "Close session"]
1365 | None
, Eliom_state.Expired_state
->
1366 [login_box true connect_action;
1367 p
[em
[pcdata
"The only user is 'toto'."]]]
1369 [login_box false connect_action;
1370 p
[em
[pcdata
"The only user is 'toto'."]]]
1373 (* -------------------------------------------------------- *)
1374 (* New handler for connect_action (user logs in): *)
1376 let connect_action_handler () login
=
1377 lwt
() = Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) () in
1378 if login
= "toto" (* Check user and password :-) *)
1380 Eliom_state.set_volatile_data_session_group ~set_max
:4
1381 (*zap* *) ~scope
:session (* *zap*) login
;
1385 Polytables.set
(Eliom_request_info.get_request_cache
()) bad_user_key true;
1390 (* -------------------------------------------------------- *)
1391 (* Registration of main services: *)
1394 Eliom_output.Xhtml.register ~service
:connect_example6 connect_example6_handler;
1395 Eliom_output.Action.register ~service
:connect_action connect_action_handler
1401 let disposable = service
["disposable"] unit ()
1403 let _ = register
disposable
1405 let disp_coservice =
1406 coservice ~max_use
:2 ~fallback
:disposable ~get_params
:unit ()
1408 register ~scope
:Eliom_common.session ~service
:disp_coservice
1412 (head
(title
(pcdata
"")) [])
1413 (body
[p
[pcdata
"I am a disposable coservice";
1415 a
disp_coservice [pcdata
"Try me once again"] ()]]))
1419 (head
(title
(pcdata
"")) [])
1420 (body
[p
[(if Eliom_request_info.get_link_too_old
()
1421 then pcdata
"Your link was outdated. I am the fallback. I just created a new disposable coservice. You can use it only twice."
1423 pcdata
"I just created a disposable coservice. You can use it only twice.");
1425 a
disp_coservice [pcdata
"Try it!"] ()]])))
1430 let timeout = service
["timeout"] unit ()
1435 register_coservice ~scope
:session
1436 ~fallback
:timeout ~get_params
:unit ~
timeout:5.
1440 (head
(title
(pcdata
"Coservices with timeouts")) [])
1442 [pcdata
"I am a coservice with timeout."; br
();
1443 pcdata
"Try to reload the page!"; br
();
1444 pcdata
"I will disappear after 5 seconds of inactivity." ];
1449 (head
(title
(pcdata
"Coservices with timeouts")) [])
1451 [pcdata
"I just created a coservice with 5 seconds timeout."; br
();
1452 a
timeoutcoserv [pcdata
"Try it"] (); ];
1455 register
timeout page
1460 let publiccoduringsess = service
["publiccoduringsess"] unit ()
1466 ~fallback
:publiccoduringsess ~get_params
:unit ~
timeout:5.
1470 (head
(title
(pcdata
"Coservices with timeouts")) [])
1472 [pcdata
"I am a public coservice with timeout."; br
();
1473 pcdata
"I will disappear after 5 seconds of inactivity." ];
1478 (head
(title
(pcdata
"Public coservices with timeouts")) [])
1480 [pcdata
"I just created a public coservice with 5 seconds timeout."; br
();
1481 a
timeoutcoserv [pcdata
"Try it"] (); ];
1484 register
publiccoduringsess page
1489 let _ = Eliom_output.set_exn_handler
1490 (fun e
-> match e
with
1491 | Eliom_common.Eliom_404
->
1492 Eliom_output.Xhtml.send ~code
:404
1494 (head
(title
(pcdata
"")) [])
1495 (body
[h1
[pcdata
"Eliom tutorial"];
1496 p
[pcdata
"Page not found"]]))
1497 (* | Eliom_common.Eliom_Wrong_parameter ->
1498 Eliom_output.Xhtml.send
1500 (head (title (pcdata "")) [])
1501 (body [h1 [pcdata "Eliom tutorial"];
1502 p [pcdata "Wrong parameters"]])) *)
1508 Eliom_parameters.make_non_localized_parameters
1511 (Eliom_parameters.int "a" ** Eliom_parameters.string "s")
1513 let nlparams = register_service
1515 ~get_params
:(int "i")
1519 (head
(title
(pcdata
"")) [])
1520 (body
[p
[pcdata
"i = ";
1521 strong
[pcdata
(string_of_int i
)]];
1522 (match Eliom_parameters.get_non_localized_get_parameters
1526 p
[pcdata
"I do not have my non localized parameters"]
1528 p
[pcdata
"I have my non localized parameters, ";
1529 pcdata
("with values a = "^string_of_int a^
1539 let tonlparams = register_service
1545 (head
(title
(pcdata
"")) [])
1547 [p
[a ~service
:nlparams [pcdata
"without nl params"] 4];
1548 p
[a ~service
:nlparams
1549 ~nl_params
:(Eliom_parameters.add_nl_parameter
1550 Eliom_parameters.empty_nl_params_set
1554 [pcdata
"with nl params"]
1558 ~nl_params
:(Eliom_parameters.add_nl_parameter
1559 Eliom_parameters.empty_nl_params_set
1564 [p
[pcdata
"form with hidden nl params";
1565 Eliom_output.Xhtml.int_input
1566 ~input_type
:`Text ~name
:iname
();
1567 Eliom_output.Xhtml.string_input
1568 ~input_type
:`Submit ~
value:"Send" ()]]);
1572 let (aname
, sname
) =
1573 Eliom_parameters.get_nl_params_names
my_nl_params
1575 [p
[pcdata
"form with nl params fiels";
1576 Eliom_output.Xhtml.int_input
1577 ~input_type
:`Text ~name
:iname
();
1578 Eliom_output.Xhtml.int_input
1579 ~input_type
:`Text ~name
:aname
();
1580 Eliom_output.Xhtml.string_input
1581 ~input_type
:`Text ~name
:sname
();
1582 Eliom_output.Xhtml.string_input
1583 ~input_type
:`Submit ~
value:"Send" ()]]);
1592 let nlparams_with_nlp =
1593 Eliom_services.add_non_localized_get_parameters
my_nl_params nlparams
1597 (************************************************************)
1598 (************ Connection of users, version 5 ****************)
1599 (************************************************************)
1602 let scope_name = Eliom_common.create_scope_name
"connect_example5"
1603 let session = `Session
scope_name
1604 let session_group = `Session_group
scope_name
1606 (* -------------------------------------------------------- *)
1607 (* We create one main service and two (POST) actions *)
1608 (* (for connection and disconnection) *)
1610 let connect_example5 =
1611 Eliom_services.service
1613 ~get_params
:Eliom_parameters.unit
1616 let connect_action =
1617 Eliom_services.post_coservice'
1619 ~post_params
:(Eliom_parameters.string "login")
1622 (* As the handler is very simple, we register it now: *)
1623 let disconnect_action =
1624 Eliom_output.Action.register_post_coservice'
1626 ~post_params
:Eliom_parameters.unit
1628 Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) ())
1631 (* -------------------------------------------------------- *)
1632 (* login ang logout boxes: *)
1634 let disconnect_box s
=
1635 Eliom_output.Xhtml.post_form
disconnect_action
1636 (fun _ -> [p
[Eliom_output.Xhtml.string_input
1637 ~input_type
:`Submit ~
value:s
()]]) ()
1640 Eliom_output.Xhtml.post_form
connect_action
1643 (let l = [pcdata
"login: ";
1644 Eliom_output.Xhtml.string_input
1645 ~input_type
:`Text ~name
:loginname
()]
1651 (* -------------------------------------------------------- *)
1652 (* Handler for the "connect_example5" service (main page): *)
1654 let connect_example5_handler () () =
1655 let sessdat = Eliom_state.get_volatile_data_session_group
(*zap* *) ~scope
:session (* *zap*) () in
1658 (head
(title
(pcdata
"")) [])
1662 [p
[pcdata
("Hello "^name
); br
()];
1663 disconnect_box "Close session"]
1664 | None
-> [login_box ()]
1668 (* -------------------------------------------------------- *)
1669 (* Handler for connect_action (user logs in): *)
1671 let connect_action_handler () login
=
1672 Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) () >>= fun () ->
1673 Eliom_state.set_volatile_data_session_group ~set_max
:4 (*zap* *) ~scope
:session (* *zap*) login
;
1677 (* -------------------------------------------------------- *)
1678 (* Registration of main services: *)
1681 Eliom_output.Xhtml.register ~service
:connect_example5 connect_example5_handler;
1682 Eliom_output.Action.register ~service
:connect_action connect_action_handler
1686 (************************************************************)
1687 (********************* Group tables *************************)
1688 (************************************************************)
1691 let scope_name = Eliom_common.create_scope_name
"group_tables"
1692 let session = `Session
scope_name
1693 let session_group = `Session_group
scope_name
1696 Eliom_state.create_volatile_table
1697 ~scope
:session_group ()
1698 (* -------------------------------------------------------- *)
1699 (* We create one main service and two (POST) actions *)
1700 (* (for connection and disconnection) *)
1702 let group_tables_example =
1703 Eliom_services.service
1704 ~path
:["grouptables"]
1705 ~get_params
:Eliom_parameters.unit
1708 let connect_action =
1709 Eliom_services.post_coservice'
1711 ~post_params
:(Eliom_parameters.string "login")
1714 let disconnect_action =
1715 Eliom_output.Action.register_post_coservice'
1716 ~name
:"disconnectgt"
1717 ~post_params
:Eliom_parameters.unit
1719 Eliom_state.discard ~scope
:session ())
1721 let disconnect_g_action =
1722 Eliom_output.Action.register_post_coservice'
1723 ~name
:"disconnectgtg"
1724 ~post_params
:Eliom_parameters.unit
1726 Eliom_state.discard ~scope
:session_group ())
1729 (* -------------------------------------------------------- *)
1730 (* login ang logout boxes: *)
1732 let disconnect_box () =
1734 Eliom_output.Xhtml.post_form
disconnect_action
1735 (fun _ -> [p
[Eliom_output.Xhtml.string_input
1736 ~input_type
:`Submit ~
value:"Close session" ()]]) ();
1737 Eliom_output.Xhtml.post_form
disconnect_g_action
1738 (fun _ -> [p
[Eliom_output.Xhtml.string_input
1739 ~input_type
:`Submit ~
value:"Close group" ()]]) ()
1743 Eliom_output.Xhtml.post_form
connect_action
1746 (let l = [pcdata
"login: ";
1747 Eliom_output.Xhtml.string_input
1748 ~input_type
:`Text ~name
:loginname
()]
1754 (* -------------------------------------------------------- *)
1755 (* Handler for the "group_tables_example" service (main page): *)
1757 let group_tables_example_handler () () =
1758 let sessdat = Eliom_state.get_volatile_data_session_group
(*zap* *) ~scope
:session (* *zap*) () in
1759 let groupdata = Eliom_state.get_volatile_data
1762 let group_info name
=
1763 match groupdata with
1764 | Eliom_state.Data_session_expired
1765 | Eliom_state.No_data
->
1766 let d = string_of_int
(Random.int 1000) in
1767 Eliom_state.set_volatile_data ~table
:my_table d;
1769 | Eliom_state.Data
d -> d
1773 (head
(title
(pcdata
"")) [])
1777 [p
[pcdata
("Hello "^name
); br
()];
1778 (let d = group_info name
in
1779 p
[pcdata
"Your group data is: ";
1781 pcdata
". It is common to all the sessions for the same user ";
1783 pcdata
". Try with another browser!"
1785 p
[pcdata
"Check that all sessions with same user name share the value."];
1786 p
[pcdata
"Check that the value disappears when all sessions from the group are closed."];
1787 p
[pcdata
"Check that the all sessions are closed when clicking on \"close group\" button."];
1789 | None
-> [login_box ()]
1793 (* -------------------------------------------------------- *)
1794 (* Handler for connect_action (user logs in): *)
1796 let connect_action_handler () login
=
1797 lwt
() = Eliom_state.discard
(*zap* *) ~scope
:session (* *zap*) () in
1798 Eliom_state.set_volatile_data_session_group ~set_max
:4 (*zap* *) ~scope
:session (* *zap*) login
;
1802 (* -------------------------------------------------------- *)
1803 (* Registration of main services: *)
1806 Eliom_output.Xhtml.register ~service
:group_tables_example group_tables_example_handler;
1807 Eliom_output.Action.register ~service
:connect_action connect_action_handler
1816 (************************************************************)
1817 (**************** Persistent group tables *******************)
1818 (************************************************************)
1820 let scope_name = Eliom_common.create_scope_name
"pgroup_tables"
1821 let session = `Session
scope_name
1822 let session_group = `Session_group
scope_name
1824 Eliom_state.create_persistent_table
1825 ~scope
:session_group "pgroup_table"
1826 (* -------------------------------------------------------- *)
1827 (* We create one main service and two (POST) actions *)
1828 (* (for connection and disconnection) *)
1831 let pgroup_tables_example =
1832 Eliom_services.service
1833 ~path
:["pgrouptables"]
1834 ~get_params
:Eliom_parameters.unit
1838 let connect_action =
1839 Eliom_services.post_coservice'
1841 ~post_params
:(Eliom_parameters.string "login")
1844 let disconnect_action =
1845 Eliom_output.Action.register_post_coservice'
1846 ~name
:"pdisconnectgt"
1847 ~post_params
:Eliom_parameters.unit
1848 (fun () () -> Eliom_state.discard ~scope
:session ())
1850 let disconnect_g_action =
1851 Eliom_output.Action.register_post_coservice'
1852 ~name
:"pdisconnectgtg"
1853 ~post_params
:Eliom_parameters.unit
1855 Eliom_state.discard ~scope
:session_group ())
1859 (* -------------------------------------------------------- *)
1860 (* login ang logout boxes: *)
1862 let disconnect_box () =
1864 Eliom_output.Xhtml.post_form
disconnect_action
1865 (fun _ -> [p
[Eliom_output.Xhtml.string_input
1866 ~input_type
:`Submit ~
value:"Close session" ()]]) ();
1867 Eliom_output.Xhtml.post_form
disconnect_g_action
1868 (fun _ -> [p
[Eliom_output.Xhtml.string_input
1869 ~input_type
:`Submit ~
value:"Close group" ()]]) ()
1873 Eliom_output.Xhtml.post_form
connect_action
1876 (let l = [pcdata
"login: ";
1877 Eliom_output.Xhtml.string_input
1878 ~input_type
:`Text ~name
:loginname
()]
1884 (* -------------------------------------------------------- *)
1885 (* Handler for the "group_tables_example" service (main page): *)
1887 let group_tables_example_handler () () =
1888 Eliom_state.get_persistent_data_session_group ~scope
:session ()
1890 Eliom_state.get_persistent_data ~table
:my_table ()
1891 >>= fun groupdata ->
1892 let group_info name
=
1893 match groupdata with
1894 | Eliom_state.Data_session_expired
1895 | Eliom_state.No_data
->
1896 let d = string_of_int
(Random.int 1000) in
1897 Eliom_state.set_persistent_data ~table
:my_table d
1898 >>= fun r
-> Lwt.return
d
1899 | Eliom_state.Data
d -> Lwt.return
d
1903 (group_info name
>>= fun d ->
1905 [p
[pcdata
("Hello "^name
); br
()];
1906 (p
[pcdata
"Your persistent group data is: ";
1908 pcdata
". It is common to all the sessions for the same user ";
1910 pcdata
". Try with another browser!"
1912 p
[pcdata
"Check that all sessions with same user name share the value."];
1913 p
[pcdata
"Check that the value disappears when all sessions from the group are closed."];
1914 p
[pcdata
"Check that the all sessions are closed when clicking on \"close group\" button."];
1915 p
[pcdata
"Check that the value is preserved after relaunching the server."];
1917 | None
-> Lwt.return
[login_box ()]) >>= fun l ->
1920 (head
(title
(pcdata
"")) [])
1924 (* -------------------------------------------------------- *)
1925 (* Handler for connect_action (user logs in): *)
1927 let connect_action_handler () login
=
1928 lwt
() = Eliom_state.discard ~scope
:session () in
1929 Eliom_state.set_persistent_data_session_group
1930 ~set_max
:(Some
4) ~scope
:session login
1933 (* -------------------------------------------------------- *)
1934 (* Registration of main services: *)
1937 Eliom_output.Xhtml.register ~service
:pgroup_tables_example group_tables_example_handler;
1938 Eliom_output.Action.register ~service
:connect_action connect_action_handler
1945 let csrf_scope_name = Eliom_common.create_scope_name
"csrf"
1946 let csrf_scope = `Session
csrf_scope_name
1948 let csrfsafe_example =
1949 Eliom_services.service
1951 ~get_params
:Eliom_parameters.unit
1954 let csrfsafe_example_post =
1955 Eliom_services.post_coservice
1962 ~fallback
:csrfsafe_example
1963 ~post_params
:Eliom_parameters.unit
1968 let l3 = Eliom_output.Xhtml.post_form
csrfsafe_example_post
1969 (fun _ -> [p
[Eliom_output.Xhtml.string_input
1971 ~
value:"Click" ()]]) ()
1975 (head
(title
(pcdata
"CSRF safe service example")) [])
1976 (body
[p
[pcdata
"A new coservice will be created each time this form is displayed"];
1979 Eliom_output.Xhtml.register
csrfsafe_example page;
1980 Eliom_output.Xhtml.register
csrfsafe_example_post
1984 (head
(title
(pcdata
"CSRF safe service")) [])
1985 (body
[p
[pcdata
"This is a CSRF safe service"]])))
1991 %<code language="ocaml"|
1992 let r = Netstring_pcre.regexp "\\\\[(.*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@)\\\\]"
1995 Eliom_output.Xhtml.register_service
1997 ~get_params:(regexp r "$1" "myparam")
2001 (head (title (pcdata "")) [])
2002 (body [p [pcdata g]])))
2008 let myregexp = Netstring_pcre.regexp "\\[(.*)\\]"
2011 Eliom_output.Xhtml.register_service
2013 ~get_params
:(regexp myregexp "$1" (fun s
-> s
) "myparam")
2017 (head
(title
(pcdata
"")) [])
2018 (body
[p
[pcdata g
]])))
2023 (* Form with bool checkbox: *)
2024 let bool_params = register_service
2026 ~get_params
:(bool "case")
2030 <head
><title
></title
></head
>
2033 $pcdata
(if case
then "checked" else "not checked")$
2038 let create_form_bool casename
=
2039 <:xhtmllist
< <p
>check? $bool_checkbox ~name
:casename
()$
<br
/>
2040 $string_input ~input_type
:`Submit ~
value:"Click" ()$
</p
> >>
2042 let form_bool = register_service
["formbool"] unit
2044 let f = get_form
bool_params create_form_bool in
2047 <head
><title
></title
></head
>
2057 let set = register_service
2059 ~get_params
:(set string "s")
2063 (fun s
-> <:xhtml
< <strong
>$str
:s$
</strong
> >>) l
2067 <head
><title
></title
></head
>
2081 let setform = register_service
2087 (head
(title
(pcdata
"")) [])
2088 (body
[h1
[pcdata
"Set Form"];
2091 [p
[pcdata
"Form to set: ";
2092 string_checkbox ~name
:n ~
value:"box1" ();
2094 ~name
:n ~
value:"box2" ~checked
:true ();
2095 string_checkbox ~name
:n ~
value:"box3" ();
2096 string_checkbox ~name
:n ~
value:"box4" ();
2097 string_input ~input_type
:`Submit ~
value:"Click" ()]])
2103 let select_example_result = register_service
2105 ~get_params
:(string "s")
2109 (head
(title
(pcdata
"")) [])
2110 (body
[p
[pcdata
"You selected: ";
2111 strong
[pcdata g
]]])))
2113 let create_select_form =
2115 [p
[pcdata
"Select something: ";
2116 Eliom_output.Xhtml.string_select ~name
:select_name
2117 (Eliom_output.Xhtml.Option
([] (* attributes *),
2119 None
(* Content, if different from value *),
2120 false (* not selected *))) (* first line *)
2121 [Eliom_output.Xhtml.Option
([], "Marc", None
, false);
2122 (Eliom_output.Xhtml.Optgroup
2125 ([], "Karin", None
, false),
2126 [([a_disabled `Disabled
], "Juliette", None
, false);
2127 ([], "Alice", None
, true);
2128 ([], "Germaine", Some
(pcdata
"Bob's mother"), false)]))]
2130 Eliom_output.Xhtml.string_input ~input_type
:`Submit ~
value:"Send" ()]])
2132 let select_example = register_service
["select"] unit
2135 Eliom_output.Xhtml.get_form
2136 select_example_result create_select_form
2140 (head
(title
(pcdata
"")) [])
2146 let coord = register_service
2148 ~get_params
:(coordinates
"coord")
2152 <head
><title
></title
></head
>
2155 You clicked on coordinates
:
2156 ($str
:(string_of_int
c.abscissa
)$
, $str
:(string_of_int
c.ordinate
)$
)
2162 let imageform = register_service
2168 (head
(title
(pcdata
"")) [])
2169 (body
[h1
[pcdata
"Image Form"];
2173 ~src
:(make_uri ~service
:(static_dir
()) ["ocsigen5.png"])
2181 let coord2 = register_service
2183 ~get_params
:(int_coordinates
"coord")
2187 <head
><title
></title
></head
>
2190 You clicked on coordinates
:
2191 ($str
:(string_of_int
c.abscissa
)$
, $str
:(string_of_int
c.ordinate
)$
)
2197 let imageform2 = register_service
2198 ~path
:["imageform2"]
2203 (head
(title
(pcdata
"")) [])
2204 (body
[h1
[pcdata
"Image Form"];
2208 ~src
:(make_uri ~service
:(static_dir
()) ["ocsigen5.png"])
2220 let coucou_list = register_service
2222 ~get_params
:(list
"a" (string "str"))
2225 List.map
(fun s
-> <:xhtml
< <strong
>$str
:s$
</strong
> >>) l in
2228 <head
><title
></title
></head
>
2241 Actually almost all services will be overwritten by new versions,
2242 but not those with user_type parameters for example
2243 (because the type description contains functions)
2246 (* Form with list: *)
2247 let create_listform f =
2248 (* Here, f.it is an iterator like List.map,
2249 but it must be applied to a function taking 3 arguments
2250 (unlike 1 in map), the first one being the name of the parameter,
2251 and the second one the element of list.
2252 The last parameter of f.it is the code that must be appended at the
2253 end of the list created
2255 f.it
(fun stringname
v init
->
2256 <:xhtmllist
< <p
>Write the
value for $str
:v$
:
2257 $string_input ~input_type
:`Text ~name
:stringname
()$
</p
> >>@init
)
2258 ["one";"two";"three";"four"]
2259 <:xhtmllist
< <p
>$string_input ~input_type
:`Submit ~
value:"Click" ()$
</p
> >>
2261 let listform = register_service
["listform"] unit
2263 let f = get_form
coucou_list create_listform in
2266 <head
><title
></title
></head
>
2274 (* Form for service with suffix: *)
2275 let create_suffixform ((suff
, endsuff
),i
) =
2276 <:xhtmllist
< <p
>Write the suffix
(integer
):
2277 $int_input ~input_type
:`Text ~name
:suff
()$
<br
/>
2278 Write a
string: $user_type_input
2279 (Url.string_of_url_path ~encode
:false)
2280 ~input_type
:`Text ~name
:endsuff
()
2282 Write an
int: $int_input ~input_type
:`Text ~name
:i
()$
<br
/>
2283 $string_input ~input_type
:`Submit ~
value:"Click" ()$
</p
> >>
2285 let suffixform = register_service
["suffixform"] unit
2287 let f = get_form
isuffix create_suffixform in
2290 <head
><title
></title
></head
>
2298 let upload = service
2303 let upload2 = register_post_service
2305 ~post_params
:(file
"file")
2308 let newname = "/tmp/thefile" in
2310 Unix.unlink
newname;
2312 Ocsigen_messages.console2
(Eliom_request_info.get_tmp_filename file
);
2313 Unix.link
(Eliom_request_info.get_tmp_filename file
) newname;
2314 let fd_in = open_in
newname in
2316 let line = input_line
fd_in in close_in
fd_in; line (*end*)
2317 with End_of_file
-> close_in
fd_in; "vide"
2321 (head
(title
(pcdata
"Upload")) [])
2322 (body
[h1
[pcdata
to_display]])))
2325 let uploadform = register
upload
2330 [p
[file_input ~name
:file
();
2332 string_input ~input_type
:`Submit ~
value:"Send" ()
2336 (head
(title
(pcdata
"form")) [])
2344 (* Hierarchical menu *)
2345 open Eliom_tools_common
2348 let hier1 = service ~path
:["hier1"] ~get_params
:unit ()
2349 let hier2 = service ~path
:["hier2"] ~get_params
:unit ()
2350 let hier3 = service ~path
:["hier3"] ~get_params
:unit ()
2351 let hier4 = service ~path
:["hier4"] ~get_params
:unit ()
2352 let hier5 = service ~path
:["hier5"] ~get_params
:unit ()
2353 let hier6 = service ~path
:["hier6"] ~get_params
:unit ()
2354 let hier7 = service ~path
:["hier7"] ~get_params
:unit ()
2355 let hier8 = service ~path
:["hier8"] ~get_params
:unit ()
2356 let hier9 = service ~path
:["hier9"] ~get_params
:unit ()
2357 let hier10 = service ~path
:["hier10"] ~get_params
:unit ()
2363 [([pcdata
"page 1"], Site_tree
(Main_page
hier1, []));
2365 ([pcdata
"page 2"], Site_tree
(Main_page
hier2, []));
2367 ([pcdata
"submenu 4"],
2369 (Default_page
hier4,
2370 [([pcdata
"submenu 3"],
2373 [([pcdata
"page 3"], Site_tree
(Main_page
hier3, []));
2374 ([pcdata
"page 4"], Site_tree
(Main_page
hier4, []));
2375 ([pcdata
"page 5"], Site_tree
(Main_page
hier5, []))]
2379 ([pcdata
"page 6"], Site_tree
(Main_page
hier6, []))]
2384 Site_tree
(Main_page
hier7, []));
2386 ([pcdata
"disabled"], Disabled
);
2388 ([pcdata
"submenu 8"],
2391 [([pcdata
"page 9"], Site_tree
(Main_page
hier9, []));
2392 ([pcdata
"page 10"], Site_tree
(Main_page
hier10, []))]
2401 (head
(title
(pcdata
""))
2402 ((style ~contenttype
:"text/css"
2405 li.eliomtools_current > a {color: blue;}\n
2410 border-right: solid 1px black;}\n
2411 .breadthmenu li.eliomtools_last {border: none;}\n
2413 Xhtml.structure_links
mymenu ~service
:s
())
2415 (body
[h1
[pcdata
("Page "^string_of_int i
)];
2416 h2
[pcdata
"Depth first, whole tree:"];
2418 (Xhtml.hierarchical_menu_depth_first
2419 ~whole_tree
:true mymenu ~service
:s
());
2420 h2
[pcdata
"Depth first, only current submenu:"];
2421 div
(Xhtml.hierarchical_menu_depth_first
mymenu ~service
:s
());
2422 h2
[pcdata
"Breadth first:"];
2424 (Xhtml.hierarchical_menu_breadth_first
2425 ~classe
:["breadthmenu"] mymenu ~service
:s
())]))
2429 register
hier1 (f 1 hier1);
2430 register
hier2 (f 2 hier2);
2431 register
hier3 (f 3 hier3);
2432 register
hier4 (f 4 hier4);
2433 register
hier5 (f 5 hier5);
2434 register
hier6 (f 6 hier6);
2435 register
hier7 (f 7 hier7);
2436 register
hier8 (f 8 hier8);
2437 register
hier9 (f 9 hier9);
2438 register
hier10 (f 10 hier10)