diff --git a/library/network/protocol/http/src/http_header.e b/library/network/protocol/http/src/http_header.e index ab7f882e..a162f9d4 100644 --- a/library/network/protocol/http/src/http_header.e +++ b/library/network/protocol/http/src/http_header.e @@ -26,11 +26,6 @@ inherit ITERABLE [READABLE_STRING_8] HTTP_HEADER_BUILDER - redefine - add_header_key_value, - put_header_key_value, - put_header_key_values - end create make, @@ -142,6 +137,8 @@ feature -- Conversion Result := res end +feature -- + append_string_to (a_result: STRING_8) -- Append current as string representation to `a_result' local @@ -298,33 +295,6 @@ feature -- Header change: general force_header_by_name (header_name_colon (h), h) end - add_header_key_value (k,v: READABLE_STRING_8) - -- Add header `k:v'. - -- If it already exists, there will be multiple header with same name - -- which can also be valid - do - Precursor (k, v) - ensure then - added: has_header_named (k) - end - - put_header_key_value (k,v: READABLE_STRING_8) - -- Add header `k:v', or replace existing header of same header name/key - do - Precursor (k, v) - ensure then - added: has_header_named (k) - end - - put_header_key_values (k: READABLE_STRING_8; a_values: ITERABLE [READABLE_STRING_8]; a_separator: detachable READABLE_STRING_8) - -- Add header `k: a_values', or replace existing header of same header values/key. - -- Use `comma_space' as default separator if `a_separator' is Void or empty. - do - Precursor (k, a_values, a_separator) - ensure then - added: has_header_named (k) - end - feature -- Redirection remove_location @@ -363,13 +333,18 @@ feature {NONE} -- Implementation: Header change feature {NONE} -- Implementation: Header conversion - append_line_to (s: READABLE_STRING_8; h: STRING_8) + append_line_to (a_line: READABLE_STRING_8; h: STRING_8) + -- Append header line `a_line' to string `h'. + --| this is used to build the header text + require + not_ending_with_new_line: not a_line.ends_with_general ("%N") do - h.append_string (s) + h.append_string (a_line) append_end_of_line_to (h) end append_end_of_line_to (h: STRING_8) + -- Append the CRLN end of header line to string `h'. do h.append_character ('%R') h.append_character ('%N') diff --git a/library/network/protocol/http/src/http_header_builder.e b/library/network/protocol/http/src/http_header_builder.e index eb25525c..12002f67 100644 --- a/library/network/protocol/http/src/http_header_builder.e +++ b/library/network/protocol/http/src/http_header_builder.e @@ -39,14 +39,14 @@ feature -- Header change: deferred -- if it already exists, there will be multiple header with same name -- which can also be valid require - h_not_empty: not h.is_empty + h_not_empty: h /= Void and then not h.is_empty deferred end put_header (h: READABLE_STRING_8) -- Add header `h' or replace existing header of same header name require - h_not_empty: not h.is_empty + h_not_empty: h /= Void and then not h.is_empty deferred end @@ -127,6 +127,8 @@ feature -- Header change: general s.append (colon_space) s.append (v) add_header (s) + ensure + added: has_header_named (k) end put_header_key_value (k,v: READABLE_STRING_8) @@ -139,6 +141,8 @@ feature -- Header change: general s.append (colon_space) s.append (v) put_header (s) + ensure + added: has_header_named (k) end put_header_key_values (k: READABLE_STRING_8; a_values: ITERABLE [READABLE_STRING_8]; a_separator: detachable READABLE_STRING_8) @@ -165,27 +169,32 @@ feature -- Header change: general if not s.is_empty then put_header_key_value (k, s) end + ensure + added: has_header_named (k) end feature -- Content related header - put_content_type (t: READABLE_STRING_8) + put_content_type (a_content_type: READABLE_STRING_8) + -- Put header line "Content-Type:" + type `a_content_type' do - put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t) + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, a_content_type) end - add_content_type (t: READABLE_STRING_8) + add_content_type (a_content_type: READABLE_STRING_8) -- same as `put_content_type', but allow multiple definition of "Content-Type" do - add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t) + add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, a_content_type) end - put_content_type_with_parameters (t: READABLE_STRING_8; a_params: detachable ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]) + put_content_type_with_parameters (a_content_type: READABLE_STRING_8; a_params: detachable ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]) + -- Put header line "Content-Type:" + type `a_content_type' and extra paramaters `a_params' + --| note: see `put_content_type_with_charset' for examples. local s: STRING_8 do if a_params /= Void and then not a_params.is_empty then - create s.make_from_string (t) + create s.make_from_string (a_content_type) across a_params as p loop @@ -201,16 +210,18 @@ feature -- Content related header end put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, s) else - put_content_type (t) + put_content_type (a_content_type) end end - add_content_type_with_parameters (t: READABLE_STRING_8; a_params: detachable ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]) + add_content_type_with_parameters (a_content_type: READABLE_STRING_8; a_params: detachable ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]) + -- Add header line "Content-Type:" + type `a_content_type' and extra paramaters `a_params'. + --| note: see `put_content_type_with_charset' for examples. local s: STRING_8 do if a_params /= Void and then not a_params.is_empty then - create s.make_from_string (t) + create s.make_from_string (a_content_type) across a_params as p loop @@ -226,39 +237,42 @@ feature -- Content related header end add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, s) else - add_content_type (t) + add_content_type (a_content_type) end end - put_content_type_with_charset (t: READABLE_STRING_8; c: READABLE_STRING_8) + put_content_type_with_charset (a_content_type: READABLE_STRING_8; a_charset: READABLE_STRING_8) + -- Put content type `a_content_type' with `a_charset' as "charset" parameter. do - put_content_type_with_parameters (t, <<["charset", c]>>) + put_content_type_with_parameters (a_content_type, <<["charset", a_charset]>>) end - add_content_type_with_charset (t: READABLE_STRING_8; c: READABLE_STRING_8) - -- same as `put_content_type_with_charset', but allow multiple definition of "Content-Type" + add_content_type_with_charset (a_content_type: READABLE_STRING_8; a_charset: READABLE_STRING_8) + -- Same as `put_content_type_with_charset', but allow multiple definition of "Content-Type". do - add_content_type_with_parameters (t, <<["charset", c]>>) + add_content_type_with_parameters (a_content_type, <<["charset", a_charset]>>) end - put_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8) + put_content_type_with_name (a_content_type: READABLE_STRING_8; a_name: READABLE_STRING_8) + -- Put content type `a_content_type' with `a_name' as "name" parameter. do - put_content_type_with_parameters (t, <<["name", n]>>) + put_content_type_with_parameters (a_content_type, <<["name", a_name]>>) end - add_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8) + add_content_type_with_name (a_content_type: READABLE_STRING_8; a_name: READABLE_STRING_8) -- same as `put_content_type_with_name', but allow multiple definition of "Content-Type" do - add_content_type_with_parameters (t, <<["name", n]>>) + add_content_type_with_parameters (a_content_type, <<["name", a_name]>>) end - put_content_length (n: INTEGER) + put_content_length (a_length: INTEGER) + -- Put "Content-Length:" + length `a_length'. do - put_header_key_value ({HTTP_HEADER_NAMES}.header_content_length, n.out) + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_length, a_length.out) end put_content_transfer_encoding (a_mechanism: READABLE_STRING_8) - -- Put "Content-Transfer-Encoding" header with for instance "binary" + -- Put "Content-Transfer-Encoding" header with `a_mechanism' --| encoding := "Content-Transfer-Encoding" ":" mechanism --| --| mechanism := "7bit" ; case-insensitive @@ -277,16 +291,17 @@ feature -- Content related header put_header_key_value ({HTTP_HEADER_NAMES}.header_content_language, a_lang) end - put_content_encoding (a_enc: READABLE_STRING_8) - -- Put "Content-Encoding" header of value `a_enc'. + put_content_encoding (a_encoding: READABLE_STRING_8) + -- Put "Content-Encoding" header of value `a_encoding'. do - put_header_key_value ({HTTP_HEADER_NAMES}.header_content_encoding, a_enc) + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_encoding, a_encoding) end - put_transfer_encoding (a_enc: READABLE_STRING_8) - -- Put "Transfer-Encoding" header with for instance "chunked" + put_transfer_encoding (a_encoding: READABLE_STRING_8) + -- Put "Transfer-Encoding" header with `a_encoding' value. + --| for instance "chunked" do - put_header_key_value ({HTTP_HEADER_NAMES}.header_transfer_encoding, a_enc) + put_header_key_value ({HTTP_HEADER_NAMES}.header_transfer_encoding, a_encoding) end put_transfer_encoding_binary @@ -367,10 +382,12 @@ feature -- Content-type helpers feature -- Cross-Origin Resource Sharing - put_access_control_allow_origin (s: READABLE_STRING_8) - -- Put "Access-Control-Allow-Origin" header. + put_access_control_allow_origin (a_origin: READABLE_STRING_8) + -- Put "Access-Control-Allow-Origin: " + `a_origin' header. + -- `a_origin' specifies a URI that may access the resource + --| for instance "http://example.com" do - put_header_key_value ({HTTP_HEADER_NAMES}.header_access_control_allow_origin, s) + put_header_key_value ({HTTP_HEADER_NAMES}.header_access_control_allow_origin, a_origin) end put_access_control_allow_all_origin @@ -379,16 +396,43 @@ feature -- Cross-Origin Resource Sharing put_access_control_allow_origin ("*") end + put_access_control_allow_credentials (b: BOOLEAN) + -- Indicates whether or not the response to the request can be exposed when the credentials flag is true. + -- When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials. + -- Note that simple GET requests are not preflighted, and so if a request is made for a resource with credentials, + -- if this header is not returned with the resource, the response is ignored by the browser and not returned to web content. + -- ex: Access-Control-Allow-Credentials: true | false + do + if b then + put_header_key_value ({HTTP_HEADER_NAMES}.header_access_control_allow_Credentials, "true") + else + put_header_key_value ({HTTP_HEADER_NAMES}.header_access_control_allow_Credentials, "false") + end + end + put_access_control_allow_methods (a_methods: ITERABLE [READABLE_STRING_8]) -- If `a_methods' is not empty, put `Access-Control-Allow-Methods' header with list `a_methods' of methods + -- `a_methods' specifies the method or methods allowed when accessing the resource. + -- This is used in response to a preflight request. + -- ex: Access-Control-Allow-Methods: [, ]* do put_header_key_values ({HTTP_HEADER_NAMES}.header_access_control_allow_methods, a_methods, Void) end - put_access_control_allow_headers (s: READABLE_STRING_8) - -- Put "Access-Control-Allow-Headers" header. + put_access_control_allow_headers (a_headers: READABLE_STRING_8) + -- Put "Access-Control-Allow-Headers" header. with value `a_headers' + -- Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. + -- ex: Access-Control-Allow-Headers: [, ]* do - put_header_key_value ({HTTP_HEADER_NAMES}.header_access_control_allow_headers, s) + put_header_key_value ({HTTP_HEADER_NAMES}.header_access_control_allow_headers, a_headers) + end + + put_access_control_allow_iterable_headers (a_fields: ITERABLE [READABLE_STRING_8]) + -- Put "Access-Control-Allow-Headers" header. with value `a_headers' + -- Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. + -- ex: Access-Control-Allow-Headers: [, ]* + do + put_header_key_values ({HTTP_HEADER_NAMES}.header_access_control_allow_headers, a_fields, Void) end feature -- Method related @@ -401,10 +445,10 @@ feature -- Method related feature -- Date - put_date (s: READABLE_STRING_8) + put_date (a_date: READABLE_STRING_8) -- Put "Date: " header do - put_header_key_value ({HTTP_HEADER_NAMES}.header_date, s) + put_header_key_value ({HTTP_HEADER_NAMES}.header_date, a_date) end put_current_date @@ -414,74 +458,89 @@ feature -- Date end put_utc_date (a_utc_date: DATE_TIME) - -- Put UTC date time `dt' with "Date" header + -- Put UTC date time `a_utc_date' with "Date" header + -- using RFC1123 date formating. do put_date (date_to_rfc1123_http_date_format (a_utc_date)) end put_last_modified (a_utc_date: DATE_TIME) - -- Put UTC date time `dt' with "Date" header + -- Put UTC date time `dt' with "Last-Modified" header do put_header_key_value ({HTTP_HEADER_NAMES}.header_last_modified, date_to_rfc1123_http_date_format (a_utc_date)) end feature -- Authorization - put_authorization (s: READABLE_STRING_8) - -- Put authorization `s' with "Authorization" header + put_authorization (a_authorization: READABLE_STRING_8) + -- Put `a_authorization' with "Authorization" header + -- The Authorization header is constructed as follows: + -- 1. Username and password are combined into a string "username:password". + -- 2. The resulting string literal is then encoded using Base64. + -- 3. The authorization method and a space, i.e. "Basic " is then put before the encoded string. + -- ex: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== do - put_header_key_value ({HTTP_HEADER_NAMES}.header_authorization, s) + put_header_key_value ({HTTP_HEADER_NAMES}.header_authorization, a_authorization) end feature -- Others - put_expires (sec: INTEGER) + put_expires (a_seconds: INTEGER) + -- Put "Expires" header to `a_seconds' seconds do - put_expires_string (sec.out) + put_expires_string (a_seconds.out) end - put_expires_string (s: STRING) + put_expires_string (a_expires: STRING) + -- Put "Expires" header with `a_expires' string value do - put_header_key_value ("Expires", s) + put_header_key_value ("Expires", a_expires) end put_expires_date (a_utc_date: DATE_TIME) + -- Put "Expires" header with UTC date time value + -- formatted following RFC1123 specification. do put_header_key_value ("Expires", date_to_rfc1123_http_date_format (a_utc_date)) end - put_cache_control (s: READABLE_STRING_8) - -- `s' could be for instance "no-cache, must-revalidate" + put_cache_control (a_cache_control: READABLE_STRING_8) + -- Put "Cache-Control" header with value `a_cache_control' + --| note: ex "Cache-Control: no-cache, must-revalidate" do - put_header_key_value ("Cache-Control", s) + put_header_key_value ("Cache-Control", a_cache_control) end - put_pragma (s: READABLE_STRING_8) + put_pragma (a_pragma: READABLE_STRING_8) + -- Put "Pragma" header with value `a_pragma' do - put_header_key_value ("Pragma", s) + put_header_key_value ("Pragma", a_pragma) end put_pragma_no_cache + -- Put "Pragma" header with "no-cache" a_pragma do put_pragma ("no-cache") end feature -- Redirection - put_location (a_location: READABLE_STRING_8) - -- Tell the client the new location `a_location' + put_location (a_uri: READABLE_STRING_8) + -- Tell the client the new location `a_uri' + -- using "Location" header. require - a_location_valid: not a_location.is_empty + a_uri_valid: not a_uri.is_empty do - put_header_key_value ({HTTP_HEADER_NAMES}.header_location, a_location) + put_header_key_value ({HTTP_HEADER_NAMES}.header_location, a_uri) end - put_refresh (a_location: READABLE_STRING_8; a_timeout_in_seconds: INTEGER) - -- Tell the client to refresh page with `a_location' after `a_timeout_in_seconds' in seconds + put_refresh (a_uri: READABLE_STRING_8; a_timeout_in_seconds: INTEGER) + -- Tell the client to refresh page with `a_uri' after `a_timeout_in_seconds' in seconds + -- using "Refresh" header. require - a_location_valid: not a_location.is_empty + a_uri_valid: not a_uri.is_empty do - put_header_key_value ({HTTP_HEADER_NAMES}.header_refresh, a_timeout_in_seconds.out + "; url=" + a_location) + put_header_key_value ({HTTP_HEADER_NAMES}.header_refresh, a_timeout_in_seconds.out + "; url=" + a_uri) end feature -- Cookie diff --git a/library/network/protocol/http/src/http_header_names.e b/library/network/protocol/http/src/http_header_names.e index 4bab76e8..f64bdc26 100644 --- a/library/network/protocol/http/src/http_header_names.e +++ b/library/network/protocol/http/src/http_header_names.e @@ -199,17 +199,26 @@ feature -- Cross-Origin Resource Sharing header_access_control_allow_origin: STRING = "Access-Control-Allow-Origin" -- Indicates whether a resource can be shared based by returning -- the value of the Origin request header in the response. - -- | Example: Access-Control-Allow-Origin: http://example.org + --| Example: Access-Control-Allow-Origin: http://example.org + + header_access_control_allow_credentials: STRING = "Access-Control-Allow-Credentials" + -- Indicates whether or not the response to the request can be exposed when the credentials flag is true. + -- When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials. + -- Note that simple GET requests are not preflighted, and so if a request is made for a resource with credentials, + -- if this header is not returned with the resource, the response is ignored by the browser and not returned to web content. + --| Access-Control-Allow-Credentials: true | false header_access_control_allow_methods: STRING = "Access-Control-Allow-Methods" -- Indicates, as part of the response to a preflight request, -- which methods can be used during the actual request. - -- | Example: Access-Control-Allow-Methods: PUT, DELETE + --| Access-Control-Allow-Methods: [, ]* + --| Example: Access-Control-Allow-Methods: PUT, DELETE header_access_control_allow_headers: STRING = "Access-Control-Allow-Headers" -- Indicates, as part of the response to a preflight request, -- which header field names can be used during the actual request. - -- | Example: Access-Control-Allow-Headers: Authorization + --| Access-Control-Allow-Headers: [, ]* + --| Example: Access-Control-Allow-Headers: Authorization feature -- Request or Response header name @@ -265,7 +274,7 @@ feature -- MIME related header_content_transfer_encoding: STRING = "Content-Transfer-Encoding" note - copyright: "2011-2013, Jocelyn Fiat, Eiffel Software and others" + copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software