Better support for HTTP/1.0 and also related to persistent connection.
This commit is contained in:
@@ -39,7 +39,7 @@ feature {NONE} -- Initialization
|
||||
create request_header.make_empty
|
||||
create request_header_map.make (10)
|
||||
|
||||
keep_alive_enabled := False
|
||||
keep_alive_requested := False
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
@@ -85,8 +85,10 @@ feature -- Access
|
||||
remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER]
|
||||
-- Information related to remote client
|
||||
|
||||
keep_alive_enabled: BOOLEAN
|
||||
-- Inside a persistent connection?
|
||||
keep_alive_requested: BOOLEAN
|
||||
-- Persistent connection requested?
|
||||
-- either has "Connection: Keep-Alive" header,
|
||||
-- or is HTTP/1.1 and no header "Connection: close".
|
||||
|
||||
is_http_version_1_0: BOOLEAN
|
||||
do
|
||||
@@ -117,7 +119,6 @@ feature -- Change
|
||||
set_is_verbose (b: BOOLEAN)
|
||||
do
|
||||
is_verbose := b
|
||||
print ("set_is_verbose " + b.out + "%N")
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
@@ -164,7 +165,9 @@ feature -- Execution
|
||||
n := n + 1
|
||||
-- FIXME: it seems to be called one more time, mostly to see this is done.
|
||||
execute_request
|
||||
l_exit := has_error or l_socket.is_closed or not l_socket.is_open_read or not keep_alive_enabled
|
||||
l_exit := not {HTTPD_SERVER}.is_persistent_connection_supported
|
||||
or has_error or l_socket.is_closed or not l_socket.is_open_read
|
||||
or not keep_alive_requested
|
||||
reset_request
|
||||
end
|
||||
end
|
||||
@@ -297,20 +300,19 @@ feature -- Parsing
|
||||
line := next_line (a_socket)
|
||||
end
|
||||
end
|
||||
if not {HTTPD_SERVER}.is_persistent_connection_supported then
|
||||
keep_alive_enabled := False
|
||||
elseif is_http_version_1_0 then
|
||||
keep_alive_enabled := attached request_header_map.item ("Connection") as l_connection and then
|
||||
-- Except for HTTP/1.0, persistent connection is the default.
|
||||
keep_alive_requested := True
|
||||
if is_http_version_1_0 then
|
||||
keep_alive_requested := attached request_header_map.item ("Connection") as l_connection and then
|
||||
l_connection.is_case_insensitive_equal_general ("keep-alive")
|
||||
else
|
||||
-- By default HTTP:1/1 support persistent connection.
|
||||
if attached request_header_map.item ("Connection") as l_connection then
|
||||
print ("Connection -> " + l_connection + "%N")
|
||||
if l_connection.is_case_insensitive_equal_general ("close") then
|
||||
keep_alive_enabled := False
|
||||
keep_alive_requested := False
|
||||
end
|
||||
else
|
||||
keep_alive_enabled := True
|
||||
keep_alive_requested := True
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,6 +76,13 @@ feature -- Request processing
|
||||
|
||||
create req.make (httpd_environment (a_socket), l_input, connector)
|
||||
create res.make (l_output, l_error)
|
||||
if is_http_version_1_0 then
|
||||
l_output.set_http_version ({HTTP_CONSTANTS}.http_version_1_0)
|
||||
res.set_http_version_1_0
|
||||
else
|
||||
l_output.set_http_version (version)
|
||||
end
|
||||
res.set_is_persistent_connection_requested (keep_alive_requested)
|
||||
|
||||
req.set_meta_string_variable ("RAW_HEADER_DATA", request_header)
|
||||
|
||||
|
||||
@@ -50,7 +50,12 @@ feature -- Status writing
|
||||
m: detachable READABLE_STRING_8
|
||||
do
|
||||
create s.make (16)
|
||||
s.append ({HTTP_CONSTANTS}.http_version_1_1)
|
||||
if attached http_version as v then
|
||||
s.append (v)
|
||||
else
|
||||
-- Default to 1.1
|
||||
s.append ({HTTP_CONSTANTS}.http_version_1_1)
|
||||
end
|
||||
s.append_character (' ')
|
||||
s.append_integer (a_code)
|
||||
m := a_reason_phrase
|
||||
|
||||
@@ -18,6 +18,28 @@ inherit
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Settings
|
||||
|
||||
is_http_version_1_0: BOOLEAN
|
||||
-- Is associated request using HTTP/1.0 ?
|
||||
|
||||
is_persistent_connection_requested: BOOLEAN
|
||||
-- Is persistent connection requested?
|
||||
|
||||
feature -- Settings change
|
||||
|
||||
set_http_version_1_0
|
||||
-- Set associated request is using HTTP/1.0.
|
||||
do
|
||||
is_http_version_1_0 := True
|
||||
end
|
||||
|
||||
set_is_persistent_connection_requested (b: BOOLEAN)
|
||||
-- Set `is_persistent_connection_requested' to `b'.
|
||||
do
|
||||
is_persistent_connection_requested := b
|
||||
end
|
||||
|
||||
feature -- Header output operation
|
||||
|
||||
put_header_text (a_text: READABLE_STRING_8)
|
||||
@@ -30,26 +52,64 @@ feature -- Header output operation
|
||||
o := output
|
||||
create s.make_from_string (a_text)
|
||||
|
||||
-- FIXME: check if HTTP versions 1.0 or else.
|
||||
|
||||
i := s.substring_index ("%NConnection:", 1)
|
||||
if i > 0 then
|
||||
j := s.index_of ('%R', i + 12)
|
||||
end
|
||||
if {HTTPD_SERVER}.is_persistent_connection_supported then
|
||||
if i = 0 then
|
||||
s.append ("Connection: Keep-Alive")
|
||||
s.append (o.crlf)
|
||||
end
|
||||
else
|
||||
-- standalone does not support persistent connection for now
|
||||
if j > 0 then
|
||||
l_connection := s.substring (i + 12, j - 1)
|
||||
l_connection.adjust
|
||||
if not l_connection.is_case_insensitive_equal_general ("close") then
|
||||
s.replace_substring ("Connection: close", i + 1, j - 1)
|
||||
-- Current standalone support persistent connection.
|
||||
-- If HTTP/1.1:
|
||||
-- by default all connection are persistent
|
||||
-- then no need to return "Connection:" header
|
||||
-- unless header has "Connection: close"
|
||||
-- then return "Connection: close"
|
||||
-- If HTTP/1.0:
|
||||
-- by default, connection is not persistent
|
||||
-- unless header has "Connection: Keep-Alive"
|
||||
-- then return "Connection: Keep-Alive"
|
||||
-- if header has "Connection: Close"
|
||||
-- then return "Connection: close"
|
||||
if is_persistent_connection_requested then
|
||||
if is_http_version_1_0 then
|
||||
if i = 0 then
|
||||
-- Existing response header does not has "Connection: " header.
|
||||
s.append ("Connection: Keep-Alive")
|
||||
s.append (o.crlf)
|
||||
else
|
||||
-- Do not override the application decision.
|
||||
end
|
||||
end
|
||||
else
|
||||
-- If HTTP/1.1 and persistent connection is not requested,
|
||||
-- then return "close"
|
||||
if i = 0 and not is_http_version_1_0 then
|
||||
-- Existing response header does not has "Connection: " header.
|
||||
s.append ("Connection: close")
|
||||
s.append (o.crlf)
|
||||
else
|
||||
-- Do not override the application decision.
|
||||
end
|
||||
end
|
||||
else
|
||||
-- persistent connection support is disabled.
|
||||
-- Return "Connection: close" in any case.
|
||||
-- Except for HTTP/1.0 since not required.
|
||||
if i > 0 then
|
||||
j := s.index_of ('%R', i + 12)
|
||||
end
|
||||
if j > 0 then
|
||||
-- Replace existing "Connection:" header with "Connection: close"
|
||||
l_connection := s.substring (i + 12, j - 1)
|
||||
l_connection.adjust
|
||||
if
|
||||
not is_http_version_1_0 and
|
||||
not l_connection.is_case_insensitive_equal_general ("close")
|
||||
then
|
||||
s.replace_substring ("Connection: close", i + 1, j - 1)
|
||||
end
|
||||
elseif not is_http_version_1_0 then
|
||||
-- HTTP/1.1: always return "close" since persistent connection is not supported.
|
||||
s.append ("Connection: close")
|
||||
s.append (o.crlf)
|
||||
elseif is_persistent_connection_requested then
|
||||
-- For HTTP/1.0, return "Connection: close", only if client sent a "Connection: Keep-Alive"
|
||||
s.append ("Connection: close")
|
||||
s.append (o.crlf)
|
||||
end
|
||||
|
||||
@@ -74,6 +74,9 @@ feature -- Status writing
|
||||
|
||||
feature -- Status report
|
||||
|
||||
http_version: detachable READABLE_STRING_8
|
||||
-- Optional HTTP version.
|
||||
|
||||
is_available: BOOLEAN
|
||||
-- Is output available?
|
||||
--| i.e: no issue with associated output stream, like closed socket, or related?
|
||||
@@ -85,6 +88,16 @@ feature -- Status report
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_http_version (v: like http_version)
|
||||
-- Set `http_version' to `v'.
|
||||
require
|
||||
valid_version: v /= Void implies v.starts_with ("HTTP/")
|
||||
do
|
||||
http_version := v
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
flush
|
||||
|
||||
Reference in New Issue
Block a user