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.make_empty
|
||||||
create request_header_map.make (10)
|
create request_header_map.make (10)
|
||||||
|
|
||||||
keep_alive_enabled := False
|
keep_alive_requested := False
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
@@ -85,8 +85,10 @@ feature -- Access
|
|||||||
remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER]
|
remote_info: detachable TUPLE [addr: STRING; hostname: STRING; port: INTEGER]
|
||||||
-- Information related to remote client
|
-- Information related to remote client
|
||||||
|
|
||||||
keep_alive_enabled: BOOLEAN
|
keep_alive_requested: BOOLEAN
|
||||||
-- Inside a persistent connection?
|
-- 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
|
is_http_version_1_0: BOOLEAN
|
||||||
do
|
do
|
||||||
@@ -117,7 +119,6 @@ feature -- Change
|
|||||||
set_is_verbose (b: BOOLEAN)
|
set_is_verbose (b: BOOLEAN)
|
||||||
do
|
do
|
||||||
is_verbose := b
|
is_verbose := b
|
||||||
print ("set_is_verbose " + b.out + "%N")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Execution
|
feature -- Execution
|
||||||
@@ -164,7 +165,9 @@ feature -- Execution
|
|||||||
n := n + 1
|
n := n + 1
|
||||||
-- FIXME: it seems to be called one more time, mostly to see this is done.
|
-- FIXME: it seems to be called one more time, mostly to see this is done.
|
||||||
execute_request
|
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
|
reset_request
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -297,20 +300,19 @@ feature -- Parsing
|
|||||||
line := next_line (a_socket)
|
line := next_line (a_socket)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not {HTTPD_SERVER}.is_persistent_connection_supported then
|
-- Except for HTTP/1.0, persistent connection is the default.
|
||||||
keep_alive_enabled := False
|
keep_alive_requested := True
|
||||||
elseif is_http_version_1_0 then
|
if is_http_version_1_0 then
|
||||||
keep_alive_enabled := attached request_header_map.item ("Connection") as l_connection and then
|
keep_alive_requested := attached request_header_map.item ("Connection") as l_connection and then
|
||||||
l_connection.is_case_insensitive_equal_general ("keep-alive")
|
l_connection.is_case_insensitive_equal_general ("keep-alive")
|
||||||
else
|
else
|
||||||
-- By default HTTP:1/1 support persistent connection.
|
-- By default HTTP:1/1 support persistent connection.
|
||||||
if attached request_header_map.item ("Connection") as l_connection then
|
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
|
if l_connection.is_case_insensitive_equal_general ("close") then
|
||||||
keep_alive_enabled := False
|
keep_alive_requested := False
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
keep_alive_enabled := True
|
keep_alive_requested := True
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -76,6 +76,13 @@ feature -- Request processing
|
|||||||
|
|
||||||
create req.make (httpd_environment (a_socket), l_input, connector)
|
create req.make (httpd_environment (a_socket), l_input, connector)
|
||||||
create res.make (l_output, l_error)
|
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)
|
req.set_meta_string_variable ("RAW_HEADER_DATA", request_header)
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,12 @@ feature -- Status writing
|
|||||||
m: detachable READABLE_STRING_8
|
m: detachable READABLE_STRING_8
|
||||||
do
|
do
|
||||||
create s.make (16)
|
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_character (' ')
|
||||||
s.append_integer (a_code)
|
s.append_integer (a_code)
|
||||||
m := a_reason_phrase
|
m := a_reason_phrase
|
||||||
|
|||||||
@@ -18,6 +18,28 @@ inherit
|
|||||||
create
|
create
|
||||||
make
|
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
|
feature -- Header output operation
|
||||||
|
|
||||||
put_header_text (a_text: READABLE_STRING_8)
|
put_header_text (a_text: READABLE_STRING_8)
|
||||||
@@ -30,26 +52,64 @@ feature -- Header output operation
|
|||||||
o := output
|
o := output
|
||||||
create s.make_from_string (a_text)
|
create s.make_from_string (a_text)
|
||||||
|
|
||||||
-- FIXME: check if HTTP versions 1.0 or else.
|
|
||||||
|
|
||||||
i := s.substring_index ("%NConnection:", 1)
|
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 {HTTPD_SERVER}.is_persistent_connection_supported then
|
||||||
if i = 0 then
|
-- Current standalone support persistent connection.
|
||||||
s.append ("Connection: Keep-Alive")
|
-- If HTTP/1.1:
|
||||||
s.append (o.crlf)
|
-- by default all connection are persistent
|
||||||
end
|
-- then no need to return "Connection:" header
|
||||||
else
|
-- unless header has "Connection: close"
|
||||||
-- standalone does not support persistent connection for now
|
-- then return "Connection: close"
|
||||||
if j > 0 then
|
-- If HTTP/1.0:
|
||||||
l_connection := s.substring (i + 12, j - 1)
|
-- by default, connection is not persistent
|
||||||
l_connection.adjust
|
-- unless header has "Connection: Keep-Alive"
|
||||||
if not l_connection.is_case_insensitive_equal_general ("close") then
|
-- then return "Connection: Keep-Alive"
|
||||||
s.replace_substring ("Connection: close", i + 1, j - 1)
|
-- 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
|
end
|
||||||
else
|
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 ("Connection: close")
|
||||||
s.append (o.crlf)
|
s.append (o.crlf)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ feature -- Status writing
|
|||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
|
|
||||||
|
http_version: detachable READABLE_STRING_8
|
||||||
|
-- Optional HTTP version.
|
||||||
|
|
||||||
is_available: BOOLEAN
|
is_available: BOOLEAN
|
||||||
-- Is output available?
|
-- Is output available?
|
||||||
--| i.e: no issue with associated output stream, like closed socket, or related?
|
--| i.e: no issue with associated output stream, like closed socket, or related?
|
||||||
@@ -85,6 +88,16 @@ feature -- Status report
|
|||||||
deferred
|
deferred
|
||||||
end
|
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
|
feature -- Basic operations
|
||||||
|
|
||||||
flush
|
flush
|
||||||
|
|||||||
Reference in New Issue
Block a user