2 * http://www.ocsigen.org
3 * Module eliomexamples.ml
4 * Copyright (C) 2007 Vincent Balat
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, with linking exception;
9 * either version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 (* Other examples for Eliom, and various tests *)
29 (*****************************************************************************)
30 (* Test for raw_post_data *)
32 let raw_post_example =
33 Eliom_output.Html5.register_service
39 (head
(title
(pcdata
"raw post data")) [])
40 (body
[p
[pcdata
"It is possible to send POST data to this URL, using any content-type other than form data or multipart. Try it with telnet. Cut and paste in a terminal:"];
41 pre
[pcdata
"telnet localhost 8080
42 POST /rawpost HTTP/1.0
43 Content-type: plop/plop
44 Content-length: 124"];
48 let raw_post_service =
49 Eliom_output.Html5.register_post_service
50 ~fallback
:raw_post_example
51 ~post_params
:raw_post_data
52 (fun () (ct
, stream
) ->
53 let ct = match ct with
55 | Some
((content_type1
, content_type2
), _
) ->
56 content_type1^
"/"^content_type2
59 | None
-> Lwt.return
""
61 Ocsigen_stream.string_of_stream
1000 (Ocsigen_stream.get stream
))
65 (head
(title
(pcdata
"raw post data")) [])
66 (body
[p
[pcdata
"I received POST data, with content-type = ";
68 pcdata
", and the first 1000 bytes of the content are:"];
74 (*****************************************************************************)
76 (************************************************************)
77 (****************** Connection of users *********************)
78 (************************************************************)
80 let scope_name = Eliom_common.create_scope_name
"connect_example_state"
81 let session = `Session
scope_name
83 (* -------------------------------------------------------- *)
84 (* We create one main service and two (POST) actions *)
85 (* (for connection and disconnection) *)
88 Eliom_services.service
89 ~path
:["connect_example"]
94 Eliom_services.post_coservice'
96 ~post_params
:(string "login")
99 (* disconnect action and box: *)
101 let disconnect_action =
102 Eliom_output.Action.register_post_coservice'
103 ~name
:"disconnection"
104 ~post_params
:Eliom_parameters.unit
106 Eliom_state.discard ~scope
:session ())
108 let disconnect_box s
=
109 Eliom_output.Html5.post_form
disconnect_action
110 (fun _
-> [p
[Eliom_output.Html5.string_input
111 ~input_type
:`Submit ~
value:s
()]]) ()
113 (* The following eref is true if the connection has action failed: *)
114 let bad_user = Eliom_references.eref ~scope
:Eliom_common.request
false
116 (* The following eref is the name of the user, when connected *)
117 let user = Eliom_references.eref ~scope
:session None
119 (* -------------------------------------------------------- *)
122 let login_box session_expired bad_u action
=
123 Eliom_output.Html5.post_form action
127 Eliom_output.Html5.string_input ~input_type
:`Text ~name
:loginname
()]
130 then (pcdata
"Wrong user")::(br
())::l
133 then (pcdata
"Session expired")::(br
())::l
138 (* -------------------------------------------------------- *)
139 (* Handler for the "connect_example" service (main page): *)
141 let connect_example_handler () () =
142 (* The following function tests whether the session has expired: *)
143 let status = Eliom_state.volatile_data_state_status
(*zap* *) ~scope
:session (* *zap*) ()
145 Eliom_references.get
bad_user >>= fun bad_u
->
146 Eliom_references.get
user >>= fun u
->
149 (head
(title
(pcdata
"")) [])
151 (match u
, status with
153 [p
[pcdata
("Hello "^name
); br
()];
154 disconnect_box "Close session"]
155 | None
, Eliom_state.Expired_state
->
156 [login_box true bad_u
connect_action;
157 p
[em
[pcdata
"The only user is 'toto'."]]]
159 [login_box false bad_u
connect_action;
160 p
[em
[pcdata
"The only user is 'toto'."]]]
163 (* -------------------------------------------------------- *)
164 (* Handler for connect_action (user logs in): *)
166 let connect_action_handler () login
=
167 lwt
() = Eliom_state.discard ~scope
:session () in
168 if login
= "toto" (* Check user and password :-) *)
169 then Eliom_references.set
user (Some login
)
170 else Eliom_references.set
bad_user true
173 (* -------------------------------------------------------- *)
174 (* Registration of main services: *)
177 Eliom_output.Html5.register ~service
:connect_example connect_example_handler;
178 Eliom_output.Action.register ~service
:connect_action connect_action_handler
181 (*****************************************************************************)
183 (************************************************************)
184 (********* Connection of users with session groups **********)
185 (************************************************************)
187 let scope_name = Eliom_common.create_scope_name
"session_group_example_state"
188 let session = `Session
scope_name
190 (* -------------------------------------------------------- *)
191 (* We create one main service and two (POST) actions *)
192 (* (for connection and disconnection) *)
194 let connect_example =
195 Eliom_services.service
201 Eliom_services.post_coservice'
203 ~post_params
:(string "login")
206 (* disconnect action and box: *)
208 let disconnect_action =
209 Eliom_output.Action.register_post_coservice'
210 ~name
:"disconnection2"
211 ~post_params
:Eliom_parameters.unit
213 Eliom_state.discard ~scope
:session ())
215 let disconnect_box s
=
216 Eliom_output.Html5.post_form
disconnect_action
217 (fun _
-> [p
[Eliom_output.Html5.string_input
218 ~input_type
:`Submit ~
value:s
()]]) ()
220 (* The following eref is true if the connection has action failed: *)
221 let bad_user = Eliom_references.eref ~scope
:Eliom_common.request
false
223 (* -------------------------------------------------------- *)
226 let login_box session_expired bad_u action
=
227 Eliom_output.Html5.post_form action
231 Eliom_output.Html5.string_input ~input_type
:`Text ~name
:loginname
()]
234 then (pcdata
"Wrong user")::(br
())::l
237 then (pcdata
"Session expired")::(br
())::l
242 (* -------------------------------------------------------- *)
243 (* Handler for the "connect_example" service (main page): *)
245 let connect_example_handler () () =
246 (* The following function tests whether the session has expired: *)
247 let status = Eliom_state.volatile_data_state_status
(*zap* *) ~scope
:session (* *zap*) ()
250 Eliom_state.get_volatile_data_session_group
(*zap* *) ~scope
:session (* *zap*) ()
252 Eliom_references.get
bad_user >>= fun bad_u
->
255 (head
(title
(pcdata
"")) [])
257 (match group, status with
259 [p
[pcdata
("Hello "^name
); br
()];
260 disconnect_box "Close session"]
261 | None
, Eliom_state.Expired_state
->
262 [login_box true bad_u
connect_action;
263 p
[em
[pcdata
"The only user is 'toto'."]]]
265 [login_box false bad_u
connect_action;
266 p
[em
[pcdata
"The only user is 'toto'."]]]
269 (* -------------------------------------------------------- *)
270 (* Handler for connect_action (user logs in): *)
272 let connect_action_handler () login
=
273 lwt
() = Eliom_state.discard ~scope
:session () in
274 if login
= "toto" (* Check user and password :-) *)
276 Eliom_state.set_volatile_data_session_group ~set_max
:4 (*zap* *) ~scope
:session (* *zap*) login
;
277 Eliom_output.Redirection.send
Eliom_services.void_hidden_coservice'
280 Eliom_references.set
bad_user true >>= fun () ->
281 Eliom_output.Action.send
()
284 (* -------------------------------------------------------- *)
285 (* Registration of main services: *)
288 Eliom_output.Html5.register ~service
:connect_example connect_example_handler;
289 Eliom_output.Any.register ~service
:connect_action connect_action_handler
293 (*****************************************************************************)
295 let myeref = Eliom_references.eref ~scope
:`Global ~persistent
:"perscount" 0
299 let mutex = Lwt_mutex.create
() in
301 Lwt_mutex.lock
mutex >>= fun () ->
302 Eliom_references.get
myeref >>= fun oldc
->
303 let newc = oldc
+ 1 in
304 Eliom_references.set
myeref newc >>= fun () ->
305 Lwt_mutex.unlock
mutex;
308 Eliom_output.Html5.register_service
316 (HTML5.M.head
(HTML5.M.title
(HTML5.M.pcdata
"counter")) [])
317 (HTML5.M.body
[HTML5.M.p
[HTML5.M.pcdata
(string_of_int n
)]]))))
320 (*****************************************************************************)
322 open Eliom_testsuite1
324 open Eliom_output.Xhtml
331 let lilists = service
[ "lilists" ] unit ()
333 let lilists2 = service
334 ["lilists2"] (list
"l" (string "title" ** (list
"il" (int "i")))) ()
338 f
.it
(fun (sn
, l2
) v init
->
339 (tr
(td
[pcdata
("Write a string: ")])
340 ((td
[string_input ~input_type
:`Text ~name
:sn
()])::
341 (td
[pcdata
("Write integers: ")])::
343 (l2
.it
(fun iname v init
->
344 (td
[int_input ~input_type
:`Text ~name
:iname
()])::init
)
349 ["one";"two";"three"]
352 [table
(List.hd
l) (List.tl
l);
353 p
[string_input ~input_type
:`Submit ~
value:"Click" ()]]
355 let () = register
lilists
357 let f = Eliom_output.Xhtml.get_form
lilists2 create_form in
360 (head
(title
(pcdata
"")) [])
363 let () = register
lilists2
367 (head
(title
(pcdata
"")) [])
369 (List.map
(fun (s
, il
) -> p
(pcdata s
::
370 List.map
(fun i
-> pcdata
(string_of_int i
)) il
)) ll
))))
373 (* sums in parameters types *)
375 let sumserv = register_service
377 ~get_params
:(sum
(int "i") (sum
(int "ii") (string "s")))
381 (head
(title
(pcdata
"")) [])
382 (body
[p
[pcdata
"You sent: ";
386 | Inj2
(Inj1 i
) -> string_of_int i
387 | Inj2
(Inj2 s
) -> s
) ]]])))
390 (fun (name1
, (name2
, name3
)) ->
392 Eliom_output.Xhtml.int_input
393 ~name
:name1 ~input_type
:`Submit ~
value:48 ();
394 Eliom_output.Xhtml.int_input
395 ~name
:name2 ~input_type
:`Submit ~
value:55 ();
396 Eliom_output.Xhtml.string_input
397 ~name
:name3 ~input_type
:`Submit ~
value:"plop" ();
400 let sumform = register_service
["sumform"] unit
402 let f = Eliom_output.Xhtml.get_form
sumserv create_form in
405 (head
(title
(pcdata
"")) [])
409 let sumform2 = service ~path
:["sumform2"] ~get_params
:unit ()
411 let sumserv = register_post_service
413 ~post_params
:(sum
(int "i") (sum
(int "ii") (string "s")))
417 (head
(title
(pcdata
"")) [])
418 (body
[p
[pcdata
"You sent: ";
422 | Inj2
(Inj1 i
) -> string_of_int i
423 | Inj2
(Inj2 s
) -> s
) ]]])))
425 let () = register
sumform2
427 let f = Eliom_output.Xhtml.post_form
sumserv create_form () in
430 (head
(title
(pcdata
"")) [])
435 (* unregistering services *)
436 let unregister_example =
437 Eliom_output.Xhtml.register_service
439 ~get_params
:Eliom_parameters.unit
441 let s1 = Eliom_output.Xhtml.register_service
442 ~path
:["unregister1"]
443 ~get_params
:Eliom_parameters.unit
444 (fun () () -> failwith
"s1")
446 let s2 = Eliom_output.Xhtml.register_coservice
448 ~get_params
:Eliom_parameters.unit
449 (fun () () -> failwith
"s2")
451 let s3 = Eliom_output.Xhtml.register_coservice'
452 ~get_params
:Eliom_parameters.unit
453 (fun () () -> failwith
"s3")
455 Eliom_output.Xhtml.register ~scope
:Eliom_common.session
457 (fun () () -> failwith
"s4");
458 Eliom_services.unregister
s1;
459 Eliom_services.unregister
s2;
460 Eliom_services.unregister
s3;
461 Eliom_services.unregister ~scope
:Eliom_common.session s1;
464 (head
(title
(pcdata
"Unregistering services")) [])
466 "These services have been registered and unregistered"];
467 p
[a
s1 [pcdata
"regular service"] ();
469 a
s2 [pcdata
"coservice"] ();
471 a
s3 [pcdata
"non attached coservice"] ();
473 a
s1 [pcdata
"session service"] ();
481 let csrfsafe_get_example =
482 Eliom_services.service
484 ~get_params
:Eliom_parameters.unit
487 let csrfsafe_example_get =
488 Eliom_services.coservice
491 ~fallback
:csrfsafe_get_example
492 ~get_params
:Eliom_parameters.unit
497 let l3 = Eliom_output.Xhtml.get_form
csrfsafe_example_get
498 (fun _ -> [p
[Eliom_output.Xhtml.string_input
504 (head
(title
(pcdata
"CSRF safe service example")) [])
505 (body
[p
[pcdata
"A new coservice will be created each time this form is displayed"];
508 Eliom_output.Xhtml.register
csrfsafe_get_example page;
509 Eliom_output.Xhtml.register
csrfsafe_example_get
513 (head
(title
(pcdata
"CSRF safe service")) [])
514 (body
[p
[pcdata
"This is a GET CSRF safe service"]])))
517 (* CSRF POST on CSRF GET coservice *)
519 let csrfsafe_postget_example =
520 Eliom_services.service
521 ~path
:["csrfpostget"]
522 ~get_params
:Eliom_parameters.unit
525 let csrfsafe_example_post =
526 Eliom_services.post_coservice
529 ~fallback
:csrfsafe_example_get (* !!! *)
530 ~post_params
:Eliom_parameters.unit
535 let l3 = Eliom_output.Xhtml.post_form
csrfsafe_example_post
536 (fun _ -> [p
[Eliom_output.Xhtml.string_input
538 ~
value:"Click" ()]]) ()
542 (head
(title
(pcdata
"CSRF safe service example")) [])
543 (body
[p
[pcdata
"A new coservice will be created each time this form is displayed"];
546 Eliom_output.Xhtml.register
csrfsafe_postget_example page;
547 Eliom_output.Xhtml.register
csrfsafe_example_post
551 (head
(title
(pcdata
"CSRF safe service")) [])
552 (body
[p
[pcdata
"This is a POST CSRF safe service, combined with a GET CSRF safe service"]])))
556 (* CSRF for_session *)
558 let csrfsafe_session_example =
559 Eliom_services.service
560 ~path
:["csrfsession"]
561 ~get_params
:Eliom_parameters.unit
564 let myscope = (`Session
(Eliom_common.create_scope_name
"plop"))
566 let csrfsafe_example_session =
567 Eliom_services.post_coservice'
572 ~post_params
:Eliom_parameters.unit
577 Eliom_output.Xhtml.register ~scope
:myscope
579 ~service
:csrfsafe_example_session
583 (head
(title
(pcdata
"CSRF safe service")) [])
584 (body
[p
[pcdata
"This is a POST CSRF safe service"]])));
585 let l3 = Eliom_output.Xhtml.post_form
csrfsafe_example_session
586 (fun _ -> [p
[Eliom_output.Xhtml.string_input
593 (head
(title
(pcdata
"CSRF safe service example")) [])
594 (body
[p
[pcdata
"A new coservice will be created each time this form is displayed"];
597 Eliom_output.Xhtml.register
csrfsafe_session_example page
602 (* optional suffix parameters *)
607 ~get_params
:(suffix
(opt
(string "q" ** (opt
(int "i")))))
611 (head
(title
(pcdata
"")) [])
612 (body
[p
[pcdata
(match o
with
617 | Some i
-> string_of_int i
));
623 ~get_params
:(suffix
(opt
(string "q") ** (opt
(int "i"))))
627 (head
(title
(pcdata
"")) [])
628 (body
[p
[pcdata
(match s
with
633 | Some i
-> string_of_int i
)];
638 Eliom_parameters.make_non_localized_parameters
641 (Eliom_parameters.int "a" ** Eliom_parameters.string "s")
644 Eliom_services.add_non_localized_get_parameters
645 my_nl_params Eliom_services.void_hidden_coservice'
647 let nlparams2 = service
649 ~get_params
:(suffix_prod
(int "year" ** int "month") (int "w" ))
652 let nlparams2_with_nlp =
653 Eliom_services.add_non_localized_get_parameters
654 my_nl_params nlparams2
658 (fun ((aa
, bb
), w
) () ->
661 (head
(title
(pcdata
"")) [])
664 [pcdata
"void coservice with non loc param"] ((), (11, "aa"));
666 [pcdata
"myself with non loc param"] (((4, 5), 777), (12, "ab"))];
667 p
[pcdata
"I have my suffix, ";
668 pcdata
("with values year = "^string_of_int aa^
669 " and month = "^string_of_int bb^
670 ". w = "^string_of_int w^
".")];
671 (match Eliom_parameters.get_non_localized_get_parameters
675 p
[pcdata
"I do not have my non localized parameters"]
677 p
[pcdata
"I have my non localized parameters, ";
678 pcdata
("with values a = "^string_of_int a^
688 (* Warning: compute_result may return an deflated result! *)
689 (* Check! (see for example Eliom_output.Action) *)
695 Ocsigen_http_client.get
"ocsigen.org" "/ocsimoreadmin/static/ocsiwikistyle.css" () >>= fun frame
->
696 (match frame
.Ocsigen_http_frame.frame_content
with
697 | None
-> Lwt.return
""
698 | Some stream
-> Ocsigen_stream.string_of_stream
(Ocsigen_config.get_maxrequestbodysizeinmemory
()) (Ocsigen_stream.get stream
)) >>= fun s
->
699 (* Here use an XML parser,
700 or send the stream directly using an appropriate Eliom_mkreg module *)
703 (head
(title
(pcdata
"")) [])
704 (body
[p
[pcdata s
]])))
711 let ri = Eliom_request_info.get_ri
() in
712 let ri = Ocsigen_extensions.ri_of_url
"tuto/" ri in
713 Ocsigen_extensions.compute_result
ri >>= fun result
->
714 let stream = fst result
.Ocsigen_http_frame.res_stream
in
715 Ocsigen_stream.string_of_stream
(Ocsigen_config.get_maxrequestbodysizeinmemory
()) (Ocsigen_stream.get
stream) >>= fun s
->
716 (* Here use an XML parser,
717 or send the stream directly using an appropriate Eliom_mkreg module *)
720 (head
(title
(pcdata
"")) [])
721 (body
[p
[pcdata s
]])))
725 ~path
:["servreqloop"]
728 let ri = Eliom_request_info.get_ri
() in
729 Ocsigen_extensions.compute_result
ri >>= fun result
->
730 let stream = fst result
.Ocsigen_http_frame.res_stream
in
731 Ocsigen_stream.string_of_stream
(Ocsigen_config.get_maxrequestbodysizeinmemory
()) (Ocsigen_stream.get
stream) >>= fun s
->
732 (* Here use an XML parser,
733 or send the stream directly using an appropriate Eliom_mkreg module *)
736 (head
(title
(pcdata
"")) [])
737 (body
[p
[pcdata s
]])))
743 (* Customizing HTTP headers *)
747 ~charset
:"plopcharset"
748 (* ~content_type:"custom/contenttype" *)
749 ~
headers:(Http_headers.add
750 (Http_headers.name
"XCustom-header")
753 ~path
:["httpheaders"]
756 Eliom_state.set_cookie
757 ~path
:[] ~name
:"Customcookie" ~
value:"Value" ~secure
:true ();
758 Eliom_state.set_cookie
759 ~path
:[] ~name
:"Customcookie2" ~
value:"Value2" ();
762 (head
(title
(pcdata
"")) [])
763 (body
[h1
[pcdata
"Look at my HTTP headers"]])))
766 (* form towards a suffix service with constants *)
767 let create_form (n1
, (_, n2
)) =
769 $string_input ~input_type
:`Text ~name
:n1
()$
770 $string_input ~input_type
:`Text ~name
:n2
()$
771 $string_input ~input_type
:`Submit ~
value:"Click" ()$
</p
> >>
773 let constform = register_service
["constform"] unit
775 let f = get_form
Eliom_testsuite1.constfix
create_form in
778 (head
(title
(pcdata
"")) [])
779 (body
[h1
[pcdata
"Hallo"];
783 (* Suffix and other service at same URL *)
787 ~get_params
:(suffix
(all_suffix_string
"s"))
791 (head
(title
(pcdata
"")) [])
794 p
[pcdata
"Try page fuffix/a/b"]])))
798 ~path
:["fuffix";"a";"b"]
803 (head
(title
(pcdata
"")) [])
804 (body
[h1
[pcdata
"Try another suffix"]])))
813 (head
(title
(pcdata
"")) [])
814 (body
[h1
[pcdata
"Try another suffix"]])))
819 ~get_params
:(suffix
(string "s" ** suffix_const
"CONST" ** string "ss"))
821 (fun (s
, ((), ss
)) () ->
824 (head
(title
(pcdata
"")) [])
827 p
[pcdata
"I am a suffix service with a constant part, registered after the generic suffix service, but I have a priority, so that you can see me!"]])))
829 let create_suffixform_su2 s
=
830 <:xhtmllist
< <p
>Write a
string:
831 $string_input ~input_type
:`Text ~name
:s
()$
<br
/>
832 $string_input ~input_type
:`Submit ~
value:"Click" ()$
</p
> >>
834 let suffixform_su2 = register_service
["suffixform_su2"] unit
836 let f = get_form
su2 create_suffixform_su2 in
839 (head
(title
(pcdata
"")) [])
840 (body
[h1
[pcdata
"Hallo"];
843 (* optional parameters *)
847 ~get_params
:(Eliom_parameters.opt
(Eliom_parameters.string "a" **
848 Eliom_parameters.string "b"))
852 (head
(title
(pcdata
"")) [])
853 (body
[h1
[pcdata
"Hallo!"];
855 | None
-> p
[pcdata
"no parameters"]
856 | Some
(a
, b
) -> p
[pcdata a
;
868 (* testing lwt_get_form *)
869 Eliom_output.Xhtml.lwt_get_form
874 string_input ~input_type
:`Text ~name
:an
();
875 string_input ~input_type
:`Text ~name
:bn
();
876 Eliom_output.Xhtml.string_input
881 (form : XHTML_types.form XHTML.M.elt
:> [> XHTML_types.form ] XHTML.M.elt
)
885 (head
(title
(pcdata
"")) [])
886 (body
[h1
[pcdata
"Hallo!"];
893 (* Preapplied service with suffix parameters *)
897 ~path
: ["preappliedsuffix2"]
898 ~get_params
: (suffix
(int "i"))
902 (head
(title
(pcdata
"")) [])
903 (body
[p
[ pcdata
("You sent: " ^
(string_of_int i
))]])))
906 let creator_handler () () =
908 [fieldset
[string_input ~input_type
:`Submit ~
value:"Click" ()]] in
909 let myservice = preapply
presu_service 10 in
910 let myform = get_form
myservice create_form in
913 (head
(title
(pcdata
"")) [])
915 p
[pcdata
"Form with preapplied parameter:"];
917 p
[a
myservice [pcdata
"Link with preapplied parameter"] ()]
920 let preappliedsuffix =
922 ~path
: ["preappliedsuffix"]
927 (* URL with ? or / in data or paths *)
931 ~path
:["urlencoding&à /=é?ablah"]
932 ~get_params
:(suffix_prod
(all_suffix
"s//\\Ã ") any
)
936 (fun (a
,s
) -> <:xhtml
< <strong
>($str
:a$
, $str
:s$
) </strong
> >>) l
940 (fun s
-> <:xhtml
< <strong
>$str
:s$
</strong
> >>) suf
944 (head
(title
(pcdata
"")) [])
945 (body
[h1
[pcdata
"Hallo"];
951 (* menu with preapplied services *)
953 let preappl = preapply coucou_params
(3,(4,"cinq"))
954 let preappl2 = preapply uasuffix
(1999,01)
957 Eliom_tools.Xhtml.menu ~classe
:["menuprincipal"]
958 (coucou
, <:xhtmllist
< coucou
>>)
960 (preappl, <:xhtmllist
< params
>>);
961 (preappl2, <:xhtmllist
< params
and suffix
>>);
962 ] ~service
:current
()
971 (head
(title
(pcdata
"")) [])
972 (body
[h1
[pcdata
"Hallo"];
978 (* GET Non-attached coservice *)
979 let nonatt = coservice' ~get_params
:(string "e") ()
981 (* GET coservice with preapplied fallback *)
982 (* + Non-attached coservice on a pre-applied coservice *)
983 (* + Non-attached coservice on a non-attached coservice *)
986 (head
(title
(pcdata
"")) [])
987 (body
[h1
[pcdata s
];
988 p
[a
nonatt [pcdata
"clic"] "nonon"];
991 [p
[pcdata
"Non attached coservice: ";
992 string_input ~input_type
:`Text ~name
:string_name
();
993 string_input ~input_type
:`Submit ~
value:"Click" ()]])
996 let getco = register_coservice
998 ~get_params
:(int "i" ** string "s")
999 (fun (i
,s
) () -> return
(f s
))
1001 let _ = register
nonatt (fun s
() -> return
(f s
))
1010 (head
(title
(pcdata
"")) [])
1011 (body
[p
[a
getco [pcdata
"clic"] (22,"eee") ];
1013 (fun (number_name
,string_name
) ->
1014 [p
[pcdata
"Write an int: ";
1015 int_input ~input_type
:`Text ~name
:number_name
();
1016 pcdata
"Write a string: ";
1017 string_input ~input_type
:`Text ~name
:string_name
();
1018 string_input ~input_type
:`Submit ~
value:"Click" ()]])
1022 (* POST service with preapplied fallback are not possible: *)
1024 let my_service_with_post_params =
1025 register_post_service
1027 ~post_params:(string "value")
1028 (fun () value -> return
1030 (head (title (pcdata "")) [])
1031 (body [h1 [pcdata value]])))
1034 (* GET coservice with coservice fallback: not possible *)
1036 let preappl3 = preapply getco (777,"ooo")
1041 ~get_params:(int "i2" ** string "s2")
1045 (head (title (pcdata "")) [])
1046 (body [h1 [pcdata s]])))
1051 (* POST service with coservice fallback *)
1052 let my_service_with_post_params =
1053 register_post_service
1055 ~post_params
:(string "value")
1056 (fun (i
,s
) value -> return
1058 (head
(title
(pcdata
"")) [])
1059 (body
[h1
[pcdata
(s^
" "^
value)]])))
1061 let postcoex = register_service
["postco"] unit
1064 (post_form
my_service_with_post_params
1066 [p
[pcdata
"Write a string: ";
1067 string_input ~input_type
:`Text ~name
:chaine
()]])
1071 (head
(title
(pcdata
"form")) [])
1075 (* action on GET attached coservice *)
1081 ~get_params
:(int "p")
1084 let act = Action.register_coservice
1085 ~fallback
:(preapply
getact 22)
1086 ~get_params
:(int "bip")
1087 (fun g p
-> v := g
; return
())
1089 (* action on GET non-attached coservice on GET coservice page *)
1090 let naact = Action.register_coservice'
1091 ~get_params
:(int "bop")
1092 (fun g p
-> v := g
; return
())
1094 let naunit = Unit.register_coservice'
1095 ~get_params
:(int "bap")
1096 (fun g p
-> v := g
; return
())
1104 (head
(title
(pcdata
"getact")) [])
1105 (body
[h1
[pcdata
("v = "^
(string_of_int
!v))];
1106 p
[pcdata
("p = "^
(string_of_int aa
))];
1107 p
[a
getact [pcdata
"link to myself"] 0;
1109 a
act [pcdata
"an attached action to change v"]
1112 a
naact [pcdata
"a non attached action to change v"]
1113 (100 + Random.int 100);
1114 pcdata
" (Actually if called after the previous one, v won't change. More precisely, it will change and turn back to the former value because the attached coservice is reloaded after action)";
1116 a
naunit [pcdata
"a non attached \"Unit\" page to change v"]
1117 (200 + Random.int 100);
1118 pcdata
" (Reload after clicking here)"
1125 let cookiename = "c"
1127 let cookies2 = service
["c";""] (suffix
(all_suffix_string
"s")) ()
1129 let _ = Eliom_output.Xhtml.register
cookies2
1131 let now = Unix.time
() in
1132 Eliom_state.set_cookie
1133 ~path
:[] ~exp
:(now +. 10.) ~name
:(cookiename^
"6")
1134 ~
value:(string_of_int
(Random.int 100)) ~secure
:true ();
1135 Eliom_state.set_cookie
1136 ~path
:[] ~exp
:(now +. 10.) ~name
:(cookiename^
"7")
1137 ~
value:(string_of_int
(Random.int 100)) ~secure
:true ();
1138 Eliom_state.set_cookie
1139 ~path
:["c";"plop"] ~name
:(cookiename^
"8")
1140 ~
value:(string_of_int
(Random.int 100)) ();
1141 Eliom_state.set_cookie
1142 ~path
:["c";"plop"] ~name
:(cookiename^
"9")
1143 ~
value:(string_of_int
(Random.int 100)) ();
1144 Eliom_state.set_cookie
1145 ~path
:["c";"plop"] ~name
:(cookiename^
"10")
1146 ~
value:(string_of_int
(Random.int 100)) ~secure
:true ();
1147 Eliom_state.set_cookie
1148 ~path
:["c";"plop"] ~name
:(cookiename^
"11")
1149 ~
value:(string_of_int
(Random.int 100)) ~secure
:true ();
1150 Eliom_state.set_cookie
1151 ~path
:["c";"plop"] ~name
:(cookiename^
"12")
1152 ~
value:(string_of_int
(Random.int 100)) ~secure
:true ();
1153 if CookiesTable.mem
(cookiename^
"1") (Eliom_request_info.get_cookies
())
1155 (Eliom_state.unset_cookie ~name
:(cookiename^
"1") ();
1156 Eliom_state.unset_cookie ~name
:(cookiename^
"2") ())
1158 Eliom_state.set_cookie
1159 ~name
:(cookiename^
"1") ~
value:(string_of_int
(Random.int 100))
1161 Eliom_state.set_cookie
1162 ~name
:(cookiename^
"2") ~
value:(string_of_int
(Random.int 100)) ();
1163 Eliom_state.set_cookie
1164 ~name
:(cookiename^
"3") ~
value:(string_of_int
(Random.int 100)) ()
1169 (head
(title
(pcdata
"")) [])
1173 (pcdata
(n^
"="^
v))::
1176 (Eliom_request_info.get_cookies
())
1177 [a
cookies2 [pcdata
"send other cookies"] ""; br
();
1178 a
cookies2 [pcdata
"send other cookies and see the url /c/plop"] "plop"]
1193 (head
(title
(pcdata
"")) [])
1194 (body
[h1
[pcdata
"With a suffix, that page will send a file"]])))
1197 Files.register_service
1199 ~get_params
:(suffix
(all_suffix
"filename"))
1201 return
("/var/www/ocsigen/"^
(Url.string_of_url_path ~encode
:false s
)))
1203 let sendfileexception =
1205 ~path
:["files";"exception"]
1210 (head
(title
(pcdata
"")) [])
1211 (body
[h1
[pcdata
"With another suffix, that page will send a file"]])))
1214 (* Complex suffixes *)
1217 ~path
:["suffix2";""]
1218 ~get_params
:(suffix
(string "suff1" ** int "ii" ** all_suffix
"ee"))
1223 (fun (suf1
, (ii
, ee
)) () ->
1226 (head
(title
(pcdata
"")) [])
1228 [p
[pcdata
"The suffix of the url is ";
1229 strong
[pcdata
(suf1^
", "^
(string_of_int ii
)^
", "^
1230 (Url.string_of_url_path ~encode
:false ee
))]];
1231 p
[a
suffix2 [pcdata
"link to myself"] ("a", (2, []))]])))
1235 ~path
:["suffix3";""]
1236 ~get_params
:(suffix_prod
1237 (string "suff1" ** int "ii" **
1238 all_suffix_user int_of_string string_of_int
"ee")
1239 (string "a" ** int "b"))
1240 (fun ((suf1
, (ii
, ee
)), (a
, b
)) () ->
1243 (head
(title
(pcdata
"")) [])
1245 [p
[pcdata
"The parameters in the url are ";
1246 strong
[pcdata
(suf1^
", "^
(string_of_int ii
)^
", "^
1247 (string_of_int ee
)^
", "^
1248 a^
", "^
(string_of_int b
))]]])))
1250 let create_suffixform2 (suf1
, (ii
, ee
)) =
1251 <:xhtmllist
< <p
>Write a
string:
1252 $string_input ~input_type
:`Text ~name
:suf1
()$
<br
/>
1253 Write an
int: $int_input ~input_type
:`Text ~name
:ii
()$
<br
/>
1254 Write a
string: $user_type_input
1255 (Url.string_of_url_path ~encode
:false)
1256 ~input_type
:`Text ~name
:ee
()$
<br
/>
1257 $string_input ~input_type
:`Submit ~
value:"Click" ()$
</p
> >>
1259 let suffixform2 = register_service
["suffixform2"] unit
1261 let f = get_form
suffix2 create_suffixform2 in
1264 (head
(title
(pcdata
"")) [])
1265 (body
[h1
[pcdata
"Hallo"];
1268 let create_suffixform3 ((suf1
, (ii
, ee
)), (a
, b
)) =
1269 <:xhtmllist
< <p
>Write a
string:
1270 $string_input ~input_type
:`Text ~name
:suf1
()$
<br
/>
1271 Write an
int: $int_input ~input_type
:`Text ~name
:ii
()$
<br
/>
1272 Write an
int: $int_input ~input_type
:`Text ~name
:ee
()$
<br
/>
1273 Write a
string: $string_input ~input_type
:`Text ~name
:a
()$
<br
/>
1274 Write an
int: $int_input ~input_type
:`Text ~name
:b
()$
<br
/>
1275 $string_input ~input_type
:`Submit ~
value:"Click" ()$
</p
> >>
1277 let suffixform3 = register_service
["suffixform3"] unit
1279 let f = get_form
suffix3 create_suffixform3 in
1282 (head
(title
(pcdata
"")) [])
1283 (body
[h1
[pcdata
"Hallo"];
1289 ~get_params
:(suffix
(all_suffix
"s"))
1293 (head
(title
(pcdata
"")) [])
1295 [p
[pcdata
"This is a page with suffix ";
1296 strong
[pcdata
(Url.string_of_url_path
1297 ~encode
:false s
)]]])))
1301 ~path
:["suffix5";"notasuffix"]
1306 (head
(title
(pcdata
"")) [])
1308 [p
[pcdata
"This is a page without suffix. Replace ";
1309 code
[pcdata
"notasuffix"];
1310 pcdata
" in the URL by something else."
1315 (* Send file with regexp *)
1316 let sendfileregexp =
1323 (head
(title
(pcdata
"")) [])
1324 (body
[h1
[pcdata
"With a suffix, that page will send a file"]])))
1326 let r = Netstring_pcre.regexp
"~([^/]*)(.*)"
1329 Files.register_service
1331 (* ~get_params:(regexp r "/home/$1/public_html$2" "filename") *)
1332 ~get_params
:(suffix ~redirect_if_not_suffix
:false
1333 (all_suffix_regexp
r "$u($1)/public_html$2"
1334 ~to_string
:(fun s
-> s
) "filename"))
1335 (fun s
() -> return s
)
1337 (* Here I am using redirect_if_not_suffix:false because
1338 otherwise I would need to write a more sophisticated to_string function *)
1342 Files.register_service
1345 (all_suffix_regexp r "/home/$1/public_html$2" "filename"))
1346 (* ~get_params:(suffix (all_suffix_regexp r "$$u($1)$2" "filename")) *)
1347 (fun s
() -> return s
)
1350 let create_suffixform4 n
=
1351 <:xhtmllist
< <p
>Write the name
of the file
:
1352 $string_input ~input_type
:`Text ~name
:n
()$
1353 $string_input ~input_type
:`Submit ~
value:"Click" ()$
</p
> >>
1355 let suffixform4 = register_service
["suffixform4"] unit
1357 let f = get_form
sendfile2 create_suffixform4 in
1360 (head
(title
(pcdata
"")) [])
1361 (body
[h1
[pcdata
"Hallo"];
1365 (* Advanced use of any *)
1366 let any2 = register_service
1368 ~get_params
:(int "i" ** any
)
1372 (fun (a
,s
) -> <:xhtml
< <strong
>($str
:a$
, $str
:s$
)</strong
> >>) l
1376 <head
><title
></title
></head
>
1380 <span
>$list
:ll$
</span
>
1382 i
= $str
:(string_of_int i
)$
1387 (* the following will not work because s is taken in any. (not checked) *)
1388 let any3 = register_service
1390 ~get_params
:(int "i" ** any
** string "s")
1391 (fun (i
,(l,s
)) () ->
1394 (fun (a
,s
) -> <:xhtml
< <strong
>($str
:a$
, $str
:s$
)</strong
> >>) l
1398 <head
><title
></title
></head
>
1402 <span
>$list
:ll$
</span
>
1404 i
= $str
:(string_of_int i
)$
1412 (* any cannot be in suffix: (not checked) *)
1413 let any4 = register_service
1415 ~get_params
:(suffix any
)
1419 (fun (a
,s
) -> <:xhtml
< <strong
>($str
:a$
, $str
:s$
)</strong
> >>) l
1423 <head
><title
></title
></head
>
1427 <span
>$list
:ll$
</span
>
1433 let any5 = register_service
1435 ~get_params
:(suffix_prod
(string "s") any
)
1439 (fun (a
,s
) -> <:xhtml
< <strong
>($str
:a$
, $str
:s$
)</strong
> >>) l
1443 <head
><title
></title
></head
>
1446 You sent
<strong
>$str
:s$
</strong
> and :
1447 <span
>$list
:ll$
</span
>
1452 (* list in suffix *)
1455 ~get_params
:(suffix
(list
"l" (string "s" ** int "i")))
1458 let _ = register
sufli
1462 (fun (s
, i
) -> <:xhtml
< <strong
> $str
:(s^string_of_int i
)$
</strong
> >>) l
1466 <head
><title
></title
></head
>
1470 <span
>$list
:ll$
</span
>
1473 $a
sufli [pcdata
"myself"] [("a", 2)]$
,
1474 $a
sufli [pcdata
"myself (empty list)"] []$
1479 let create_sufliform f =
1481 f.it
(fun (sn
, iname
) v init
->
1482 (tr
(td
[pcdata
("Write a string: ")])
1483 [td
[string_input ~input_type
:`Text ~name
:sn
()];
1484 td
[pcdata
("Write an integer: ")];
1485 td
[int_input ~input_type
:`Text ~name
:iname
()];
1487 ["one";"two";"three"]
1490 [table
(List.hd
l) (List.tl
l);
1491 p
[string_input ~input_type
:`Submit ~
value:"Click" ()]]
1493 let sufliform = register_service
["sufliform"] unit
1495 let f = get_form
sufli create_sufliform in
1498 (head
(title
(pcdata
"")) [])
1499 (body
[h1
[pcdata
"Hallo"];
1503 (* mmmh ... disabled dynamically for now *)
1504 let sufli2 = service
1506 ~get_params
:(suffix
((list
"l" (int "i")) ** int "j"))
1509 let _ = register
sufli2
1512 List.map
(fun i
-> <:xhtml
< <strong
> $str
:(string_of_int i
)$
</strong
> >>) l
1516 <head
><title
></title
></head
>
1520 <span
>$list
:ll$
</span
>,
1522 j
=$str
:string_of_int j$
.
1525 $a
sufli2 [pcdata
"myself"] ([1; 2], 3)$
,
1526 $a
sufli2 [pcdata
"myself (empty list)"] ([], 1)$
1532 let sufliopt = service
1534 ~get_params
:(suffix
(list
"l" (opt
(string "s"))))
1537 let _ = register
sufliopt
1541 (function None
-> pcdata
"<none>"
1542 | Some s
-> <:xhtml
< <strong
> $str
:s$
</strong
> >>) l
1546 <head
><title
></title
></head
>
1550 <span
>$list
:ll$
</span
>
1553 $a
sufliopt [pcdata
"myself"] [Some
"a"; None
; Some
"po"; None
; None
; Some
"k"; None
]$
,
1554 $a
sufliopt [pcdata
"myself (empty list)"] []$
1555 $a
sufliopt [pcdata
"myself (list [None; None])"] [None
; None
]$
1556 $a
sufliopt [pcdata
"myself (list [None])"] [None
]$
1562 let sufliopt2 = service
1564 ~get_params
:(suffix
(list
"l" (opt
(string "s" ** string "ss"))))
1567 let _ = register
sufliopt2
1571 (function None
-> pcdata
"<none>"
1572 | Some
(s
, ss
) -> <:xhtml
< <strong
> ($str
:s$
, $str
:ss$
) </strong
> >>) l
1576 <head
><title
></title
></head
>
1580 <span
>$list
:ll$
</span
>
1583 $a
sufliopt2 [pcdata
"myself"] [Some
("a", "jj"); None
; Some
("po", "jjj"); None
; None
; Some
("k", "pp"); None
]$
,
1584 $a
sufliopt2 [pcdata
"myself (empty list)"] []$
1585 $a
sufliopt2 [pcdata
"myself (list [None; None])"] [None
; None
]$
1586 $a
sufliopt2 [pcdata
"myself (list [None])"] [None
]$
1593 let sufset = register_service
1595 ~get_params
:(suffix
(Eliom_parameters.set
string "s"))
1599 (fun s
-> <:xhtml
< <strong
>$str
:s$
</strong
> >>) l
1603 <head
><title
></title
></head
>
1607 <span
>$list
:ll$
</span
>
1615 let any2form = register_service
1621 (head
(title
(pcdata
"")) [])
1622 (body
[h1
[pcdata
"Any Form"];
1625 [p
[pcdata
"Form to any2: ";
1626 int_input ~input_type
:`Text ~name
:iname
();
1627 raw_input ~input_type
:`Text ~name
:"plop" ();
1628 raw_input ~input_type
:`Text ~name
:"plip" ();
1629 raw_input ~input_type
:`Text ~name
:"plap" ();
1630 string_input ~input_type
:`Submit ~
value:"Click" ()]])
1636 let boollist = register_service
1638 ~get_params
:(list
"a" (bool "b"))
1642 (strong
[pcdata
(if b
then "true" else "false")])) l in
1645 (head
(title
(pcdata
"")) [])
1647 [p
((pcdata
"You sent: ")::ll)]
1650 let create_listform f =
1651 (* Here, f.it is an iterator like List.map,
1652 but it must be applied to a function taking 2 arguments
1653 (and not 1 as in map), the first one being the name of the parameter.
1654 The last parameter of f.it is the code that must be appended at the
1655 end of the list created
1658 f.it
(fun boolname
v init
->
1659 (tr
(td
[pcdata
("Write the value for "^
v^
": ")])
1660 [td
[bool_checkbox ~name
:boolname
()]])::init
)
1661 ["one";"two";"three"]
1664 [table
(List.hd
l) (List.tl
l);
1665 p
[raw_input ~input_type
:`Submit ~
value:"Click" ()]]
1667 let boollistform = register_service
["boolform"] unit
1669 let f = get_form
boollist create_listform in return
1671 (head
(title
(pcdata
"")) [])
1684 (head
(title
(pcdata
"")) [])
1685 (body
[h1
[pcdata
"Hallo!"]])))
1688 let any = register_post_service
1694 (fun (a
,s
) -> <:xhtml
< <strong
>($str
:a$
, $str
:s$
)</strong
> >>) l
1698 <head
><title
></title
></head
>
1708 let anypostform = register_service
1709 ~path
:["anypostform"]
1714 (head
(title
(pcdata
"")) [])
1715 (body
[h1
[pcdata
"Any Form"];
1718 [p
[pcdata
"Empty form to any: ";
1719 string_input ~input_type
:`Submit ~
value:"Click" ()]])
1726 (* ce qui suit ne doit pas fonctionner. Mais il faudrait l'interdire *)
1727 let get_param_service =
1730 ~get_params
:(string "name" ** file
"file")
1731 (fun (name
,file
) () ->
1733 let newname = "/tmp/fichier" in
1735 Unix.unlink
newname;
1737 Unix.link
(Eliom_request_info.get_tmp_filename file
) newname;
1738 let fd_in = open_in
newname in
1740 let line = input_line
fd_in in close_in
fd_in; line (*end*)
1741 with End_of_file
-> close_in
fd_in; "vide"
1745 (head
(title
(pcdata name
)) [])
1746 (body
[h1
[pcdata
to_display]])))
1749 let uploadgetform = register_service
["uploadget"] unit
1752 (* ARG (post_form ~a:[(XHTML.M.a_enctype "multipart/form-data")] fichier2 *)
1753 (get_form ~a
:[(XHTML.M.a_enctype
"multipart/form-data")] ~service
:get_param_service
1754 (*post_form my_service_with_post_params *)
1756 [p
[pcdata
"Write a string: ";
1757 string_input ~input_type
:`Text ~name
:str
();
1759 file_input ~name
:file
()]])) in return
1761 (head
(title
(pcdata
"form")) [])
1766 (* Actions that raises an exception *)
1767 let exn_act = Action.register_coservice'
1769 (fun g p
-> fail Not_found
)
1778 (head
(title
(pcdata
"exnact")) [])
1779 (body
[h1
[pcdata
"Hello"];
1780 p
[a
exn_act [pcdata
"Do the action"] ()
1784 let action_example2_scope =
1785 `Session
(Eliom_common.create_scope_name
"action_example2")
1787 (* close sessions from outside *)
1788 let close_from_outside =
1790 ~path
:["close_from_outside"]
1793 lwt
() = discard_all ~scope
:persistent_session_scope
() in
1794 lwt
() = discard_all ~scope
:action_example2_scope () in
1797 (head
(title
(pcdata
"")) [])
1798 (body
[h1
[pcdata
"all sessions called \"persistent_sessions\" and \"action_example2\" closed"];
1799 p
[a persist_session_example
[pcdata
"try"] ()]])))
1803 (* setting timeouts *)
1806 ~path
:["set_timeout"]
1807 ~get_params
:(int "t" ** (bool "recompute" ** bool "overrideconfig"))
1808 (fun (t
, (recompute
, override_configfile
)) () ->
1809 set_global_persistent_data_state_timeout
1810 ~override_configfile
1811 ~scope
:persistent_session_scope
1812 ~recompute_expdates
:recompute
(Some
(float_of_int t
));
1813 set_global_volatile_state_timeout
1814 ~override_configfile
1815 ~scope
:action_example2_scope
1816 ~recompute_expdates
:recompute
(Some
(float_of_int t
));
1819 (head
(title
(pcdata
"")) [])
1820 (body
[h1
[pcdata
"Setting timeout"];
1823 then pcdata
("The timeout for sessions called \"persistent_sessions\" and \"action_example2\" has been set to "^
(string_of_int t
)^
" seconds (all expiration dates updated).")
1824 else pcdata
("From now, the timeout for sessions called \"persistent_sessions\" and \"action_example2\" will be "^
(string_of_int t
)^
" seconds (expiration dates not updated)."); br
();
1825 a persist_session_example
[pcdata
"Try"] ()]])))
1829 (fun (number_name
, (bool1name
, bool2name
)) ->
1830 [p
[pcdata
"New timeout: ";
1831 Eliom_output.Xhtml.int_input ~input_type
:`Text ~name
:number_name
();
1833 pcdata
"Check the box if you want to recompute all timeouts: ";
1834 Eliom_output.Xhtml.bool_checkbox ~name
:bool1name
();
1836 pcdata
"Check the box if you want to override configuration file: ";
1837 Eliom_output.Xhtml.bool_checkbox ~name
:bool2name
();
1838 Eliom_output.Xhtml.string_input ~input_type
:`Submit ~
value:"Submit" ()]])
1840 let set_timeout_form =
1845 let f = Eliom_output.Xhtml.get_form
set_timeout create_form in
1848 (head
(title
(pcdata
"")) [])
1853 (******************************************************************)
1859 (fun () () -> failwith
"Bad use of exceptions")
1865 (fun () () -> Lwt.fail
(Failure
"Service raising an exception"))
1868 (*****************************************************************************)
1870 (* 2011/08/02 Vincent - Volatile group data
1871 removing group data or not when no session in the group?*)
1874 open Eliom_output.Html5
1877 let scope_name = Eliom_common.create_scope_name
"session_group_data_example_state"
1878 let session = `Session
scope_name
1879 let group = `Session_group
scope_name
1881 (* -------------------------------------------------------- *)
1882 (* We create one main service and two (POST) actions *)
1883 (* (for connection and disconnection) *)
1885 let connect_example_gd =
1886 Eliom_services.service
1887 ~path
:["sessgrpdata"]
1891 let connect_action =
1892 Eliom_services.post_coservice'
1893 ~name
:"connectiongd"
1894 ~post_params
:(string "login")
1897 (* disconnect action and box: *)
1899 let disconnect_action =
1900 Eliom_output.Action.register_post_coservice'
1901 ~name
:"disconnectiongd"
1902 ~post_params
:Eliom_parameters.unit
1903 (fun () () -> Eliom_state.discard ~scope
:session ())
1905 let disconnect_box s
=
1906 Eliom_output.Html5.post_form
disconnect_action
1907 (fun _ -> [p
[Eliom_output.Html5.string_input
1908 ~input_type
:`Submit ~
value:s
()]]) ()
1910 (* The following eref is true if the connection has action failed: *)
1911 let bad_user = Eliom_references.eref ~scope
:Eliom_common.request
false
1913 let my_group_data = Eliom_references.eref ~scope
:group None
1916 Eliom_output.Action.register_post_coservice'
1918 ~post_params
:Eliom_parameters.unit
1919 (fun () () -> Eliom_references.set
my_group_data (Some
(1000 + Random.int 1000)))
1921 (* -------------------------------------------------------- *)
1922 (* new login box: *)
1924 let login_box session_expired bad_u action
=
1925 Eliom_output.Html5.post_form action
1929 Eliom_output.Html5.string_input ~input_type
:`Text ~name
:loginname
()]
1932 then (pcdata
"Wrong user")::(br
())::l
1935 then (pcdata
"Session expired")::(br
())::l
1940 (* -------------------------------------------------------- *)
1941 (* Handler for the "connect_example" service (main page): *)
1943 let connect_example_handler () () =
1944 (* The following function tests whether the session has expired: *)
1945 let status = Eliom_state.volatile_data_state_status
(*zap* *) ~scope
:session (* *zap*) ()
1948 Eliom_state.get_volatile_data_session_group
(*zap* *) ~scope
:session (* *zap*) ()
1950 Eliom_references.get
bad_user >>= fun bad_u
->
1951 Eliom_references.get
my_group_data >>= fun my_group_data ->
1954 (head
(title
(pcdata
"")) [])
1956 (match group, status with
1958 [p
[pcdata
("Hello "^name
); br
();
1959 (match my_group_data with
1960 | None
-> pcdata
"You have no group data."
1961 | Some i
-> pcdata
("Your group data is "^string_of_int i^
"."))];
1962 Eliom_output.Html5.post_form
change_gd
1963 (fun () -> [p
[Eliom_output.Html5.string_input
1965 ~
value:"Change group data" ()]]) ();
1966 p
[pcdata
"Check that several sessions have the same group data."];
1967 p
[pcdata
"Volatile group data are currently discarded when all group disappear. This is weird and not coherent with persistent group data. But I don't really see a correct use of volatile group data. Is there any? And there is a risk of memory leak if we keep them. Besides, volatile sessions are (hopefully) going to disappear soon."];
1968 disconnect_box "Close session"]
1969 | None
, Eliom_state.Expired_state
->
1970 [login_box true bad_u
connect_action;
1971 p
[em
[pcdata
"The only user is 'toto'."]]]
1973 [login_box false bad_u
connect_action;
1974 p
[em
[pcdata
"The only user is 'toto'."]]]
1977 (* -------------------------------------------------------- *)
1978 (* Handler for connect_action (user logs in): *)
1980 let connect_action_handler () login
=
1981 lwt
() = Eliom_state.discard ~scope
:session () in
1982 if login
= "toto" (* Check user and password :-) *)
1984 Eliom_state.set_volatile_data_session_group ~set_max
:4 (*zap* *) ~scope
:session (* *zap*) login
;
1985 Eliom_references.get
my_group_data >>= fun mgd
->
1987 then Eliom_references.set
my_group_data (Some
(Random.int 1000))
1988 else Lwt.return
()) >>= fun () ->
1989 Eliom_output.Redirection.send
Eliom_services.void_hidden_coservice'
1992 Eliom_references.set
bad_user true >>= fun () ->
1993 Eliom_output.Action.send
()
1996 (* -------------------------------------------------------- *)
1997 (* Registration of main services: *)
2000 Eliom_output.Html5.register ~service
:connect_example_gd connect_example_handler;
2001 Eliom_output.Any.register ~service
:connect_action connect_action_handler
2004 (*****************************************************************************)
2006 (* 2011/08/02 Vincent - Persistent group data
2007 removing group data or not when no session in the group? *)
2012 let scope_name = Eliom_common.create_scope_name
"pers_session_group_data_example_state"
2013 let session = `Session
scope_name
2014 let group = `Session_group
scope_name
2016 (* -------------------------------------------------------- *)
2017 (* We create one main service and two (POST) actions *)
2018 (* (for connection and disconnection) *)
2020 let connect_example_pgd =
2021 Eliom_services.service
2022 ~path
:["psessgrpdata"]
2026 let connect_action =
2027 Eliom_services.post_coservice'
2028 ~name
:"connectionpgd"
2029 ~post_params
:(string "login")
2032 (* disconnect action and box: *)
2034 let disconnect_action =
2035 Eliom_output.Action.register_post_coservice'
2036 ~name
:"disconnectionpgd"
2037 ~post_params
:Eliom_parameters.unit
2038 (fun () () -> Eliom_state.discard ~scope
:session ())
2040 let disconnect_box s
=
2041 Eliom_output.Html5.post_form
disconnect_action
2042 (fun _ -> [p
[Eliom_output.Html5.string_input
2043 ~input_type
:`Submit ~
value:s
()]]) ()
2045 (* The following eref is true if the connection has action failed: *)
2046 let bad_user = Eliom_references.eref ~scope
:Eliom_common.request
false
2048 let my_group_data = Eliom_references.eref ~persistent
:"pgd" ~scope
:group None
2051 Eliom_output.Action.register_post_coservice'
2053 ~post_params
:Eliom_parameters.unit
2054 (fun () () -> Eliom_references.set
my_group_data (Some
(1000 + Random.int 1000)))
2057 (* -------------------------------------------------------- *)
2058 (* new login box: *)
2060 let login_box session_expired bad_u action
=
2061 Eliom_output.Html5.post_form action
2065 Eliom_output.Html5.string_input ~input_type
:`Text ~name
:loginname
()]
2068 then (pcdata
"Wrong user")::(br
())::l
2071 then (pcdata
"Session expired")::(br
())::l
2076 (* -------------------------------------------------------- *)
2077 (* Handler for the "connect_example" service (main page): *)
2079 let connect_example_handler () () =
2080 (* The following function tests whether the session has expired: *)
2081 let status = Eliom_state.volatile_data_state_status
(*zap* *) ~scope
:session (* *zap*) ()
2084 Eliom_state.get_volatile_data_session_group
(*zap* *) ~scope
:session (* *zap*) ()
2086 Eliom_references.get
bad_user >>= fun bad_u
->
2087 Eliom_references.get
my_group_data >>= fun my_group_data ->
2090 (head
(title
(pcdata
"")) [])
2092 (match group, status with
2094 [p
[pcdata
("Hello "^name
); br
();
2095 (match my_group_data with
2096 | None
-> pcdata
"You have no group data."
2097 | Some i
-> pcdata
("Your group data is "^string_of_int i^
"."));
2099 Eliom_output.Html5.post_form
change_gd
2100 (fun () -> [p
[Eliom_output.Html5.string_input
2102 ~
value:"Change group data" ()]]) ();
2103 p
[pcdata
"Check that several sessions have the same group data."];
2104 p
[pcdata
"Check that persistent group data do not disappear when all sessions from the group are closed."];
2105 p
[pcdata
"Persistent group data are used as a basic database, for example to store user information (email, etc)."];
2106 disconnect_box "Close session"]
2107 | None
, Eliom_state.Expired_state
->
2108 [login_box true bad_u
connect_action;
2109 p
[em
[pcdata
"The only user is 'toto'."]]]
2111 [login_box false bad_u
connect_action;
2112 p
[em
[pcdata
"The only user is 'toto'."]]]
2115 (* -------------------------------------------------------- *)
2116 (* Handler for connect_action (user logs in): *)
2118 let connect_action_handler () login
=
2119 lwt
() = Eliom_state.discard ~scope
:session () in
2120 if login
= "toto" (* Check user and password :-) *)
2122 Eliom_state.set_volatile_data_session_group ~set_max
:4 (*zap* *) ~scope
:session (* *zap*) login
;
2123 Eliom_references.get
my_group_data >>= fun mgd
->
2125 then Eliom_references.set
my_group_data (Some
(Random.int 1000))
2126 else Lwt.return
()) >>= fun () ->
2127 Eliom_output.Redirection.send
Eliom_services.void_hidden_coservice'
2130 Eliom_references.set
bad_user true >>= fun () ->
2131 Eliom_output.Action.send
()
2134 (* -------------------------------------------------------- *)
2135 (* Registration of main services: *)
2138 Eliom_output.Html5.register ~service
:connect_example_pgd connect_example_handler;
2139 Eliom_output.Any.register ~service
:connect_action connect_action_handler
2142 (*****************************************************************************)
2143 (* Actions with `NoReload option *)
2144 let noreload_ref = ref 0
2146 let noreload_action =
2147 Eliom_output.Action.register_coservice'
2150 (fun () () -> noreload_ref := !noreload_ref + 1; Lwt.return
())
2159 (head
(title
(pcdata
"counter")) [])
2160 (body
[p
[pcdata
(string_of_int
(!noreload_ref)); br
();
2161 Eliom_output.Html5.a ~service
:noreload_action
2162 [pcdata
"Click to increment the counter."] ();
2164 pcdata
"You should not see the result if you do not reload the page."