+class request ic =
+ let (meth, uri, version) = Http_parser.parse_request_fst_line ic in
+ let uri_str = Neturl.string_of_url uri in
+ let path = Http_parser.parse_path uri in
+ let query_get_params = Http_parser.parse_query_get_params uri in
+ let headers = Http_parser.parse_headers ic in (* trailing \r\n consumed! *)
+ let body =
+ (* TODO fallback on Transfer-Encoding if Content-Length isn't defined *)
+ if meth = `POST then
+ Buffer.contents
+ (try (* read only Content-Length bytes *)
+ let limit_raw =
+ (try
+ (snd (List.find
+ (fun (h,v) -> String.lowercase h = "content-length") headers))
+ with Not_found -> raise Fallback)
+ in
+ let limit =
+ (try (* TODO supports only a maximum content-length of 1Gb *)
+ int_of_string limit_raw
+ with Failure "int_of_string" ->
+ raise (Invalid_header ("Content-Length: " ^ limit_raw)))
+ in
+ Http_misc.buf_of_inchan ~limit ic
+ with Fallback -> Http_misc.buf_of_inchan ic) (* read until EOF *)
+ else "" (* TODO empty body for methods other than POST, is what we want? *)
+ in
+ (* TODO brave assumption: when meth = `POST, Content-Type is
+ application/x-www-form-urlencoded and is therefore one-liner parsed as a GET
+ query *)
+ let query_post_params =
+ match meth with
+ | `POST -> Http_parser.split_query_params body
+ | _ -> []
+ in
+ let params = query_post_params @ query_get_params in (* prefers POST params *)
+ let _ = debug_dump_request path params in
+ let (clisockaddr, srvsockaddr) =
+ (Http_misc.peername_of_in_channel ic, Http_misc.sockname_of_in_channel ic)
+ in