From 5ff361af543a3d303b83c576a10366a4fdddc6cd Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Thu, 24 Jan 2019 11:19:05 +0100 Subject: [PATCH] Simplified proxy example, no more proxy.conf file. Added forwarding case based on server name. --- examples/proxy/README.md | 16 ++++- examples/proxy/application_execution.e | 64 +++++-------------- examples/proxy/proxy.conf | 2 - .../wsf_simple_reverse_proxy_handler.e | 51 ++++++++++----- 4 files changed, 65 insertions(+), 68 deletions(-) delete mode 100644 examples/proxy/proxy.conf diff --git a/examples/proxy/README.md b/examples/proxy/README.md index e0fb5e7c..a543a3e8 100644 --- a/examples/proxy/README.md +++ b/examples/proxy/README.md @@ -2,5 +2,17 @@ Proxy example ============= Via the `wsf_proxy` library, it is possible to implement a simple reverse proxy service. -Note: you need to edit the `proxy.conf` file to use proper remote service. -(You can use for instance any of the EWF examples as remote server, or also existing public server). + +This example forwards request based on server name, or location as described below: +- if server name is `foo`, forwards to `http://localhost:8080/foo` +- if server name is `bar`, forwards to `http://localhost:8080/bar` +- if path starts with "/search/", forwards to `http://www.google.com/search?q=` + +For instance: +- http://foo/a/test -> http://localhost:8080/foo/a/test +- http://localhost:9090/search/eiffel -> http://www.google.com/search?q=eiffel + +Notes: +- look at `{APPLICATION_EXECUTION}.execute` for the implementation. +- the `send_proxy_response` implements a general forwarding, but for more advanced need, this could be customized per forwarding. For instance, a specific forwarding, may need the X-Forwarded headers, or to keep the `Host` from the client, ... + diff --git a/examples/proxy/application_execution.e b/examples/proxy/application_execution.e index 5e3d88d4..1ef4d885 100644 --- a/examples/proxy/application_execution.e +++ b/examples/proxy/application_execution.e @@ -18,56 +18,21 @@ feature -- Basic operations local l_forwarded: BOOLEAN do - -- NOTE: please edit the proxy.conf file - across - proxy_map as ic - until - l_forwarded - loop - if request.path_info.starts_with_general (ic.key) then - l_forwarded := True - send_proxy_response (ic.key, ic.item, agent proxy_uri (ic.key, ?)) - end - end - if not l_forwarded then + -- Hardocoded for the example + if request.server_name.same_string ("foo") then + send_proxy_response ("http://localhost:8080/foo", Void) + l_forwarded := True + elseif request.server_name.same_string ("bar") then + send_proxy_response ("http://localhost:8080/bar", Void) + l_forwarded := True + elseif request.path_info.starts_with_general ("/search/") then + send_proxy_response ("http://www.google.com/search?q=", agent uri_for_location_based_proxy ("/search/", ?)) + else response.send (create {WSF_PAGE_RESPONSE}.make_with_body ("EiffelWeb proxy: not forwarded!")) end end - proxy_map: HASH_TABLE [STRING, STRING] - -- location => target - local - f: PLAIN_TEXT_FILE - l_line: STRING - p: INTEGER - once ("thread") - create Result.make (1) - -- Load proxy.conf - create f.make_with_name ("proxy.conf") - if f.exists and then f.is_access_readable then - f.open_read - from - until - f.end_of_file or f.exhausted - loop - f.read_line - l_line := f.last_string - if l_line.starts_with ("#") then - -- ignore - else - -- Format: - -- path%Tserver - p := l_line.index_of ('%T', 1) - if p > 0 then - Result.force (l_line.substring (p + 1, l_line.count), l_line.head (p - 1)) - end - end - end - f.close - end - end - - send_proxy_response (a_location, a_remote: READABLE_STRING_8; a_rewriter: detachable FUNCTION [WSF_REQUEST, STRING]) + send_proxy_response (a_remote: READABLE_STRING_8; a_rewriter: detachable FUNCTION [WSF_REQUEST, STRING]) local h: WSF_SIMPLE_REVERSE_PROXY_HANDLER do @@ -85,13 +50,16 @@ feature -- Basic operations -- Uncomment following line to keep the original Host value. -- h.keep_proxy_host (True) + -- For debug information, uncomment next line +-- response.put_error ("Forwarding to " + h.proxy_url (request)) + h.execute (request, response) end feature -- Helpers - proxy_uri (a_location: READABLE_STRING_8; a_request: WSF_REQUEST): STRING - -- Request uri rewriten as url. + uri_for_location_based_proxy (a_location: READABLE_STRING_8; a_request: WSF_REQUEST): STRING + -- Request uri rewritten as url. do Result := a_request.request_uri -- If related proxy setting is diff --git a/examples/proxy/proxy.conf b/examples/proxy/proxy.conf deleted file mode 100644 index 5ba995d7..00000000 --- a/examples/proxy/proxy.conf +++ /dev/null @@ -1,2 +0,0 @@ -/google/ http://www.google.com/search?q=eiffel -/ http://localhost:8080/testproxy diff --git a/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e b/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e index 48444127..b54cd32a 100644 --- a/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e +++ b/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e @@ -143,18 +143,24 @@ feature -- Header Change is_using_proxy_host := b end -feature -- Execution +feature -- Access / information - proxy_uri (request: WSF_REQUEST): STRING - -- URI to query on proxyfied host. + proxy_url (req: WSF_REQUEST): STRING + -- Proxy forward to `Result` URL. + local + l_remote_uri: like remote_uri do + l_remote_uri := remote_uri + create Result.make_from_string (l_remote_uri.string) if attached uri_rewriter as r then - Result := r.uri (request) + Result.append (r.uri (req)) else - Result := request.request_uri + Result.append (req.request_uri) end end +feature -- Execution + execute (request: WSF_REQUEST; response: WSF_RESPONSE) -- Execute reverse proxy request. local @@ -186,16 +192,7 @@ feature -- Execution l_socket.is_connected and then attached l_socket.peer_address as l_socket_peer_address then - create l_http_query.make_from_string (request.request_method) - l_http_query.append_character (' ') - l_http_query.append (l_remote_uri.path) - if attached l_remote_uri.query as q then - l_http_query.append_character ('?') - l_http_query.append (q) - end - l_http_query.append (proxy_uri (request)) - l_http_query.append_character (' ') - l_http_query.append (request.server_protocol) + l_http_query := forward_http_query (request) if attached request.raw_header_data as l_raw_header then i := l_raw_header.substring_index ("%R%N", 1) if i > 0 then @@ -357,7 +354,29 @@ feature -- Execution end end -feature {NONE} -- Implementation +feature {NONE} -- Implementation + + forward_http_query (req: WSF_REQUEST): STRING + local + l_remote_uri: like remote_uri + do + l_remote_uri := remote_uri + + create Result.make_from_string (req.request_method) + Result.append_character (' ') + Result.append (l_remote_uri.path) + if attached l_remote_uri.query as q then + Result.append_character ('?') + Result.append (q) + end + if attached uri_rewriter as r then + Result.append (r.uri (req)) + else + Result.append (req.request_uri) + end + Result.append_character (' ') + Result.append (req.server_protocol) + end status_line_info (a_line: READABLE_STRING_8): detachable TUPLE [protocol: READABLE_STRING_8; status_code: INTEGER; reason_phrase: detachable READABLE_STRING_8] -- Info from status line