package sihl
The modular functional web framework
Install
Dune Dependency
Authors
Maintainers
Sources
sihl-queue-0.1.9.tbz
sha256=77f0813d75a88edd14b3396e8b848d94c31c28803299b4b1bd4b78b1de4a2e80
sha512=a8907bc35ea14b7c3a7d638979a2a274860202b2de58b84b5621a4908db001ace493d8aa2e5383f4c8b1847efd256938592f63ef75a41521284b3640d3a7442a
doc/src/sihl.http/response.ml.html
Source file response.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
(* This module is based on the reworked API of Opium. MIT License Copyright (c) 2019 Rudi Grinberg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *) open Lwt.Syntax include Opium_kernel.Rock.Response (* Encoders *) let redirect_to ?(env = Opium_kernel.Hmap.empty) ?(headers = Cohttp.Header.init ()) location = let headers = Cohttp.Header.add headers "Location" location in { env; code = `Moved_permanently; headers; body = Cohttp_lwt.Body.empty } ;; let of_plain_text ?(env = Opium_kernel.Hmap.empty) ?(headers = Cohttp.Header.init ()) ?(code = `OK) text = let body = Cohttp_lwt.Body.of_string text in { env; code; headers; body } ;; let of_json ?(env = Opium_kernel.Hmap.empty) ?(headers = Cohttp.Header.init ()) ?(code = `OK) json = let headers = Cohttp.Header.add_unless_exists headers "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string (Yojson.Safe.to_string json) in { env; code; headers; body } ;; let of_file ?(headers = Cohttp.Header.init ()) file_path = let* response_body = Cohttp_lwt_unix.Server.respond_file ~headers ~fname:file_path () in Lwt.return @@ of_response_body response_body ;; (* Decoders *) let to_json_exn t = let open Lwt.Syntax in let* body = Cohttp_lwt.Body.to_string t.body in Lwt.return @@ Yojson.Safe.from_string body ;; let to_json t = let open Lwt.Syntax in Lwt.catch (fun () -> let+ json = to_json_exn t in Some json) (function | _ -> Lwt.return None) ;; let to_plain_text t = Cohttp_lwt.Body.to_string t.body (* Setters & Getters *) let status response = Cohttp.Code.code_of_status response.code let set_status status response = { response with code = Cohttp.Code.status_of_code status } ;; let header k t = Cohttp.Header.get t.headers k let headers k t = Cohttp.Header.get_multi t.headers k let add_header (k, v) t = (* TODO [jerben] make sure this appends values and doesn't replace *) { t with headers = Cohttp.Header.add t.headers k v } ;; let add_header_or_replace (k, v) t = { t with headers = Cohttp.Header.add t.headers k v } let add_header_unless_exists (k, v) t = { t with headers = Cohttp.Header.add_unless_exists t.headers k v } ;; let add_headers headers t = (* TODO [jerben] make sure this appends values and doesn't replace *) { t with headers = Cohttp.Header.add_list t.headers headers } ;; let add_headers_or_replace headers t = { t with headers = Cohttp.Header.add_list t.headers headers } ;; let add_headers_unless_exists headers t = List.fold_left (fun t (k, v) -> add_header_unless_exists (k, v) t) t headers ;; let remove_header s t = { t with headers = Cohttp.Header.remove t.headers s } let content_type t = header "content-type" t let set_content_type s t = add_header_or_replace ("content-type", s) t let etag t = header "etag" t let set_etag s t = add_header_or_replace ("etag", s) t let location t = header "location" t let set_location s t = add_header_or_replace ("location", s) t let cache_control t = header "cache-control" t let set_cache_control s t = add_header_or_replace ("cache-control", s) t (* Cookies *) let ?signed_with key t = let = headers "Set-Cookie" t |> List.map (fun v -> Cookie.of_set_cookie_header ?signed_with ("Set-Cookie", v)) |> List.find_opt (function | Some Cookie.{ value = k, _; _ } when String.equal k key -> true | _ -> false) in Option.bind cookie_opt (fun x -> x) ;; let ?signed_with t = headers "set-cookie" t |> List.map (fun v -> Cookie.of_set_cookie_header ?signed_with ("set-cookie", v)) |> List.filter_map (fun x -> x) ;; let replace_or_add_to_list ~f to_add l = let found = ref false in let rec aux acc l = match l with | [] -> if not !found then to_add :: acc |> List.rev else List.rev acc | el :: rest -> if f el to_add then ( found := true; aux (to_add :: acc) rest) else aux (el :: acc) rest in aux [] l ;; let ?sign_with ?expires ?scope ?same_site ?secure ?http_only value t = let = Cookie.make ?sign_with ?expires ?scope ?same_site ?secure ?http_only value |> Cookie.to_set_cookie_header in let headers = replace_or_add_to_list ~f:(fun (k, v) _ -> match k, v with | k, v when String.equal (String.lowercase_ascii k) "set-cookie" && String.length v > String.length (fst value) && String.equal (StringLabels.sub v ~pos:0 ~len:(String.length (fst value))) (fst value) -> true | _ -> false) cookie_header (Cohttp.Header.to_list t.headers) in { t with headers = Cohttp.Header.of_list headers } ;; let ?sign_with ?expires ?scope ?same_site ?secure ?http_only (k, v) t = let = cookies t in if List.exists (fun Cookie.{ value = , _; _ } -> String.equal cookie k) cookies then t else add_cookie ?sign_with ?expires ?scope ?same_site ?secure ?http_only (k, v) t ;; let key t = add_cookie ~expires:(`Max_age 0L) (key, "") t
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>