package eliom
Advanced client/server Web and mobile framework
Install
Dune Dependency
Authors
Maintainers
Sources
10.4.1.tar.gz
md5=218bcb5cd275cc05be06574c5fa357fa
sha512=edbf8b084ec1b7439d4715199c22eb925a77a2dcfbe76bb5bbc4b9d076b70be1b0de74f9eab9dfb7854df28d65eb31a4c17380528d4a461d9c2a4222abe804cc
doc/src/eliom.server/eliommod_pagegen.ml.html
Source file eliommod_pagegen.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
(* Ocsigen * http://www.ocsigen.org * Module eliommod_pagegen.ml * Copyright (C) 2007 Vincent Balat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, with linking exception; * either version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) open Lwt.Infix let headers_with_content_type headers = Cohttp.Header.add_opt headers Ocsigen_header.Name.(to_string content_type) (Printf.sprintf "%s; charset=utf-8" Eliom_content_core.Html.D.Info.content_type) let out = let encode x = fst (Xml_print.Utf8.normalize_html x) in Eliom_content_core.Html.Printer.pp ~encode () let make_response ?headers ~status body = let body = Cohttp_lwt.Body.of_string (Format.asprintf "%a" out body) and response = let headers = headers_with_content_type headers in Cohttp.Response.make ~status ~headers () in Lwt.return (Ocsigen_response.make ~body response) (* module Html_content = Ocsigen_senders.Make_XML_Content(Xml)(Html.F) *) (* Exception handler for the site *) let def_handler e = Lwt.fail e (* Update cookie tables *) let ?now sitedata (ci, sci) = let now = match now with Some n -> n | None -> Unix.gettimeofday () in let update_exp (, , ) = (* Update service expiration date and value *) Eliom_common.Full_state_name_table.iter (fun name (_oldvalue, newr) -> (* catch fun () -> *) match !newr with | Eliom_common.SCData_session_expired | Eliom_common.SCNo_data -> () (* The cookie has been removed *) | Eliom_common.SC newc -> ( newc.Eliom_common.sc_exp := match !(newc.Eliom_common.sc_timeout) with | Eliom_common.TGlobal -> ( let globaltimeout = Eliommod_timeouts.find_global `Service name sitedata in match globaltimeout with | None -> None | Some t -> Some (t +. now)) | Eliom_common.TNone -> None | Eliom_common.TSome t -> Some (t +. now))) !service_cookies_info; (* Update "in memory data" expiration date and value *) Eliom_common.Full_state_name_table.iter (fun name v -> (* 2018-07-17 We do this for all volatile sessions, even if it has not been used, otherwise, sessions could have different duration. (Before: we were doing this only if (Lazy.is_val v)) Keeping same duration is important for example for comet (which is using both service and volatile data sessions). *) let _oldvalue, newr = Lazy.force v in match !newr with | Eliom_common.SCData_session_expired | Eliom_common.SCNo_data -> () (* The cookie has been removed *) | Eliom_common.SC newc -> ( newc.Eliom_common.dc_exp := match !(newc.Eliom_common.dc_timeout) with | Eliom_common.TGlobal -> ( let globaltimeout = Eliommod_timeouts.find_global `Data name sitedata in match globaltimeout with | None -> None | Some t -> Some (t +. now)) | Eliom_common.TNone -> None | Eliom_common.TSome t -> Some (t +. now))) !data_cookies_info; let module Expiry_tolerance = struct (* Avoid cookie updates that only change the cookie expiry date by a negligible amount of time. *) let timeout_tolerance_factor = 0.01 let within_tolerance x y = let diff = Float.abs (x -. y) in diff < timeout_tolerance_factor *. Float.abs (x -. now) let within_tolerance_opt x y = match x, y with Some x, Some y -> within_tolerance x y | _ -> x = y end in (* Update persistent expiration date, user timeout and value *) (* 2018-07-17 We do this for all persistent sessions only if one persistent session has been used: - all persistent sessions will have same duration - will not do too many database requests *) if Eliom_common.Full_state_name_table.exists (fun _ v -> Lazy.is_val v) !pers_cookies_info then Eliom_common.Full_state_name_table.fold (fun name v thr -> let thr2 = Lazy.force v >>= fun (oldvalue, newr) -> match !newr with | Eliom_common.SCData_session_expired | Eliom_common.SCNo_data -> (* The cookie has been removed *) Lwt.return () | Eliom_common.SC newc -> ( let newexp = match !(newc.Eliom_common.pc_timeout) with | Eliom_common.TGlobal -> ( let globaltimeout = Eliommod_timeouts.find_global `Persistent name sitedata in match globaltimeout with | None -> None | Some t -> Some (t +. now)) | Eliom_common.TNone -> None | Eliom_common.TSome t -> Some (t +. now) in match oldvalue with | Some (_, oldti, oldexp, oldgrp) when Expiry_tolerance.within_tolerance_opt oldexp newexp && oldti = !(newc.Eliom_common.pc_timeout) && oldgrp = !(newc.Eliom_common.pc_session_group) && newc.Eliom_common.pc_set_value = None -> Lwt.return () (* nothing to do *) | Some (_, _oldti, oldexp, _oldgrp) when newc.Eliom_common.pc_set_value = None -> Lwt.catch (fun () -> let = Eliom_common.( Hashed_cookies.to_string newc.pc_hvalue) in Eliommod_cookies.Persistent_cookies.replace_if_exists cookieid { Eliommod_cookies.full_state_name = name ; expiry = newexp ; timeout = !(newc.Eliom_common.pc_timeout) ; session_group = !(newc.Eliom_common.pc_session_group) } >>= fun () -> Eliommod_cookies.Persistent_cookies.Expiry_dates .remove_cookie oldexp cookieid) (function | Not_found -> Lwt.return () (* someone else closed the session *) | e -> Lwt.fail e) | _ -> Eliommod_cookies.Persistent_cookies.add Eliom_common.(Hashed_cookies.to_string newc.pc_hvalue) { Eliommod_cookies.full_state_name = name ; expiry = newexp ; timeout = !(newc.Eliom_common.pc_timeout) ; session_group = !(newc.Eliom_common.pc_session_group) }) (*VVV Do not forget to change persistent_cookie_table_version if you change the type of persistent table data, otherwise the server will crash!!! *) in thr >>= fun () -> thr2) !pers_cookies_info Lwt.return_unit else Lwt.return_unit in update_exp ci >>= fun () -> (* the same, for secure cookies: *) update_exp sci (*****************************************************************************) (* Generation of the page or naservice + update the cookie tables (value, expiration date and timeout) *) let execute now generate_page ({; ; _} as info) sitedata = let%lwt result = Lwt.catch (fun () -> generate_page now info sitedata) (fun e -> sitedata.Eliom_common.exn_handler e) in let%lwt () = update_cookie_table ~now sitedata all_cookie_info in let%lwt () = update_cookie_table ~now sitedata tab_cookie_info in Lwt.return result (** Set expired sessions in request data *) let set_expired_sessions ri closedservsessions = if closedservsessions = ([], []) then () else Polytables.set ~table:(Ocsigen_request.request_cache ri.Ocsigen_extensions.request_info) ~key:Eliom_common.eliom_service_session_expired ~value:closedservsessions open Ocsigen_extensions let handled_method = function | `GET | `HEAD | `POST | `PUT | `DELETE -> true | _ -> false let do_redirection header_id status uri = Ocsigen_extensions.Ext_found (fun () -> let response = let headers = Cohttp.Header.init_with Ocsigen_header.Name.(to_string header_id) uri in Cohttp.Response.make ~status ~headers () in Lwt.return (Ocsigen_response.make response)) let gen_req_not_found ~is_eliom_extension ~sitedata ~previous_extension_err ~req = let req = Eliom_common.patch_request_info req in let now = Unix.gettimeofday () in let%lwt ri, si, = Eliom_common.get_session_info ~sitedata ~req 404 in let , closedsessions = Eliommod_cookies.get_cookie_info now sitedata si.Eliom_common.si_service_session_cookies si.Eliom_common.si_data_session_cookies si.Eliom_common.si_persistent_session_cookies si.Eliom_common.si_secure_cookie_info in let (, closedsessions_tab), = (* If tab cookie info exists in rc (because an action put them here), we get it from here. Otherwise we get it from tab cookies in parameters. *) match previous_tab_cookies_info with | Some (atci, utc) -> (atci, []), utc | None -> ( Eliommod_cookies.get_cookie_info now sitedata si.Eliom_common.si_service_session_cookies_tab si.Eliom_common.si_data_session_cookies_tab si.Eliom_common.si_persistent_session_cookies_tab si.Eliom_common.si_secure_cookie_info_tab , Ocsigen_cookie_map.empty ) in set_expired_sessions ri (closedsessions, closedsessions_tab); let rec gen_aux ({Eliom_common.request = ri; session_info = si; ; _} as info) = let sp = Eliom_common.make_server_params sitedata info None None in (* The last two arguments are not yet available, so for now we use None. This value will later be overwritten once this information is available. *) Lwt.with_value Eliom_common.sp_key (Some sp) @@ fun () -> let genfun = match si.Eliom_common.si_nonatt_info with | Eliom_common.RNa_no -> (* page generation *) Eliom_route.get_page | _ -> (* anonymous service *) Eliom_route.make_naservice in Lwt.catch (fun () -> let%lwt res = execute now genfun info sitedata in let response, _ = Ocsigen_response.to_cohttp res and = Ocsigen_response.cookies res in let%lwt = Eliommod_cookies.compute_cookies_to_send sitedata all_cookie_info all_user_cookies in let res = match Ocsigen_request.header ri.Ocsigen_extensions.request_info (Ocsigen_header.Name.of_string Eliom_common_base.cookie_substitutes_header_name) with | Some _ -> let response = let headers = Cohttp.Header.add (Cohttp.Response.headers response) Eliom_common_base.set_cookie_substitutes_header_name (Eliommod_cookies.cookieset_to_json cookies) in {response with Cohttp.Response.headers} in Ocsigen_response.update ~response ~cookies res | None -> Ocsigen_response.update ~cookies res in try Polytables.get ~table: (Ocsigen_request.request_cache ri.Ocsigen_extensions.request_info) ~key:Eliom_common.found_stop_key; (* if we find this information in request cache, the request has already been completed. (used after an action). Do not try the following extensions. *) Lwt.return (Ocsigen_extensions.Ext_found_stop (fun () -> Lwt.return res)) with Not_found -> Lwt.return (Ocsigen_extensions.Ext_found (fun () -> Lwt.return res))) (function (* FIXME COHTTP transition ; restore all that *) | Eliom_common.Eliom_Typing_Error l -> Lwt.return (Ocsigen_extensions.Ext_found (fun () -> make_response ~status:`Bad_request (Eliom_error_pages.page_error_param_type l))) | Eliom_common.Eliom_Wrong_parameter -> let%lwt ripp = match Ocsigen_request.post_params req.request_info ri.request_config.Ocsigen_extensions.uploaddir ri.request_config.Ocsigen_extensions.maxuploadfilesize with | None -> Lwt.return [] | Some l -> l in let response = Eliom_error_pages.page_bad_param (try ignore @@ Polytables.get ~table:(Ocsigen_request.request_cache ri.request_info) ~key:Eliom_common.eliom_params_after_action; true with Not_found -> false) (Ocsigen_request.get_params_flat ri.request_info) (List.map fst ripp) in Lwt.return @@ Ocsigen_extensions.Ext_found (fun () -> make_response ~status:`Bad_request response) | Eliom_common.Eliom_404 -> Lwt.return (Ocsigen_extensions.Ext_next previous_extension_err) | Eliom_common.Eliom_retry_with a -> gen_aux a | Eliom_common.Eliom_do_redirection uri -> Lwt.return @@ do_redirection Ocsigen_header.Name.location `Temporary_redirect uri | Eliom_common.Eliom_do_half_xhr_redirection uri -> Lwt.return @@ do_redirection (Ocsigen_header.Name.of_string Eliom_common.half_xhr_redir_header) `No_content uri | e -> Lwt.fail e) in let info = { Eliom_common.request = ri ; session_info = si ; all_cookie_info ; tab_cookie_info ; user_tab_cookies } in match is_eliom_extension with | Some ext -> Eliom_extension.run_eliom_extension ext now info sitedata | None -> gen_aux info let gen is_eliom_extension sitedata = let open Ocsigen_extensions in function | Req_found _ -> Lwt.return Ext_do_nothing | Req_not_found ((`Not_found as previous_extension_err), req) when handled_method (Ocsigen_request.meth req.request_info) -> gen_req_not_found ~is_eliom_extension ~sitedata ~previous_extension_err ~req | Req_not_found (_, _ri) -> Lwt.return Ext_do_nothing
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>