From c34f89df9b5df743934c13f54958d61599344339 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 18 Oct 2016 13:22:32 +0200 Subject: [PATCH] Added connection header related functions. - WSF_REQUEST.is_keep_alive_http_connection: BOOLEAN - HTTP_HEADER_MODIFIER.put_connection_keep_alive - HTTP_HEADER_MODIFIER.put_connection_close In Standalone request handler code, better detection of Connection: keep-alive header. --- examples/simple/application_execution.e | 4 +- examples/simple_ssl/application_execution.e | 4 +- examples/websocket/application_execution.e | 7 +-- .../protocol/http/src/http_header_modifier.e | 20 ++++++++ .../server/httpd/httpd_request_handler_i.e | 49 ++++++++++++++++--- library/server/wsf/src/wsf_request.e | 10 +++- .../wsf_simple_reverse_proxy_handler.e | 7 +-- 7 files changed, 82 insertions(+), 19 deletions(-) diff --git a/examples/simple/application_execution.e b/examples/simple/application_execution.e index d823a16e..a27e79d2 100644 --- a/examples/simple/application_execution.e +++ b/examples/simple/application_execution.e @@ -30,8 +30,8 @@ feature -- Basic operations response.set_status_code ({HTTP_STATUS_CODE}.ok) 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") + if request.is_keep_alive_http_connection then + response.header.put_connection_keep_alive end response.put_string (s) end diff --git a/examples/simple_ssl/application_execution.e b/examples/simple_ssl/application_execution.e index 2d6d0a75..7e2c3c6d 100644 --- a/examples/simple_ssl/application_execution.e +++ b/examples/simple_ssl/application_execution.e @@ -32,8 +32,8 @@ feature -- Basic operations response.set_status_code ({HTTP_STATUS_CODE}.ok) 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") + if request.is_keep_alive_http_connection then + response.header.put_connection_keep_alive end response.put_string (s) end diff --git a/examples/websocket/application_execution.e b/examples/websocket/application_execution.e index fc920446..506bbedf 100644 --- a/examples/websocket/application_execution.e +++ b/examples/websocket/application_execution.e @@ -35,8 +35,8 @@ feature -- Basic operations response.set_status_code ({HTTP_STATUS_CODE}.ok) 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") + if request.is_keep_alive_http_connection then + response.header.put_connection_keep_alive end response.put_string (s) end @@ -96,9 +96,10 @@ $(document).ready(function() { function connect(){ - var host = "##WSSCHEME##://127.0.0.1:##PORTNUMBER##"; + var host = "##WSSCHEME##://127.0.0.1:##PORTNUMBER##/app"; try{ + socket = new WebSocket(host); message('

Socket Status: '+socket.readyState); socket.onopen = function(){ diff --git a/library/network/protocol/http/src/http_header_modifier.e b/library/network/protocol/http/src/http_header_modifier.e index 3af4e45b..44ccd191 100644 --- a/library/network/protocol/http/src/http_header_modifier.e +++ b/library/network/protocol/http/src/http_header_modifier.e @@ -544,6 +544,26 @@ feature -- Others put_pragma ("no-cache") end +feature -- Connection + + put_connection (a_conn: READABLE_STRING_8) + -- Put "Connection" header with `a_conn' value. + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_connection, a_conn) + end + + put_connection_keep_alive + -- Put "Connection" header with "keep-alive". + do + put_connection ("keep-alive") + end + + put_connection_close + -- Put "Connection" header with "close". + do + put_connection ("close") + end + feature -- Redirection put_location (a_uri: READABLE_STRING_8) diff --git a/library/server/httpd/httpd_request_handler_i.e b/library/server/httpd/httpd_request_handler_i.e index 6263cb5c..6ae119df 100644 --- a/library/server/httpd/httpd_request_handler_i.e +++ b/library/server/httpd/httpd_request_handler_i.e @@ -455,14 +455,11 @@ feature -- Parsing -- Except for HTTP/1.0, persistent connection is the default. is_persistent_connection_requested := True if is_http_version_1_0 then - is_persistent_connection_requested := attached request_header_map.item ("Connection") as l_connection and then - l_connection.is_case_insensitive_equal_general ("keep-alive") + is_persistent_connection_requested := has_keep_alive_http_connection_header (request_header_map) else -- By default HTTP:1/1 support persistent connection. - if attached request_header_map.item ("Connection") as l_connection then - if l_connection.is_case_insensitive_equal_general ("close") then - is_persistent_connection_requested := False - end + if has_close_http_connection_header (request_header_map) then + is_persistent_connection_requested := False else is_persistent_connection_requested := True end @@ -476,6 +473,46 @@ feature -- Parsing end end + has_keep_alive_http_connection_header (h_map: like request_header_map): BOOLEAN + -- Does Current request header map `h_map' have "keep-alive" connection header? + local + i: INTEGER + do + if attached h_map.item ("Connection") as l_connection then + -- Could be for instance "keep-alive, Upgrade" + i := l_connection.substring_index ("keep-alive", 1) + if i > 0 then + i := i + 9 -- "keep-alive" has 10 characters + check i <= l_connection.count end + if i = l_connection.count then + Result := True + else + Result := l_connection [i + 1] = ',' or l_connection [i + 1].is_space + end + end + end + end + + has_close_http_connection_header (h_map: like request_header_map): BOOLEAN + -- Does Current request header map `h_map' have "close" connection header? + local + i: INTEGER + do + if attached h_map.item ("Connection") as l_connection then + -- Could be for instance "close, ..." + i := l_connection.substring_index ("close", 1) + if i > 0 then + i := i + 4 -- "close" has 5 characters + check i <= l_connection.count end + if i = l_connection.count then + Result := True + else + Result := l_connection [i + 1] = ',' or l_connection [i + 1].is_space + end + end + end + end + analyze_request_line (line: STRING) -- Analyze `line' as a HTTP request line. -- note: may update `has_error'. diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index 10d8dfca..3df32b6c 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -1200,11 +1200,19 @@ feature -- HTTP_* http_connection: detachable READABLE_STRING_8 -- Contents of the Connection: header from the current wgi_request, if there is one. - -- Example: 'Keep-Alive'. + -- Example: 'keep-alive'. do Result := wgi_request.http_connection end + is_keep_alive_http_connection: BOOLEAN + -- Is a keep-alive connection? + do + if attached http_connection as conn then + Result := conn.starts_with ("keep-alive") + end + end + http_expect: detachable READABLE_STRING_8 -- The Expect request-header field is used to indicate that particular server behaviors are required by the client. -- Example: '100-continue'. diff --git a/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e b/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e index a0ab3c6b..e01f7b72 100644 --- a/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e +++ b/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e @@ -291,11 +291,8 @@ feature {NONE} -- Implementation 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") + if request.is_keep_alive_http_connection then + response.header.put_connection_keep_alive end response.put_string (s) end