123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2022 Nomadic Labs, <contact@nomadic-labs.com> *)(* *)(* 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. *)(* *)(*****************************************************************************)letmake_transform_callbackforwarding_endpointcallbackconnreqbody=letopenLwt_syntaxinletopenCohttpin(* Using a [Cohttp_lwt.Body.t] destructs it. As we may need it
twice, we explicitly clone the underlying [Lwt_stream.t]. *)letbody_stream=Cohttp_lwt.Body.to_streambodyinlet*answer=callbackconnreq(Cohttp_lwt.Body.of_stream(Lwt_stream.clonebody_stream))inletanswer_has_not_found_status=function|`Expert(response,_)|`Response(response,_)->Response.statusresponse=`Not_foundinifanswer_has_not_found_statusanswerthenleturi=Request.urireqinleturi=Uri.make?scheme:(Uri.schemeforwarding_endpoint)?userinfo:(Uri.userinfoforwarding_endpoint)?host:(Uri.hostforwarding_endpoint)?port:(Uri.portforwarding_endpoint)~path:(Filename.concat(Uri.pathforwarding_endpoint)(Uri.pathuri))~query:(Uri.queryuri)?fragment:(Uri.fragmenturi)()in(* Strip out hop-by-hop connection headers (stolen from
cohttp-lwt-unix/bin/cohttp_proxy_lwt.ml from
github.com/mirage/ocaml-cohttp) *)letheaders=Request.headersreq|>funh->Header.removeh"accept-encoding"|>funh->Header.removeh"content-length"|>funh->Header.removeh"transfer-encoding"|>funh->Header.removeh"connection"|>funh->Header.addh"accept-encoding""identity"inlet*resp,body=Cohttp_lwt_unix.Client.call~headers~body:(Cohttp_lwt.Body.of_streambody_stream)(Request.methreq)uriinletstatus=Response.statusrespinletheaders=Response.headersresp|>funh->Header.removeh"transfer-encoding"|>funh->Header.removeh"content-length"|>funh->Header.removeh"connection"inlet*answer=Cohttp_lwt_unix.Server.respond~headers~status~body()inLwt.return(`Responseanswer)elseLwt.returnanswerletrpc_metrics_transform_callback~update_metricsdircallbackconnreqbody=letopenLwt_result_syntaxinletdo_call()=callbackconnreqbodyinletcohttp_meth=Cohttp.Request.methreqinleturi=Cohttp.Request.urireqinletpath=Uri.pathuriinletdecoded=Resto.Utils.decode_split_pathpathinlet*!description=let*resto_meth=matchcohttp_methwith|#Resto.methasmeth->Lwt.return_okmeth|_->Lwt.return_error@@`Method_not_allowed[]inlet*uri_desc=Tezos_rpc.Directory.lookup_uri_descdir()resto_methdecodedinLwt.return_ok(uri_desc,Resto.string_of_methresto_meth)inmatchdescriptionwith|Ok(uri,meth)->(* We update the metric only if the URI can succesfully
be matched in the directory tree. *)update_metricsurimethdo_call|Error_->(* Otherwise, the call must be done anyway. *)do_call()letproxy_server_query_forwarderforwarding_endpoint=make_transform_callbackforwarding_endpoint