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.
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
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
-- Hardocoded for the example
if request.server_name.same_string ("foo") then
send_proxy_response ("http://localhost:8080/foo", Void)
l_forwarded := True
send_proxy_response (ic.key, ic.item, agent proxy_uri (ic.key, ?))
end
end
if not l_forwarded then
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

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
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
@@ -359,6 +356,28 @@ feature -- Execution
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
--| Such as "HTTP/1.1 200 OK" -> ["1.1", 200, "OK"]