Merge branch 'reverse_proxy'
This commit is contained in:
29
examples/proxy/application.e
Normal file
29
examples/proxy/application.e
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
note
|
||||||
|
description: "Launcher for reverse proxy web application."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION]
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service.
|
||||||
|
do
|
||||||
|
-- Specific to `standalone' connector (the EiffelWeb server).
|
||||||
|
-- See `{WSF_STANDALONE_SERVICE_LAUNCHER}.initialize'
|
||||||
|
set_service_option ("port", 9090)
|
||||||
|
import_service_options (create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI}.make_from_file ("server.ini"))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
49
examples/proxy/application_execution.e
Normal file
49
examples/proxy/application_execution.e
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
note
|
||||||
|
description: "Reverse proxy example."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION_EXECUTION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_EXECUTION
|
||||||
|
|
||||||
|
WSF_URI_REWRITER
|
||||||
|
rename
|
||||||
|
uri as proxy_uri
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
execute
|
||||||
|
do
|
||||||
|
-- NOTE: please enter the target server uri here
|
||||||
|
-- replace "http://localhost:8080/foobar"
|
||||||
|
send_proxy_response ("http://localhost:8080/foobar", Current)
|
||||||
|
end
|
||||||
|
|
||||||
|
send_proxy_response (a_remote: READABLE_STRING_8; a_rewriter: detachable WSF_URI_REWRITER)
|
||||||
|
local
|
||||||
|
h: WSF_SIMPLE_REVERSE_PROXY_HANDLER
|
||||||
|
do
|
||||||
|
create h.make (a_remote)
|
||||||
|
h.set_uri_rewriter (a_rewriter)
|
||||||
|
h.set_uri_rewriter (create {WSF_AGENT_URI_REWRITER}.make (agent proxy_uri))
|
||||||
|
h.set_timeout (30) -- 30 seconds
|
||||||
|
h.set_connect_timeout (5_000) -- milliseconds = 5 seconds
|
||||||
|
h.execute (request, response)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Helpers
|
||||||
|
|
||||||
|
proxy_uri (a_request: WSF_REQUEST): STRING
|
||||||
|
-- Request uri rewriten as url.
|
||||||
|
do
|
||||||
|
Result := a_request.request_uri
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
28
examples/proxy/proxy.ecf
Normal file
28
examples/proxy/proxy.ecf
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="proxy" uuid="B55F0D95-3793-4C90-BBAC-BF5F2DECD5E6" library_target="proxy">
|
||||||
|
<target name="common" abstract="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/.svn$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
</file_rule>
|
||||||
|
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
|
||||||
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||||
|
</option>
|
||||||
|
<setting name="console_application" value="true"/>
|
||||||
|
<variable name="ssl_supported" value="false"/>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<library name="http" location="..\..\library\network\protocol\http\http-safe.ecf"/>
|
||||||
|
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||||
|
<library name="wsf_proxy" location="..\..\library\server\wsf_proxy\wsf_proxy-safe.ecf" readonly="false"/>
|
||||||
|
</target>
|
||||||
|
<target name="proxy" extends="common">
|
||||||
|
<root class="APPLICATION" feature="make_and_launch"/>
|
||||||
|
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||||
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||||
|
</option>
|
||||||
|
<setting name="concurrency" value="scoop"/>
|
||||||
|
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf"/>
|
||||||
|
<cluster name="proxy" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
</system>
|
||||||
8
examples/proxy/server.ini
Normal file
8
examples/proxy/server.ini
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
verbose=true
|
||||||
|
verbose_level=ALERT
|
||||||
|
port=9090
|
||||||
|
#max_concurrent_connections=100
|
||||||
|
#keep_alive_timeout=15
|
||||||
|
#max_tcp_clients=100
|
||||||
|
#socket_timeout=300
|
||||||
|
#max_keep_alive_requests=300
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_PROXY_SOCKET_FACTORY}."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_PROXY_SOCKET_FACTORY
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_PROXY_SOCKET_FACTORY_I
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
ssl_socket (a_host: READABLE_STRING_8; a_port: INTEGER): detachable NETWORK_STREAM_SOCKET
|
||||||
|
do
|
||||||
|
check supported: False end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_PROXY_SOCKET_FACTORY}."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_PROXY_SOCKET_FACTORY
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_PROXY_SOCKET_FACTORY_I
|
||||||
|
redefine
|
||||||
|
is_ssl_supported
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
ssl_socket (a_host: READABLE_STRING_8; a_port: INTEGER): detachable SSL_NETWORK_STREAM_SOCKET
|
||||||
|
do
|
||||||
|
if attached create_from_name (a_host) as l_peer_address then
|
||||||
|
create Result.make_client_by_address_and_port (l_peer_address, a_port)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Status
|
||||||
|
|
||||||
|
is_ssl_supported: BOOLEAN = True
|
||||||
|
-- Is https:// supported?
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_PROXY_SOCKET_FACTORY_I}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
WSF_PROXY_SOCKET_FACTORY_I
|
||||||
|
|
||||||
|
inherit
|
||||||
|
INET_ADDRESS_FACTORY
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
socket_from_uri (a_uri: URI): like socket
|
||||||
|
local
|
||||||
|
l_port: INTEGER
|
||||||
|
do
|
||||||
|
if a_uri.is_valid and then attached a_uri.host as l_host then
|
||||||
|
l_port := a_uri.port
|
||||||
|
if a_uri.scheme.is_case_insensitive_equal_general ("https") then
|
||||||
|
if is_ssl_supported then
|
||||||
|
if l_port <= 0 then
|
||||||
|
l_port := 443
|
||||||
|
end
|
||||||
|
Result := ssl_socket (l_host, l_port)
|
||||||
|
end
|
||||||
|
elseif a_uri.scheme.is_case_insensitive_equal_general ("http") then
|
||||||
|
if l_port <= 0 then
|
||||||
|
l_port := 80
|
||||||
|
end
|
||||||
|
Result := socket (l_host, l_port)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Status
|
||||||
|
|
||||||
|
is_uri_supported (a_uri: URI): BOOLEAN
|
||||||
|
do
|
||||||
|
Result := a_uri.scheme.is_case_insensitive_equal_general ("http")
|
||||||
|
or else (
|
||||||
|
a_uri.scheme.is_case_insensitive_equal_general ("https")
|
||||||
|
and is_ssl_supported
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
is_ssl_supported: BOOLEAN
|
||||||
|
-- Is https:// supported?
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
socket (a_host: READABLE_STRING_8; a_port: INTEGER): detachable NETWORK_STREAM_SOCKET
|
||||||
|
do
|
||||||
|
if attached create_from_name (a_host) as l_peer_address then
|
||||||
|
create Result.make_client_by_address_and_port (l_peer_address, a_port)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ssl_socket (a_host: READABLE_STRING_8; a_port: INTEGER): detachable NETWORK_STREAM_SOCKET
|
||||||
|
require
|
||||||
|
is_ssl_supported: is_ssl_supported
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,303 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_SIMPLE_REVERSE_PROXY_HANDLER}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_SIMPLE_REVERSE_PROXY_HANDLER
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_remote_uri: READABLE_STRING_8)
|
||||||
|
do
|
||||||
|
create remote_uri.make_from_string (a_remote_uri)
|
||||||
|
timeout := 30 -- seconds. See {NETWORK_SOCKET}.default_timeout
|
||||||
|
connect_timeout := 5_000 -- 5 seconds.
|
||||||
|
is_via_header_supported := True
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
remote_uri: URI
|
||||||
|
-- Url for the targetted service.
|
||||||
|
|
||||||
|
uri_rewriter: detachable WSF_URI_REWRITER assign set_uri_rewriter
|
||||||
|
-- URI rewriter component, to compute the URI on targetted service
|
||||||
|
-- based on current request.
|
||||||
|
|
||||||
|
feature -- Settings
|
||||||
|
|
||||||
|
connect_timeout: INTEGER assign set_connect_timeout
|
||||||
|
-- In milliseconds.
|
||||||
|
|
||||||
|
timeout: INTEGER assign set_timeout
|
||||||
|
-- In seconds.
|
||||||
|
|
||||||
|
is_via_header_supported: BOOLEAN
|
||||||
|
-- Via: header supported.
|
||||||
|
-- Default: True.
|
||||||
|
|
||||||
|
feature -- Change
|
||||||
|
|
||||||
|
set_uri_rewriter (a_rewriter: like uri_rewriter)
|
||||||
|
do
|
||||||
|
uri_rewriter := a_rewriter
|
||||||
|
end
|
||||||
|
|
||||||
|
set_timeout (a_timeout_in_seconds: INTEGER)
|
||||||
|
-- in seconds.
|
||||||
|
do
|
||||||
|
timeout := a_timeout_in_seconds
|
||||||
|
end
|
||||||
|
|
||||||
|
set_connect_timeout (a_timeout_in_milliseconds: INTEGER)
|
||||||
|
-- in milliseconds.
|
||||||
|
do
|
||||||
|
connect_timeout := a_timeout_in_milliseconds
|
||||||
|
end
|
||||||
|
|
||||||
|
set_is_via_header_supported (b: BOOLEAN)
|
||||||
|
-- Set `is_via_header_supported' to `b'.
|
||||||
|
do
|
||||||
|
is_via_header_supported := b
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Execution
|
||||||
|
|
||||||
|
proxy_uri (request: WSF_REQUEST): STRING
|
||||||
|
-- URI to query on proxyfied host.
|
||||||
|
do
|
||||||
|
if attached uri_rewriter as r then
|
||||||
|
Result := r.uri (request)
|
||||||
|
else
|
||||||
|
Result := request.request_uri
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
execute (request: WSF_REQUEST; response: WSF_RESPONSE)
|
||||||
|
-- Execute reverse proxy request.
|
||||||
|
local
|
||||||
|
h: HTTP_HEADER
|
||||||
|
l_http_query: STRING
|
||||||
|
l_status_line: STRING
|
||||||
|
l_max_forward: INTEGER
|
||||||
|
l_via: detachable STRING
|
||||||
|
l_protocol: STRING
|
||||||
|
i: INTEGER
|
||||||
|
l_completed: BOOLEAN
|
||||||
|
l_remote_uri: like remote_uri
|
||||||
|
l_socket_factory: WSF_PROXY_SOCKET_FACTORY
|
||||||
|
do
|
||||||
|
l_remote_uri := remote_uri
|
||||||
|
create l_socket_factory
|
||||||
|
if not l_socket_factory.is_uri_supported (l_remote_uri) then
|
||||||
|
send_error (request, response, {HTTP_STATUS_CODE}.bad_gateway, l_remote_uri.scheme + " is not supported! [for remote " + l_remote_uri.string + "]")
|
||||||
|
elseif attached l_socket_factory.socket_from_uri (l_remote_uri) as l_socket then
|
||||||
|
l_socket.set_connect_timeout (connect_timeout) -- milliseconds
|
||||||
|
l_socket.set_timeout (timeout) -- seconds
|
||||||
|
|
||||||
|
l_socket.connect
|
||||||
|
if l_socket.is_connected then
|
||||||
|
create l_http_query.make_from_string (request.request_method)
|
||||||
|
l_http_query.append_character (' ')
|
||||||
|
l_http_query.append (l_remote_uri.path)
|
||||||
|
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
|
||||||
|
i := l_raw_header.substring_index ("%R%N", 1)
|
||||||
|
if i > 0 then
|
||||||
|
-- Skip the first status line.
|
||||||
|
create h.make_from_raw_header_data (l_raw_header.substring (i + 2, l_raw_header.count))
|
||||||
|
else
|
||||||
|
create h.make_from_raw_header_data (l_raw_header)
|
||||||
|
end
|
||||||
|
if attached l_remote_uri.host as l_remote_host then
|
||||||
|
if l_remote_uri.port > 0 then
|
||||||
|
h.put_header_key_value ("Host", l_remote_host + ":" + l_remote_uri.port.out)
|
||||||
|
else
|
||||||
|
h.put_header_key_value ("Host", l_remote_host)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Via header
|
||||||
|
if is_via_header_supported then
|
||||||
|
if attached h.item ("Via") as v then
|
||||||
|
l_via := v
|
||||||
|
l_via.append (", ")
|
||||||
|
else
|
||||||
|
create l_via.make_empty
|
||||||
|
end
|
||||||
|
l_via.append (request.server_protocol + " " + request.server_name + " (PROXY-" + request.server_software + ")")
|
||||||
|
h.put_header_key_value ("Via", l_via)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Max-Forwards header handling
|
||||||
|
if attached h.item ("Max-Forwards") as h_max_forward then
|
||||||
|
-- Max-Forwards: 0 stop, otherwise decrement by one.
|
||||||
|
-- see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.31
|
||||||
|
if h_max_forward.is_integer then
|
||||||
|
l_max_forward := h_max_forward.to_integer - 1
|
||||||
|
if l_max_forward >= 0 then
|
||||||
|
h.put_header_key_value ("Max-Forwards", l_max_forward.out)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if l_max_forward < 0 then
|
||||||
|
-- i.e previous Max-Forwards was '0'
|
||||||
|
send_error (request, response, {HTTP_STATUS_CODE}.bad_gateway, "Reached maximum number of Forwards, not forwarded to " + l_remote_uri.string)
|
||||||
|
else
|
||||||
|
l_socket.put_string (l_http_query)
|
||||||
|
l_socket.put_string ("%R%N")
|
||||||
|
l_socket.put_string (h.string)
|
||||||
|
l_socket.put_string ("%R%N")
|
||||||
|
if request.content_length_value > 0 then
|
||||||
|
request.read_input_data_into_file (l_socket)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get HTTP status
|
||||||
|
l_socket.read_line_thread_aware
|
||||||
|
create l_status_line.make_from_string (l_socket.last_string)
|
||||||
|
-- Get HTTP header block
|
||||||
|
if attached next_http_header_block (l_socket) as l_resp_header then
|
||||||
|
create h.make_from_raw_header_data (l_resp_header)
|
||||||
|
if attached status_line_info (l_status_line) as l_status_info then
|
||||||
|
l_protocol := l_status_info.protocol
|
||||||
|
if attached l_status_info.reason_phrase as l_phrase then
|
||||||
|
response.set_status_code_with_reason_phrase (l_status_info.status_code, l_phrase)
|
||||||
|
else
|
||||||
|
response.set_status_code (l_status_info.status_code)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
check has_status_line: False end
|
||||||
|
l_protocol := "1.0" -- Default?
|
||||||
|
response.set_status_code (80)
|
||||||
|
end
|
||||||
|
|
||||||
|
if is_via_header_supported then
|
||||||
|
if attached h.item ("Via") as v then
|
||||||
|
l_via := v
|
||||||
|
l_via.append (", ")
|
||||||
|
else
|
||||||
|
create l_via.make_empty
|
||||||
|
end
|
||||||
|
l_via.append (l_protocol + " " + request.server_name + " (PROXY-" + request.server_software + ")")
|
||||||
|
h.put_header_key_value ("Via", l_via)
|
||||||
|
end
|
||||||
|
|
||||||
|
response.add_header_lines (h)
|
||||||
|
from
|
||||||
|
l_socket.read_stream (2_048)
|
||||||
|
until
|
||||||
|
l_socket.was_error
|
||||||
|
or not l_socket.is_connected
|
||||||
|
or l_socket.bytes_read <= 0
|
||||||
|
or l_completed
|
||||||
|
loop
|
||||||
|
response.put_string (l_socket.last_string)
|
||||||
|
if l_socket.bytes_read = 2_048 then
|
||||||
|
l_socket.read_stream (2_048)
|
||||||
|
else
|
||||||
|
l_completed := True
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
send_error (request, response, {HTTP_STATUS_CODE}.internal_server_error, "Invalid response header!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
send_error (request, response, {HTTP_STATUS_CODE}.internal_server_error, "Can not access request header!")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
send_error (request, response, {HTTP_STATUS_CODE}.gateway_timeout, "Unable to connect " + l_remote_uri.string)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
send_error (request, response, {HTTP_STATUS_CODE}.bad_gateway, "Unable to connect " + l_remote_uri.string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
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"]
|
||||||
|
local
|
||||||
|
i,j: INTEGER
|
||||||
|
p,s: detachable READABLE_STRING_8
|
||||||
|
c: INTEGER
|
||||||
|
do
|
||||||
|
i := a_line.index_of (' ', 1)
|
||||||
|
if i > 0 then
|
||||||
|
p := a_line.substring (1, i - 1)
|
||||||
|
if p.starts_with_general ("HTTP/") then
|
||||||
|
p := p.substring (6, p.count) -- We could also keep HTTP/
|
||||||
|
end
|
||||||
|
j := i + 1
|
||||||
|
i := a_line.index_of (' ', j)
|
||||||
|
if i > 0 then
|
||||||
|
s := a_line.substring (j, i - 1)
|
||||||
|
if s.is_integer then
|
||||||
|
c := s.to_integer
|
||||||
|
s := a_line.substring (i + 1, a_line.count)
|
||||||
|
if s.is_whitespace then
|
||||||
|
s := Void
|
||||||
|
elseif s[s.count].is_space then
|
||||||
|
s := s.substring (1, s.count - 1)
|
||||||
|
end
|
||||||
|
Result := [p, c, s]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
next_http_header_block (a_socket: NETWORK_STREAM_SOCKET): detachable STRING
|
||||||
|
local
|
||||||
|
h: STRING
|
||||||
|
do
|
||||||
|
create h.make_empty
|
||||||
|
from
|
||||||
|
a_socket.read_line_thread_aware
|
||||||
|
until
|
||||||
|
Result /= Void
|
||||||
|
or a_socket.was_error
|
||||||
|
or (a_socket.bytes_read = 0 or a_socket.bytes_read = -1)
|
||||||
|
or not a_socket.is_connected
|
||||||
|
loop
|
||||||
|
if a_socket.last_string.same_string ("%R") then
|
||||||
|
-- End of header
|
||||||
|
Result := h
|
||||||
|
else
|
||||||
|
h.append (a_socket.last_string)
|
||||||
|
h.append ("%N")
|
||||||
|
a_socket.read_line_thread_aware
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
send_error (request: WSF_REQUEST; response: WSF_RESPONSE; a_status_code: INTEGER; a_message: READABLE_STRING_8)
|
||||||
|
local
|
||||||
|
s: STRING
|
||||||
|
do
|
||||||
|
-- To send a response we need to setup, the status code and
|
||||||
|
-- the response headers.
|
||||||
|
create s.make_from_string (a_message)
|
||||||
|
debug
|
||||||
|
s.append ("%N(UTC time is " + (create {HTTP_DATE}.make_now_utc).rfc850_string + ").%N")
|
||||||
|
end
|
||||||
|
response.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "plain/text"], ["Content-Length", s.count.out]>>)
|
||||||
|
response.set_status_code (a_status_code)
|
||||||
|
response.header.put_content_type_text_html
|
||||||
|
response.header.put_content_length (s.count)
|
||||||
|
if
|
||||||
|
attached request.http_connection as l_connection and then
|
||||||
|
l_connection.is_case_insensitive_equal_general ("keep-alive")
|
||||||
|
then
|
||||||
|
response.header.put_header_key_value ("Connection", "keep-alive")
|
||||||
|
end
|
||||||
|
response.put_string (s)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
38
library/server/wsf_proxy/rewriter/wsf_agent_uri_rewriter.e
Normal file
38
library/server/wsf_proxy/rewriter/wsf_agent_uri_rewriter.e
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_AGENT_URI_REWRITER}."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_AGENT_URI_REWRITER
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_URI_REWRITER
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
--convert
|
||||||
|
-- make ({FUNCTION [TUPLE [WSF_REQUEST], STRING]})
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_rewriter_function: like rewriter_function)
|
||||||
|
do
|
||||||
|
rewriter_function := a_rewriter_function
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
rewriter_function: FUNCTION [TUPLE [WSF_REQUEST], STRING]
|
||||||
|
|
||||||
|
feature -- Conversion
|
||||||
|
|
||||||
|
uri (a_request: WSF_REQUEST): STRING
|
||||||
|
-- <Precursor>.
|
||||||
|
do
|
||||||
|
Result := rewriter_function (a_request)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
16
library/server/wsf_proxy/rewriter/wsf_uri_rewriter.e
Normal file
16
library/server/wsf_proxy/rewriter/wsf_uri_rewriter.e
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_URI_REWRITER}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
WSF_URI_REWRITER
|
||||||
|
|
||||||
|
feature -- Conversion
|
||||||
|
|
||||||
|
uri (a_request: WSF_REQUEST): STRING
|
||||||
|
-- Rewritten request uri based on `a_request'.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
34
library/server/wsf_proxy/wsf_proxy-safe.ecf
Normal file
34
library/server/wsf_proxy/wsf_proxy-safe.ecf
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="wsf_proxy" uuid="A39CCC27-BF63-4959-B881-7D0713F4C84A" library_target="wsf_proxy">
|
||||||
|
<target name="wsf_proxy">
|
||||||
|
<root all_classes="true"/>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<library name="http" location="..\..\..\library\network\protocol\http\http-safe.ecf"/>
|
||||||
|
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
|
||||||
|
<library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl-safe.ecf">
|
||||||
|
<condition>
|
||||||
|
<custom name="ssl_supported" value="true"/>
|
||||||
|
</condition>
|
||||||
|
</library>
|
||||||
|
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri-safe.ecf"/>
|
||||||
|
<library name="wsf" location="..\wsf\wsf-safe.ecf"/>
|
||||||
|
<cluster name="network" location=".\network\" recursive="true">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>no_ssl</exclude>
|
||||||
|
<exclude>ssl</exclude>
|
||||||
|
</file_rule>
|
||||||
|
<cluster name="network_ssl" location="$|ssl\">
|
||||||
|
<condition>
|
||||||
|
<custom name="ssl_supported" value="true"/>
|
||||||
|
</condition>
|
||||||
|
</cluster>
|
||||||
|
<cluster name="network_no_ssl" location="$|no_ssl\">
|
||||||
|
<condition>
|
||||||
|
<custom name="ssl_supported" excluded_value="true"/>
|
||||||
|
</condition>
|
||||||
|
</cluster>
|
||||||
|
</cluster>
|
||||||
|
<cluster name="reverse_proxy" location=".\reverse_proxy\" recursive="true"/>
|
||||||
|
<cluster name="rewriter" location=".\rewriter\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
</system>
|
||||||
14
library/server/wsf_proxy/wsf_proxy.ecf
Normal file
14
library/server/wsf_proxy/wsf_proxy.ecf
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="wsf_proxy" uuid="A39CCC27-BF63-4959-B881-7D0713F4C84A" library_target="wsf_proxy">
|
||||||
|
<target name="wsf_proxy">
|
||||||
|
<root all_classes="true"/>
|
||||||
|
<option void_safety="none">
|
||||||
|
</option>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||||
|
<library name="http" location="..\..\..\library\network\protocol\http\http.ecf"/>
|
||||||
|
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
||||||
|
<library name="wsf" location="..\wsf\wsf.ecf"/>
|
||||||
|
<cluster name="reverse_proxy" location=".\reverse_proxy\" recursive="true"/>
|
||||||
|
<cluster name="rewriter" location=".\rewriter\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
</system>
|
||||||
Reference in New Issue
Block a user