Simplified proxy example, no more proxy.conf file.

Added forwarding case based on server name.
This commit is contained in:
2019-01-24 11:19:05 +01:00
parent 65525aa112
commit 5ff361af54
4 changed files with 65 additions and 68 deletions

View File

@@ -2,5 +2,17 @@ Proxy example
============= =============
Via the `wsf_proxy` library, it is possible to implement a simple reverse proxy service. 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, ...

View File

@@ -18,56 +18,21 @@ feature -- Basic operations
local local
l_forwarded: BOOLEAN l_forwarded: BOOLEAN
do do
-- NOTE: please edit the proxy.conf file -- Hardocoded for the example
across if request.server_name.same_string ("foo") then
proxy_map as ic send_proxy_response ("http://localhost:8080/foo", Void)
until l_forwarded := True
l_forwarded elseif request.server_name.same_string ("bar") then
loop send_proxy_response ("http://localhost:8080/bar", Void)
if request.path_info.starts_with_general (ic.key) then l_forwarded := True
l_forwarded := True elseif request.path_info.starts_with_general ("/search/") then
send_proxy_response (ic.key, ic.item, agent proxy_uri (ic.key, ?)) send_proxy_response ("http://www.google.com/search?q=", agent uri_for_location_based_proxy ("/search/", ?))
end else
end
if not l_forwarded then
response.send (create {WSF_PAGE_RESPONSE}.make_with_body ("EiffelWeb proxy: not forwarded!")) response.send (create {WSF_PAGE_RESPONSE}.make_with_body ("EiffelWeb proxy: not forwarded!"))
end end
end end
proxy_map: HASH_TABLE [STRING, STRING] send_proxy_response (a_remote: READABLE_STRING_8; a_rewriter: detachable FUNCTION [WSF_REQUEST, 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])
local local
h: WSF_SIMPLE_REVERSE_PROXY_HANDLER h: WSF_SIMPLE_REVERSE_PROXY_HANDLER
do do
@@ -85,13 +50,16 @@ feature -- Basic operations
-- Uncomment following line to keep the original Host value. -- Uncomment following line to keep the original Host value.
-- h.keep_proxy_host (True) -- h.keep_proxy_host (True)
-- For debug information, uncomment next line
-- response.put_error ("Forwarding to " + h.proxy_url (request))
h.execute (request, response) h.execute (request, response)
end end
feature -- Helpers feature -- Helpers
proxy_uri (a_location: READABLE_STRING_8; a_request: WSF_REQUEST): STRING uri_for_location_based_proxy (a_location: READABLE_STRING_8; a_request: WSF_REQUEST): STRING
-- Request uri rewriten as url. -- Request uri rewritten as url.
do do
Result := a_request.request_uri Result := a_request.request_uri
-- If related proxy setting is -- If related proxy setting is

View File

@@ -1,2 +0,0 @@
/google/ http://www.google.com/search?q=eiffel
/ http://localhost:8080/testproxy

View File

@@ -143,18 +143,24 @@ feature -- Header Change
is_using_proxy_host := b is_using_proxy_host := b
end end
feature -- Execution feature -- Access / information
proxy_uri (request: WSF_REQUEST): STRING proxy_url (req: WSF_REQUEST): STRING
-- URI to query on proxyfied host. -- Proxy forward to `Result` URL.
local
l_remote_uri: like remote_uri
do do
l_remote_uri := remote_uri
create Result.make_from_string (l_remote_uri.string)
if attached uri_rewriter as r then if attached uri_rewriter as r then
Result := r.uri (request) Result.append (r.uri (req))
else else
Result := request.request_uri Result.append (req.request_uri)
end end
end end
feature -- Execution
execute (request: WSF_REQUEST; response: WSF_RESPONSE) execute (request: WSF_REQUEST; response: WSF_RESPONSE)
-- Execute reverse proxy request. -- Execute reverse proxy request.
local local
@@ -186,16 +192,7 @@ feature -- Execution
l_socket.is_connected and then l_socket.is_connected and then
attached l_socket.peer_address as l_socket_peer_address attached l_socket.peer_address as l_socket_peer_address
then then
create l_http_query.make_from_string (request.request_method) l_http_query := forward_http_query (request)
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)
if attached request.raw_header_data as l_raw_header then if attached request.raw_header_data as l_raw_header then
i := l_raw_header.substring_index ("%R%N", 1) i := l_raw_header.substring_index ("%R%N", 1)
if i > 0 then if i > 0 then
@@ -357,7 +354,29 @@ feature -- Execution
end end
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] 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 -- Info from status line