diff --git a/CHANGES.rst b/CHANGES.rst index 435ea8dd6663f5edaa63ac0a6ad76e26d741d5c6..be1654b471145c4d0d0ce7ede56d7050ed233d07 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -98,6 +98,10 @@ Signer Proxy Server ------------ +- Redirected not found replies (HTTP 404 answers) to the underlying + octez-node itself. Public visibility of the node is not required + anymore. + Protocol Compiler And Environment --------------------------------- diff --git a/src/lib_rpc_http/RPC_middleware.ml b/src/lib_rpc_http/RPC_middleware.ml index 9cdee633977b789ddd7a147ea5cd27f3147077d5..214d1e6e567a9f064356135f4eccfb3e1085b514 100644 --- a/src/lib_rpc_http/RPC_middleware.ml +++ b/src/lib_rpc_http/RPC_middleware.ml @@ -26,24 +26,55 @@ let make_transform_callback forwarding_endpoint callback conn req body = let open Lwt_syntax in let open Cohttp in - let* answer = callback conn req body in - let uri = Request.uri req in + (* Using a [Cohttp_lwt.Body.t] destructs it. As we may need it + twice, we explicitly clone the underlying [Lwt_stream.t]. *) + let body_stream = Cohttp_lwt.Body.to_stream body in + let* answer = + callback conn req (Cohttp_lwt.Body.of_stream (Lwt_stream.clone body_stream)) + in let answer_has_not_found_status = function | `Expert (response, _) | `Response (response, _) -> Response.status response = `Not_found in if answer_has_not_found_status answer then - let overriding = Uri.to_string forwarding_endpoint ^ Uri.path uri in - let headers = Header.of_list [("Location", overriding)] in - let response = Response.make ~status:`Moved_permanently ~headers () in - Lwt.return - (`Response - ( response, - Cohttp_lwt.Body.of_string - (Format.asprintf - "tezos-proxy-server: request unsupported for proxy server, \ - redirecting to node endpoint at %s" - overriding) )) + let uri = Request.uri req in + let uri = + Uri.make + ?scheme:(Uri.scheme forwarding_endpoint) + ?userinfo:(Uri.userinfo forwarding_endpoint) + ?host:(Uri.host forwarding_endpoint) + ?port:(Uri.port forwarding_endpoint) + ~path:(Filename.concat (Uri.path forwarding_endpoint) (Uri.path uri)) + ~query:(Uri.query uri) + ?fragment:(Uri.fragment uri) + () + in + (* Strip out hop-by-hop connection headers (stolen from + cohttp-lwt-unix/bin/cohttp_proxy_lwt.ml from + github.com/mirage/ocaml-cohttp) *) + let headers = + Request.headers req |> fun h -> + Header.remove h "accept-encoding" |> fun h -> + Header.remove h "content-length" |> fun h -> + Header.remove h "transfer-encoding" |> fun h -> + Header.remove h "connection" |> fun h -> + Header.add h "accept-encoding" "identity" + in + let* resp, body = + Cohttp_lwt_unix.Client.call + ~headers + ~body:(Cohttp_lwt.Body.of_stream body_stream) + (Request.meth req) + uri + in + let status = Response.status resp in + let headers = + Response.headers resp |> fun h -> + Header.remove h "transfer-encoding" |> fun h -> + Header.remove h "content-length" |> fun h -> Header.remove h "connection" + in + let* answer = Cohttp_lwt_unix.Server.respond ~headers ~status ~body () in + Lwt.return (`Response answer) else Lwt.return answer let rpc_metrics_transform_callback ~update_metrics dir callback conn req body = diff --git a/tezt/tests/proxy_server_test.ml b/tezt/tests/proxy_server_test.ml index 1981be48c95d3644f35fed4a65410643265da8fc..0e9d660e27333c6b1c99b5a5d8f74c6248b98d89 100644 --- a/tezt/tests/proxy_server_test.ml +++ b/tezt/tests/proxy_server_test.ml @@ -226,10 +226,10 @@ let test_wrong_data_dir = re_str else Lwt.return_unit -let test_proxy_server_redirect_unsupported = +let test_proxy_server_serve_unsupported = Protocol.register_test ~__FILE__ - ~title:"proxy_server redirect curl" + ~title:"proxy_server serve unsupported curl" ~tags:["redirect"] @@ fun protocol -> let* node, _client = Client.init_with_protocol `Client ~protocol () in @@ -240,11 +240,10 @@ let test_proxy_server_redirect_unsupported = "localhost" (Proxy_server.rpc_port _ps) in - let r = Process.spawn "curl" ["-vL"; p] in + let r = Process.spawn "curl" ["-v"; p] in let* err = Process.check_and_read_stderr r in - let re_str = "301 Moved Permanently" in - let re_str' = "200 OK" in - let good_match = err =~ rex re_str && err =~ rex re_str' in + let re_str = "200 OK" in + let good_match = err =~ rex re_str in if not good_match then Test.fail "Unexpected error message: %s. It doesn't match the regexp %S" @@ -340,7 +339,7 @@ let register ~protocols = register `Node ; register `Proxy_server_data_dir ; register `Proxy_server_rpc ; - test_proxy_server_redirect_unsupported protocols ; + test_proxy_server_serve_unsupported protocols ; test_equivalence protocols ; test_wrong_data_dir protocols ; test_multi_protocols protocols