123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127(*{{{ Copyright (c) 2012 Anil Madhavapeddy <anil@recoil.org>
* Copyright (c) 2011-2012 Martin Jambon <martin@mjambon.com>
* Copyright (c) 2010 Mika Illouz
*
* 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.
*
}}}*)includeHttp.Headerletmedia_type_re=letre=Re.Emacs.re~case:true"[ \t]*\\([^ \t;]+\\)"inRe.(compile(seq[start;re]))letget_first_match_res=tryletsubs=Re.exec~pos:0media_type_resinletstart,stop=Re.Group.offsetsubs1inSome(String.subsstart(stop-start))withNot_found->None(* Grab "foo/bar" from " foo/bar ; charset=UTF-8" *)letget_media_typeheaders=matchgetheaders"content-type"with|Somes->get_first_matchmedia_type_res|None->Noneletget_acceptable_media_rangesheaders=Accept.media_ranges(get_multi_concat~list_value_only:trueheaders"accept")letget_acceptable_charsetsheaders=Accept.charsets(get_multi_concat~list_value_only:trueheaders"accept-charset")letget_acceptable_encodingsheaders=Accept.encodings(get_multi_concat~list_value_only:trueheaders"accept-encoding")letget_acceptable_languagesheaders=Accept.languages(get_multi_concat~list_value_only:trueheaders"accept-language")(* Parse the transfer-encoding and content-length headers to
* determine how to decode a body *)letget_transfer_encodingheaders=(* It should actually be [get] as the interresting value is actually the last.*)matchget_multi_concat~list_value_only:trueheaders"transfer-encoding"with|Some"chunked"->Transfer.Chunked|Some_|None->(matchget_content_rangeheaderswith|Somelen->Transfer.Fixedlen|None->Transfer.Unknown)letadd_transfer_encodingheadersenc=letopenTransferin(* Only add a header if one doesnt already exist, e.g. from the app *)match(get_transfer_encodingheaders,enc)with|Fixed_,_(* App has supplied a content length, so use that *)|Chunked,_->headers(* TODO: this is a protocol violation *)|Unknown,Chunked->addheaders"transfer-encoding""chunked"|Unknown,Fixedlen->addheaders"content-length"(Int64.to_stringlen)|Unknown,Unknown->headersletadd_authorization_reqheaderschallenge=addheaders"www-authenticate"(Auth.string_of_challengechallenge)letadd_authorizationheaderscred=addheaders"authorization"(Auth.string_of_credentialcred)letget_authorizationheaders=matchgetheaders"authorization"with|None->None|Somev->Some(Auth.credential_of_stringv)letis_formheaders=get_media_typeheaders=Some"application/x-www-form-urlencoded"letget_locationheaders=matchget_locationheaderswith|None->None|Someu->Some(Uri.of_stringu)letget_linksheaders=List.rev(List.fold_left(funlistlink_s->List.rev_append(Link.of_stringlink_s)list)[](get_multiheaders"link"))letadd_linksheaderslinks=add_multiheaders"link"(List.mapLink.to_stringlinks)letuser_agent=Printf.sprintf"ocaml-cohttp/%s"Conf.versionletprepend_user_agentheadersuser_agent=letk="user-agent"inmatchgetheaderskwith|Someua->replaceheadersk(user_agent^" "^ua)|None->addheaderskuser_agentletconnectionh=matchgeth"connection"with|Somevwhenv="keep-alive"->Some`Keep_alive|Somevwhenv="close"->Some`Close|Somex->Some(`Unknownx)|_->NoneopenSexplib0.Sexp_convletsexp_of_tt=sexp_of_list(sexp_of_pairsexp_of_stringsexp_of_string)(to_listt)lett_of_sexps=of_list(list_of_sexp(pair_of_sexpstring_of_sexpstring_of_sexp)s)letpp_humppfh=Format.fprintfppf"%s"(h|>sexp_of_t|>Sexplib0.Sexp.to_string_hum)