package cohttp
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
An OCaml library for HTTP clients and servers
Install
dune-project
Dependency
Authors
Maintainers
Sources
cohttp-6.1.1.tbz
sha256=6b420c56203b3a0b515964f036bcea0fb9a362876b5791cd7ff50e12366c489c
sha512=839ff6156658ca6d7922e6eed63ebb84dd09c76107790477be55a1ffc4a3800bf49c435147a0ed628f147eaeccff9a8d34565e3787f32c15e187b6e8855f0b93
doc/src/cohttp/request.ml.html
Source file request.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(*{{{ Copyright (c) 2012 Anil Madhavapeddy <anil@recoil.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * }}}*) open Sexplib0.Sexp_conv type t = Http.Request.t = { headers : Header.t; meth : Code.meth; resource : string; version : Code.version; } [@@deriving sexp] let compare { headers; meth; resource; version } y = match Header.compare headers y.headers with | 0 -> ( match Code.compare_method meth y.meth with | 0 -> ( match String.compare resource y.resource with | 0 -> Code.compare_version version y.version | i -> i) | i -> i) | i -> i let headers t = t.headers let meth t = t.meth let resource t = t.resource let version t = t.version let encoding t = Header.get_transfer_encoding t.headers let make ?(meth = `GET) ?(version = `HTTP_1_1) ?encoding ?(headers = Header.init ()) ?(absolute_form = false) uri = let port () = match Uri.port uri with | Some p -> ":" ^ string_of_int p | None when meth = `CONNECT -> ( match Uri_services.tcp_port_of_uri uri with | None -> failwith "A port is required for the CONNECT method." | Some p -> ":" ^ string_of_int p) | None -> "" in let host = match Header.get headers "host" with | None -> ( match Uri.scheme uri with | Some "httpunix" -> "" | _ -> Uri.host_with_default ~default:"localhost" uri ^ port ()) | Some host -> if String.contains host ':' then host else host ^ port () in let headers = Header.replace headers "host" host in let headers = Header.add_unless_exists headers "user-agent" Header.user_agent in let headers = (* Add user:password auth to headers from uri * if headers don't already have auth *) match (Header.get_authorization headers, Uri.user uri, Uri.password uri) with | None, Some user, Some pass -> let auth = `Basic (user, pass) in Header.add_authorization headers auth | _, _, _ -> headers in let resource = if absolute_form then Uri.to_string uri else Uri.path_and_query uri in let headers = match encoding with | None -> headers | Some encoding -> Header.add_transfer_encoding headers encoding in { headers; meth; resource; version } let is_keep_alive t = Http.Request.is_keep_alive t (* Make a client request, which involves guessing encoding and adding content headers if appropriate. @param chunked Forces chunked encoding *) let make_for_client ?headers ?chunked ?body_length ?absolute_form meth uri = let encoding = match (chunked, body_length) with | Some true, None -> Transfer.Chunked | (None | Some false), Some fixed -> Transfer.Fixed fixed | (Some false | None), None -> Transfer.Unknown | Some true, Some _ -> invalid_arg "cannot set both ?chunked and ?body_length:" in make ~meth ~encoding ?headers ?absolute_form uri let pp_hum ppf r = Format.fprintf ppf "%s" (r |> sexp_of_t |> Sexplib0.Sexp.to_string_hum) (* Validate path when reading URI. Implemented for compatibility with old implementation rather than efficiency *) let is_valid_uri path meth = path = "*" || meth = `CONNECT || match Uri.scheme (Uri.of_string path) with | Some _ -> true | None -> not (String.length path > 0 && path.[0] <> '/') let uri { resource; headers; meth; _ } = match resource with | "*" -> ( match Header.get headers "host" with | None -> Uri.of_string "" | Some host -> let host_uri = Uri.of_string ("//" ^ host) in Uri.(make ?host:(host host_uri) ?port:(port host_uri) ())) | when meth = `CONNECT -> Uri.of_string ("//" ^ authority) | path -> ( let uri = Uri.of_string path in match Uri.scheme uri with | Some _ -> ( Uri.( (* we have an absoluteURI *) match path uri with | "" -> with_path uri "/" | _ -> uri)) | None -> ( let empty = Uri.of_string "" in let empty_base = Uri.of_string "///" in let pqs = match Stringext.split ~max:2 path ~on:'?' with | [] -> empty_base | [ path ] -> Uri.resolve "http" empty_base (Uri.with_path empty path) | path :: qs :: _ -> let path_base = Uri.resolve "http" empty_base (Uri.with_path empty path) in Uri.with_query path_base (Uri.query_of_encoded qs) in match Header.get headers "host" with | None -> Uri.(with_scheme (with_host pqs None) None) | Some host -> let host_uri = Uri.of_string ("//" ^ host) in let uri = Uri.with_host pqs (Uri.host host_uri) in Uri.with_port uri (Uri.port host_uri))) type tt = t module Make (IO : S.IO) = struct type t = tt module IO = IO module Header_IO = Header_io.Make (IO) module Transfer_IO = Transfer_io.Make (IO) type reader = Transfer_IO.reader type writer = Transfer_IO.writer open IO let rec read ic = let result = IO.with_input_buffer ic ~f:(fun buf ~pos ~len -> match Http.Private.Parser.parse_request ~pos ~len buf with | Ok (req, consumed) -> (`Ok req, consumed) | Error Partial -> (`Partial, 0) | Error (Msg msg) -> (`Invalid msg, 0)) in match result with | `Partial -> ( IO.refill ic >>= function `Ok -> read ic | `Eof -> return `Eof) | `Ok req -> if is_valid_uri (Http.Request.resource req) (Http.Request.meth req) then return (`Ok req) else return (`Invalid "bad request URI") | `Invalid msg -> return (`Invalid msg) let make_body_reader req ic = Transfer_IO.make_reader (Header.get_transfer_encoding req.headers) ic let read_body_chunk = Transfer_IO.read let write_header req oc = let fst_line = Printf.sprintf "%s %s %s\r\n" (Http.Method.to_string req.meth) (if req.meth = `CONNECT then Option.get (Header.get req.headers "host") else if req.resource = "" then "/" else req.resource) (Http.Version.to_string req.version) in IO.write oc fst_line >>= fun _ -> Header_IO.write req.headers oc let make_body_writer ~flush req oc = Transfer_IO.make_writer ~flush (Header.get_transfer_encoding req.headers) oc let write_body = Transfer_IO.write let headers oc = match Header.get_transfer_encoding headers with | Transfer.Chunked -> (* TODO Trailer header support *) IO.write oc "0\r\n\r\n" | Transfer.Fixed _ | Transfer.Unknown -> return () let write ~flush write_body req oc = write_header req oc >>= fun () -> let writer = make_body_writer ~flush req oc in write_body writer >>= fun () -> write_footer req.headers oc end module Private = struct module Make = Make end let has_body = Http.Request.has_body
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>