Class renaming for content_negotiation
Splitted SERVER_CONTENT_NEGOTIATION in 4 differents classes for each kind of negotiation Changed to use ITERABLE over LIST for supported variants arguments Factorized some code for http parameter parsing such as q=1.0;note="blabla" and so on Integrated within EWF
This commit is contained in:
@@ -1,249 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {CONNEG_SERVER_SIDE}. Utility class to support Server Side Content Negotiation "
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
description: "[
|
||||
Reference : http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.1
|
||||
Server-driven Negotiation : If the selection of the best representation for a response is made by an algorithm located at the server,
|
||||
it is called server-driven negotiation. Selection is based on the available representations of the response (the dimensions over which it can vary; e.g. language, content-coding, etc.)
|
||||
and the contents of particular header fields in the request message or on other information pertaining to the request (such as the network address of the client).
|
||||
Server-driven negotiation is advantageous when the algorithm for selecting from among the available representations is difficult to describe to the user agent,
|
||||
or when the server desires to send its "best guess" to the client along with the first response (hoping to avoid the round-trip delay of a subsequent request if the "best guess" is good enough for the user).
|
||||
In order to improve the server's guess, the user agent MAY include request header fields (Accept, Accept-Language, Accept-Encoding, etc.) which describe its preferences for such a response.
|
||||
]"
|
||||
EIS: "name=server driven negotiation", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.", "protocol=uri"
|
||||
|
||||
class
|
||||
CONNEG_SERVER_SIDE
|
||||
|
||||
inherit
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_mediatype_dft: READABLE_STRING_8; a_language_dft: READABLE_STRING_8; a_charset_dft: READABLE_STRING_8; a_encoding_dft: READABLE_STRING_8)
|
||||
-- Initialize Current with default Media type, language, charset and encoding.
|
||||
do
|
||||
initialize
|
||||
set_default_media_type (a_mediatype_dft)
|
||||
set_default_language (a_language_dft)
|
||||
set_default_charset (a_charset_dft)
|
||||
set_default_encoding (a_encoding_dft)
|
||||
ensure
|
||||
default_media_type_set: default_media_type = a_mediatype_dft
|
||||
default_language_set: default_language = a_language_dft
|
||||
default_charset_set: default_charset = a_charset_dft
|
||||
default_encoding_set: default_encoding = a_encoding_dft
|
||||
end
|
||||
|
||||
initialize
|
||||
-- Initialize Current
|
||||
do
|
||||
create accept_media_type_parser
|
||||
create any_header_parser
|
||||
create accept_language_parser
|
||||
end
|
||||
|
||||
accept_media_type_parser: HTTP_ACCEPT_MEDIA_TYPE_PARSER
|
||||
-- MIME
|
||||
|
||||
any_header_parser: HTTP_ANY_ACCEPT_HEADER_PARSER
|
||||
-- Charset and Encoding
|
||||
|
||||
accept_language_parser: HTTP_ACCEPT_LANGUAGE_PARSER
|
||||
-- Language
|
||||
|
||||
feature -- Access: Server Side Defaults Formats
|
||||
|
||||
default_media_type: READABLE_STRING_8
|
||||
-- Media type which is acceptable for the response.
|
||||
|
||||
default_language: READABLE_STRING_8
|
||||
-- Natural language that is preferred as a response to the request.
|
||||
|
||||
default_charset: READABLE_STRING_8
|
||||
-- Character set that is acceptable for the response.
|
||||
|
||||
default_encoding: READABLE_STRING_8
|
||||
-- Content-coding that is acceptable in the response.
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
set_default_media_type (a_mediatype: READABLE_STRING_8)
|
||||
-- Set `default_media_type' with `a_mediatype'
|
||||
do
|
||||
default_media_type := a_mediatype
|
||||
ensure
|
||||
default_media_type_set: a_mediatype = default_media_type
|
||||
end
|
||||
|
||||
set_default_language (a_language: READABLE_STRING_8)
|
||||
-- Set `default_language' with `a_language'
|
||||
do
|
||||
default_language := a_language
|
||||
ensure
|
||||
default_language_set: a_language = default_language
|
||||
end
|
||||
|
||||
set_default_charset (a_charset: READABLE_STRING_8)
|
||||
-- Set `default_charset' with `a_charset'
|
||||
do
|
||||
default_charset := a_charset
|
||||
ensure
|
||||
default_charset_set: a_charset = default_charset
|
||||
end
|
||||
|
||||
set_default_encoding (a_encoding: READABLE_STRING_8)
|
||||
-- Set `default_encoding' with `a_encoding'
|
||||
do
|
||||
default_encoding := a_encoding
|
||||
ensure
|
||||
default_encoding_set: a_encoding = default_encoding
|
||||
end
|
||||
|
||||
feature -- Media Type Negotiation
|
||||
|
||||
media_type_preference (a_mime_types_supported: LIST [READABLE_STRING_8]; a_header: detachable READABLE_STRING_8): HTTP_ACCEPT_MEDIA_TYPE_VARIANTS
|
||||
-- `a_mime_types_supported' represent media types supported by the server.
|
||||
-- `a_header represent' the Accept header, ie, the client preferences.
|
||||
-- Return which media type to use for representation in a response, if the server supports
|
||||
-- the requested media type, or empty in other case.
|
||||
note
|
||||
EIS: "name=media type", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1", "protocol=uri"
|
||||
local
|
||||
l_mime_match: READABLE_STRING_8
|
||||
do
|
||||
create Result.make
|
||||
Result.set_supported_variants (a_mime_types_supported)
|
||||
if a_header = Void or else a_header.is_empty then
|
||||
-- the request has no Accept header, ie the header is empty, in this case we use the default format
|
||||
Result.set_acceptable (True)
|
||||
Result.set_variant_value (default_media_type)
|
||||
else
|
||||
Result.set_vary_header_value
|
||||
|
||||
-- select the best match, server support, client preferences
|
||||
l_mime_match := accept_media_type_parser.best_match (a_mime_types_supported, a_header)
|
||||
if l_mime_match.is_empty then
|
||||
-- The server does not support any of the media types preferred by the client
|
||||
Result.set_acceptable (False)
|
||||
else
|
||||
-- Set the best match
|
||||
Result.set_variant_value (l_mime_match)
|
||||
Result.set_acceptable (True)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Encoding Negotiation
|
||||
|
||||
charset_preference (a_server_charset_supported: LIST [READABLE_STRING_8]; a_header: detachable READABLE_STRING_8): HTTP_ACCEPT_CHARSET_VARIANTS
|
||||
-- `a_server_charset_supported' represent a list of character sets supported by the server.
|
||||
-- `a_header' represents the Accept-Charset header, ie, the client preferences.
|
||||
-- Return which Charset to use in a response, if the server supports
|
||||
-- the requested Charset, or empty in other case.
|
||||
note
|
||||
EIS: "name=charset", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2", "protocol=uri"
|
||||
local
|
||||
l_charset_match: READABLE_STRING_8
|
||||
do
|
||||
create Result.make
|
||||
Result.set_supported_variants (a_server_charset_supported)
|
||||
if a_header = Void or else a_header.is_empty then
|
||||
-- the request has no Accept-Charset header, ie the header is empty, in this case use default charset encoding
|
||||
Result.set_acceptable (True)
|
||||
Result.set_variant_value (default_charset)
|
||||
else
|
||||
Result.set_vary_header_value
|
||||
|
||||
-- select the best match, server support, client preferences
|
||||
l_charset_match := any_header_parser.best_match (a_server_charset_supported, a_header)
|
||||
if l_charset_match.is_empty then
|
||||
-- The server does not support any of the compression types prefered by the client
|
||||
Result.set_acceptable (False)
|
||||
else
|
||||
-- Set the best match
|
||||
Result.set_variant_value (l_charset_match)
|
||||
Result.set_acceptable (True)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Compression Negotiation
|
||||
|
||||
encoding_preference (a_server_encoding_supported: LIST [READABLE_STRING_8]; a_header_value: detachable READABLE_STRING_8): HTTP_ACCEPT_ENCODING_VARIANTS
|
||||
-- `a_server_encoding_supported' represent a list of encoding supported by the server.
|
||||
-- `a_header_value' represent the Accept-Encoding header, ie, the client preferences.
|
||||
-- Return which Encoding to use in a response, if the server supports
|
||||
-- the requested Encoding, or empty in other case.
|
||||
note
|
||||
EIS: "name=encoding", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3", "protocol=uri"
|
||||
local
|
||||
l_compression_match: READABLE_STRING_8
|
||||
do
|
||||
create Result.make
|
||||
Result.set_supported_variants (a_server_encoding_supported)
|
||||
if a_header_value = Void or else a_header_value.is_empty then
|
||||
-- the request has no Accept-Encoding header, ie the header is empty, in this case do not compress representations
|
||||
Result.set_acceptable (True)
|
||||
Result.set_variant_value (default_encoding)
|
||||
else
|
||||
Result.set_vary_header_value
|
||||
|
||||
-- select the best match, server support, client preferences
|
||||
l_compression_match := any_header_parser.best_match (a_server_encoding_supported, a_header_value)
|
||||
if l_compression_match.is_empty then
|
||||
-- The server does not support any of the compression types prefered by the client
|
||||
Result.set_acceptable (False)
|
||||
else
|
||||
-- Set the best match
|
||||
Result.set_variant_value (l_compression_match)
|
||||
Result.set_acceptable (True)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Language Negotiation
|
||||
|
||||
language_preference (a_server_language_supported: LIST [READABLE_STRING_8]; a_header_value: detachable READABLE_STRING_8): HTTP_ACCEPT_LANGUAGE_VARIANTS
|
||||
-- `a_server_language_supported' represent a list of languages supported by the server.
|
||||
-- `a_header_value' represent the Accept-Language header, ie, the client preferences.
|
||||
-- Return which Language to use in a response, if the server supports
|
||||
-- the requested Language, or empty in other case.
|
||||
note
|
||||
EIS: "name=language", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4", "protocol=uri"
|
||||
|
||||
local
|
||||
l_language_match: READABLE_STRING_8
|
||||
do
|
||||
create Result.make
|
||||
Result.set_supported_variants (a_server_language_supported)
|
||||
|
||||
if a_header_value = Void or else a_header_value.is_empty then
|
||||
-- the request has no Accept header, ie the header is empty, in this case we use the default format
|
||||
Result.set_acceptable (True)
|
||||
Result.set_variant_value (default_language)
|
||||
else
|
||||
Result.set_vary_header_value
|
||||
|
||||
-- select the best match, server support, client preferences
|
||||
l_language_match := accept_language_parser.best_match (a_server_language_supported, a_header_value)
|
||||
if l_language_match.is_empty then
|
||||
-- The server does not support any of the media types prefered by the client
|
||||
Result.set_acceptable (False)
|
||||
else
|
||||
-- Set the best match
|
||||
Result.set_variant_value (l_language_match)
|
||||
Result.set_acceptable (True)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
note
|
||||
description: "[
|
||||
{HTTP_ACCEPT_LANGUAGE_PARSER} is encharge to parse language tags defined as follow:
|
||||
{HTTP_ACCEPT_LANGUAGE_UTILITIES} is in charge to parse language tags defined as follow:
|
||||
|
||||
Accept-Language = "Accept-Language" ":"
|
||||
1#( language-l_range [ ";" "q" "=" qvalue ] )
|
||||
@@ -15,13 +15,10 @@ note
|
||||
EIS: "name=Accept-Language", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4", "protocol=uri"
|
||||
|
||||
class
|
||||
HTTP_ACCEPT_LANGUAGE_PARSER
|
||||
HTTP_ACCEPT_LANGUAGE_UTILITIES
|
||||
|
||||
inherit
|
||||
|
||||
HTTP_HEADER_PARSER
|
||||
|
||||
REFACTORING_HELPER
|
||||
HTTP_HEADER_UTILITIES
|
||||
|
||||
feature -- Parser
|
||||
|
||||
@@ -68,29 +65,22 @@ feature -- Parser
|
||||
Result := quality_from_list (a_language, accept_language_list (a_ranges))
|
||||
end
|
||||
|
||||
best_match (a_supported: LIST [READABLE_STRING_8]; a_header_value: READABLE_STRING_8): READABLE_STRING_8
|
||||
best_match (a_supported: ITERABLE [READABLE_STRING_8]; a_header_value: READABLE_STRING_8): READABLE_STRING_8
|
||||
-- Choose the `parse_language' with the highest fitness score and quality ('q') from a list of candidates.
|
||||
local
|
||||
l_header_results: LIST [HTTP_ACCEPT_LANGUAGE]
|
||||
l_weighted_matches: LIST [FITNESS_AND_QUALITY]
|
||||
l_res: LIST [READABLE_STRING_8]
|
||||
p_res: HTTP_ACCEPT_LANGUAGE
|
||||
l_fitness_and_quality, l_first_one: detachable FITNESS_AND_QUALITY
|
||||
s: READABLE_STRING_8
|
||||
do
|
||||
l_header_results := accept_language_list (a_header_value)
|
||||
|
||||
--| weighted matches
|
||||
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} l_weighted_matches.make (a_supported.count)
|
||||
from
|
||||
a_supported.start
|
||||
until
|
||||
a_supported.after
|
||||
loop
|
||||
l_fitness_and_quality := fitness_and_quality_from_list (a_supported.item_for_iteration, l_header_results)
|
||||
l_fitness_and_quality.set_entity (entity_value (a_supported.item_for_iteration))
|
||||
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} l_weighted_matches.make (0)
|
||||
across a_supported as ic loop
|
||||
l_fitness_and_quality := fitness_and_quality_from_list (ic.item, l_header_results)
|
||||
l_fitness_and_quality.set_entity (entity_value (ic.item))
|
||||
l_weighted_matches.force (l_fitness_and_quality)
|
||||
a_supported.forth
|
||||
end
|
||||
|
||||
--| Keep only top quality+fitness types
|
||||
@@ -177,7 +167,6 @@ feature {NONE} -- Implementation
|
||||
l_target: HTTP_ACCEPT_LANGUAGE
|
||||
l_target_type: READABLE_STRING_8
|
||||
l_range: HTTP_ACCEPT_LANGUAGE
|
||||
l_keys: LIST [READABLE_STRING_8]
|
||||
l_param_matches: INTEGER
|
||||
l_element: detachable READABLE_STRING_8
|
||||
l_fitness: INTEGER
|
||||
@@ -201,23 +190,21 @@ feature {NONE} -- Implementation
|
||||
or l_target_type.same_string ("*")
|
||||
)
|
||||
then
|
||||
from
|
||||
l_param_matches := 0
|
||||
l_keys := l_target.keys
|
||||
l_keys.start
|
||||
until
|
||||
l_keys.after
|
||||
loop
|
||||
l_element := l_keys.item_for_iteration
|
||||
if
|
||||
not l_element.same_string ("q") and then
|
||||
l_range.has_key (l_element) and then
|
||||
(attached l_target.item (l_element) as t_item and attached l_range.item (l_element) as r_item) and then
|
||||
t_item.same_string (r_item)
|
||||
then
|
||||
l_param_matches := l_param_matches + 1
|
||||
l_param_matches := 0
|
||||
if attached l_target.parameters as l_target_parameters then
|
||||
across
|
||||
l_target_parameters as ic
|
||||
loop
|
||||
l_element := ic.key
|
||||
if
|
||||
not l_element.same_string ("q") and then
|
||||
l_range.has_parameter (l_element) and then
|
||||
(attached ic.item as t_item and attached l_range.parameter (l_element) as r_item) and then
|
||||
t_item.same_string (r_item)
|
||||
then
|
||||
l_param_matches := l_param_matches + 1
|
||||
end
|
||||
end
|
||||
l_keys.forth
|
||||
end
|
||||
if l_range_type.same_string (l_target_type) then
|
||||
l_fitness := 100
|
||||
@@ -239,7 +226,7 @@ feature {NONE} -- Implementation
|
||||
l_fitness := l_fitness + l_param_matches
|
||||
if l_fitness > l_best_fitness then
|
||||
l_best_fitness := l_fitness
|
||||
l_element := l_range.item ("q")
|
||||
l_element := l_range.parameter ("q")
|
||||
if l_element /= Void then
|
||||
l_best_fit_q := l_element.to_real_64.min (l_target_q)
|
||||
else
|
||||
@@ -1,6 +1,6 @@
|
||||
note
|
||||
description: "[
|
||||
{HTTP_ACCEPT_MEDIA_TYPE_PARSER}. is encharge to parse Accept request-header field defined as follow:
|
||||
{HTTP_ACCEPT_MEDIA_TYPE_UTILITIES}. is encharge to parse Accept request-header field defined as follow:
|
||||
|
||||
Accept = "Accept" ":"
|
||||
#( media-range [ accept-params ] )
|
||||
@@ -20,13 +20,10 @@
|
||||
EIS: "name=Accept", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1", "protocol=uri"
|
||||
|
||||
class
|
||||
HTTP_ACCEPT_MEDIA_TYPE_PARSER
|
||||
HTTP_ACCEPT_MEDIA_TYPE_UTILITIES
|
||||
|
||||
inherit
|
||||
|
||||
HTTP_HEADER_PARSER
|
||||
|
||||
REFACTORING_HELPER
|
||||
HTTP_HEADER_UTILITIES
|
||||
|
||||
feature -- Parser
|
||||
|
||||
@@ -81,7 +78,7 @@ feature -- Parser
|
||||
Result := quality_from_list (a_mime_type, res)
|
||||
end
|
||||
|
||||
best_match (supported: LIST [READABLE_STRING_8]; header: READABLE_STRING_8): READABLE_STRING_8
|
||||
best_match (supported: ITERABLE [READABLE_STRING_8]; header: READABLE_STRING_8): READABLE_STRING_8
|
||||
-- Choose the mime-type with the highest fitness score and quality ('q') from a list of candidates.
|
||||
local
|
||||
l_header_results: LIST [HTTP_MEDIA_TYPE]
|
||||
@@ -105,17 +102,12 @@ feature -- Parser
|
||||
l_res.forth
|
||||
end
|
||||
|
||||
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} weighted_matches.make (supported.count)
|
||||
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} weighted_matches.make (0)
|
||||
|
||||
from
|
||||
supported.start
|
||||
until
|
||||
supported.after
|
||||
loop
|
||||
fitness_and_quality := fitness_and_quality_from_list (supported.item_for_iteration, l_header_results)
|
||||
fitness_and_quality.set_entity (entity_value (supported.item_for_iteration))
|
||||
across supported as ic loop
|
||||
fitness_and_quality := fitness_and_quality_from_list (ic.item, l_header_results)
|
||||
fitness_and_quality.set_entity (entity_value (ic.item))
|
||||
weighted_matches.force (fitness_and_quality)
|
||||
supported.forth
|
||||
end
|
||||
|
||||
--| Keep only top quality+fitness types
|
||||
@@ -236,13 +228,9 @@ feature {NONE} -- Implementation
|
||||
)
|
||||
then
|
||||
if attached target.parameters as l_keys then
|
||||
from
|
||||
param_matches := 0
|
||||
l_keys.start
|
||||
until
|
||||
l_keys.after
|
||||
loop
|
||||
element := l_keys.key_for_iteration
|
||||
param_matches := 0
|
||||
across l_keys as ic loop
|
||||
element := ic.key
|
||||
if
|
||||
not element.same_string ("q") and then
|
||||
range.has_parameter (element) and then
|
||||
@@ -251,7 +239,6 @@ feature {NONE} -- Implementation
|
||||
then
|
||||
param_matches := param_matches + 1
|
||||
end
|
||||
l_keys.forth
|
||||
end
|
||||
end
|
||||
if l_range_type.same_string (l_target_type) then
|
||||
@@ -9,56 +9,34 @@ note
|
||||
EIS: "name=Encoding", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3", "protocol=uri"
|
||||
|
||||
class
|
||||
HTTP_ANY_ACCEPT_HEADER_PARSER
|
||||
HTTP_ANY_ACCEPT_HEADER_UTILITIES
|
||||
|
||||
inherit
|
||||
HTTP_HEADER_PARSER
|
||||
HTTP_HEADER_UTILITIES
|
||||
|
||||
feature -- Parser
|
||||
|
||||
header (a_header: READABLE_STRING_8): HTTP_ANY_ACCEPT_HEADER
|
||||
header (a_header: READABLE_STRING_8): HTTP_ANY_ACCEPT
|
||||
-- Parses `a_header' charset/encoding into its component parts.
|
||||
-- For example, the charset 'iso-8889-5' would get parsed
|
||||
-- into:
|
||||
-- ('iso-8889-5', {'q':'1.0'})
|
||||
local
|
||||
l_parts: LIST [READABLE_STRING_8]
|
||||
sub_parts: LIST [READABLE_STRING_8]
|
||||
p: READABLE_STRING_8
|
||||
i: INTEGER
|
||||
l_header: READABLE_STRING_8
|
||||
do
|
||||
create Result.make
|
||||
l_parts := a_header.split (';')
|
||||
if l_parts.count = 1 then
|
||||
Result.put ("1.0", "q")
|
||||
else
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i > l_parts.count
|
||||
loop
|
||||
p := l_parts [i]
|
||||
sub_parts := p.split ('=')
|
||||
if sub_parts.count = 2 then
|
||||
Result.put (trim (sub_parts [2]), trim (sub_parts [1]))
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
create Result.make_from_string (a_header)
|
||||
if Result.parameter ("q") = Void then
|
||||
Result.put_parameter ("1.0", "q")
|
||||
end
|
||||
l_header := trim (l_parts [1])
|
||||
Result.set_field (trim (l_header))
|
||||
end
|
||||
|
||||
quality (a_field: READABLE_STRING_8; a_commons: READABLE_STRING_8): REAL_64
|
||||
quality (a_field: READABLE_STRING_8; a_header: READABLE_STRING_8): REAL_64
|
||||
-- Returns the quality 'q' of a charset/encoding when compared against the
|
||||
-- a list of charsets/encodings/
|
||||
local
|
||||
l_commons: LIST [READABLE_STRING_8]
|
||||
res: ARRAYED_LIST [HTTP_ANY_ACCEPT_HEADER]
|
||||
p_res: HTTP_ANY_ACCEPT_HEADER
|
||||
res: ARRAYED_LIST [HTTP_ANY_ACCEPT]
|
||||
p_res: HTTP_ANY_ACCEPT
|
||||
do
|
||||
l_commons := a_commons.split (',')
|
||||
l_commons := a_header.split (',')
|
||||
from
|
||||
create res.make (10)
|
||||
l_commons.start
|
||||
@@ -72,17 +50,17 @@ feature -- Parser
|
||||
Result := quality_from_list (a_field, res)
|
||||
end
|
||||
|
||||
best_match (a_supported: LIST [READABLE_STRING_8]; a_header: READABLE_STRING_8): READABLE_STRING_8
|
||||
best_match (a_supported: ITERABLE [READABLE_STRING_8]; a_header: READABLE_STRING_8): READABLE_STRING_8
|
||||
-- Choose the accept with the highest fitness score and quality ('q') from a list of candidates.
|
||||
local
|
||||
l_header_results: LIST [HTTP_ANY_ACCEPT_HEADER]
|
||||
l_header_results: LIST [HTTP_ANY_ACCEPT]
|
||||
l_weighted_matches: LIST [FITNESS_AND_QUALITY]
|
||||
l_res: LIST [READABLE_STRING_8]
|
||||
p_res: HTTP_ANY_ACCEPT_HEADER
|
||||
p_res: HTTP_ANY_ACCEPT
|
||||
l_fitness_and_quality, l_first_one: detachable FITNESS_AND_QUALITY
|
||||
do
|
||||
l_res := a_header.split (',')
|
||||
create {ARRAYED_LIST [HTTP_ANY_ACCEPT_HEADER]} l_header_results.make (l_res.count)
|
||||
create {ARRAYED_LIST [HTTP_ANY_ACCEPT]} l_header_results.make (l_res.count)
|
||||
from
|
||||
l_res.start
|
||||
until
|
||||
@@ -92,16 +70,11 @@ feature -- Parser
|
||||
l_header_results.force (p_res)
|
||||
l_res.forth
|
||||
end
|
||||
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} l_weighted_matches.make (a_supported.count)
|
||||
from
|
||||
a_supported.start
|
||||
until
|
||||
a_supported.after
|
||||
loop
|
||||
l_fitness_and_quality := fitness_and_quality_from_list (a_supported.item_for_iteration, l_header_results)
|
||||
l_fitness_and_quality.set_entity (entity_value (a_supported.item_for_iteration))
|
||||
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} l_weighted_matches.make (0)
|
||||
across a_supported as ic loop
|
||||
l_fitness_and_quality := fitness_and_quality_from_list (ic.item, l_header_results)
|
||||
l_fitness_and_quality.set_entity (entity_value (ic.item))
|
||||
l_weighted_matches.force (l_fitness_and_quality)
|
||||
a_supported.forth
|
||||
end
|
||||
|
||||
--| Keep only top quality+fitness types
|
||||
@@ -150,7 +123,7 @@ feature -- Parser
|
||||
until
|
||||
l_header_results.after or l_fitness_and_quality /= Void
|
||||
loop
|
||||
if attached l_header_results.item.field as l_field then
|
||||
if attached l_header_results.item.value as l_field then
|
||||
from
|
||||
l_weighted_matches.start
|
||||
until
|
||||
@@ -184,7 +157,7 @@ feature -- Parser
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
fitness_and_quality_from_list (a_field: READABLE_STRING_8; a_parsed_charsets: LIST [HTTP_ANY_ACCEPT_HEADER]): FITNESS_AND_QUALITY
|
||||
fitness_and_quality_from_list (a_field: READABLE_STRING_8; a_parsed_charsets: LIST [HTTP_ANY_ACCEPT]): FITNESS_AND_QUALITY
|
||||
-- Find the best match for a given charset/encoding against a list of charsets/encodings
|
||||
-- that have already been parsed by parse_common. Returns a
|
||||
-- tuple of the fitness value and the value of the 'q' quality parameter of
|
||||
@@ -194,15 +167,15 @@ feature {NONE} -- Implementation
|
||||
best_fitness: INTEGER
|
||||
target_q: REAL_64
|
||||
best_fit_q: REAL_64
|
||||
target: HTTP_ANY_ACCEPT_HEADER
|
||||
range: HTTP_ANY_ACCEPT_HEADER
|
||||
target: HTTP_ANY_ACCEPT
|
||||
range: HTTP_ANY_ACCEPT
|
||||
element: detachable READABLE_STRING_8
|
||||
l_fitness: INTEGER
|
||||
do
|
||||
best_fitness := -1
|
||||
best_fit_q := 0.0
|
||||
target := header (a_field)
|
||||
if attached target.item ("q") as q and then q.is_double then
|
||||
if attached target.parameter ("q") as q and then q.is_double then
|
||||
target_q := q.to_double
|
||||
if target_q < 0.0 then
|
||||
target_q := 0.0
|
||||
@@ -212,14 +185,14 @@ feature {NONE} -- Implementation
|
||||
else
|
||||
target_q := 1.0
|
||||
end
|
||||
if attached target.field as l_target_field then
|
||||
if attached target.value as l_target_field then
|
||||
from
|
||||
a_parsed_charsets.start
|
||||
until
|
||||
a_parsed_charsets.after
|
||||
loop
|
||||
range := a_parsed_charsets.item_for_iteration
|
||||
if attached range.field as l_range_common then
|
||||
if attached range.value as l_range_common then
|
||||
if l_target_field.same_string (l_range_common) or l_target_field.same_string ("*") or l_range_common.same_string ("*") then
|
||||
if l_range_common.same_string (l_target_field) then
|
||||
l_fitness := 100
|
||||
@@ -228,7 +201,7 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
if l_fitness > best_fitness then
|
||||
best_fitness := l_fitness
|
||||
element := range.item ("q")
|
||||
element := range.parameter ("q")
|
||||
if element /= Void then
|
||||
best_fit_q := element.to_double.min (target_q)
|
||||
else
|
||||
@@ -243,7 +216,7 @@ feature {NONE} -- Implementation
|
||||
create Result.make (best_fitness, best_fit_q)
|
||||
end
|
||||
|
||||
quality_from_list (a_field: READABLE_STRING_8; a_parsed_common: LIST [HTTP_ANY_ACCEPT_HEADER]): REAL_64
|
||||
quality_from_list (a_field: READABLE_STRING_8; a_parsed_common: LIST [HTTP_ANY_ACCEPT]): REAL_64
|
||||
-- Find the best match for a given charset/encoding against a list of charsets/encodings that
|
||||
-- have already been parsed by parse_charsets(). Returns the 'q' quality
|
||||
-- parameter of the best match, 0 if no match was found. This function
|
||||
@@ -252,7 +225,6 @@ feature {NONE} -- Implementation
|
||||
Result := fitness_and_quality_from_list (a_field, a_parsed_common).quality
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
@@ -1,11 +1,14 @@
|
||||
note
|
||||
description: "Summary description for {HTTP_HEADER_PARSER}."
|
||||
description: "Summary description for {HTTP_HEADER_UTILITIES}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTP_HEADER_PARSER
|
||||
HTTP_HEADER_UTILITIES
|
||||
|
||||
inherit
|
||||
REFACTORING_HELPER
|
||||
|
||||
feature {NONE} -- Helpers
|
||||
|
||||
@@ -16,13 +19,13 @@ feature {NONE} -- Helpers
|
||||
do
|
||||
p := a_str.index_of (';', 1)
|
||||
if p > 0 then
|
||||
Result := trim (a_str.substring (1, p - 1))
|
||||
Result := trimmed_string (a_str.substring (1, p - 1))
|
||||
else
|
||||
Result := trim (a_str.string)
|
||||
Result := trimmed_string (a_str.string)
|
||||
end
|
||||
end
|
||||
|
||||
trim (a_string: READABLE_STRING_8): STRING_8
|
||||
trimmed_string (a_string: READABLE_STRING_8): STRING_8
|
||||
-- trim whitespace from the beginning and end of a string
|
||||
-- `a_string'
|
||||
require
|
||||
@@ -28,74 +28,50 @@ feature {NONE} -- Initialization
|
||||
-- In addition this also guarantees that there is a value for 'q'
|
||||
-- in the params dictionary, filling it in with a proper default if
|
||||
-- necessary.
|
||||
require
|
||||
a_accept_language_item_not_empty: not a_accept_language_item.is_empty
|
||||
local
|
||||
l_parts: LIST [READABLE_STRING_8]
|
||||
p: READABLE_STRING_8
|
||||
i: INTEGER
|
||||
l_tag: STRING_8
|
||||
do
|
||||
fixme (generator + ".make_from_string: improve code!!!")
|
||||
l_parts := a_accept_language_item.split (';')
|
||||
from
|
||||
l_parts.start
|
||||
make_with_language (trimmed_string (l_parts.item))
|
||||
if not l_parts.after then
|
||||
l_parts.forth
|
||||
end
|
||||
until
|
||||
l_parts.after
|
||||
loop
|
||||
p := l_parts.item
|
||||
i := p.index_of ('=', 1)
|
||||
if i > 0 then
|
||||
put (trimmed_string (p.substring (i + 1, p.count)), trimmed_string (p.substring (1, i - 1)))
|
||||
else
|
||||
check is_well_formed_parameter: False end
|
||||
end
|
||||
l_parts.forth
|
||||
i := a_accept_language_item.index_of (';', 1)
|
||||
if i > 0 then
|
||||
make_with_language (trimmed_string (a_accept_language_item.substring (1, i - 1)))
|
||||
create parameters.make_from_substring (a_accept_language_item, i + 1, a_accept_language_item.count)
|
||||
check attached parameters as l_params and then not l_params.has_error end
|
||||
else
|
||||
make_with_language (trimmed_string (a_accept_language_item))
|
||||
end
|
||||
|
||||
check quality_initialized_to_1: quality = 1.0 end
|
||||
|
||||
-- Get quality from parameter if any, and format the value as expected.
|
||||
if attached item ("q") as q then
|
||||
if attached parameter ("q") as q then
|
||||
if q.same_string ("1") then
|
||||
--| Use 1.0 formatting
|
||||
put ("1.0", "q")
|
||||
put_parameter ("1.0", "q")
|
||||
elseif q.is_double and then attached q.to_real_64 as r then
|
||||
if r <= 0.0 then
|
||||
quality := 0.0 --| Should it be 1.0 ?
|
||||
put_parameter ("0.0", "q")
|
||||
elseif r >= 1.0 then
|
||||
quality := 1.0
|
||||
put_parameter ("1.0", "q")
|
||||
else
|
||||
quality := r
|
||||
end
|
||||
else
|
||||
put ("1.0", "q")
|
||||
put_parameter ("1.0", "q")
|
||||
quality := 1.0
|
||||
end
|
||||
else
|
||||
put ("1.0", "q")
|
||||
put_parameter ("1.0", "q")
|
||||
end
|
||||
end
|
||||
|
||||
make_with_language (a_lang_tag: READABLE_STRING_8)
|
||||
-- Instantiate Current from language tag `a_lang_tag'.
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
initialize
|
||||
|
||||
create language_range.make_from_string (a_lang_tag)
|
||||
i := a_lang_tag.index_of ('-', 1)
|
||||
if i > 0 then
|
||||
language := a_lang_tag.substring (1, i - 1)
|
||||
specialization := a_lang_tag.substring (i + 1, a_lang_tag.count)
|
||||
else
|
||||
language := a_lang_tag
|
||||
end
|
||||
set_language_range (a_lang_tag)
|
||||
ensure
|
||||
language_range_set: language_range.same_string (a_lang_tag) and a_lang_tag /= language_range
|
||||
end
|
||||
@@ -119,7 +95,7 @@ feature {NONE} -- Initialization
|
||||
initialize
|
||||
-- Initialize Current
|
||||
do
|
||||
create params.make (2)
|
||||
create parameters.make (1)
|
||||
quality := 1.0
|
||||
end
|
||||
|
||||
@@ -148,37 +124,24 @@ feature -- Status report
|
||||
Result.append_double (quality)
|
||||
end
|
||||
|
||||
feature -- Parameters
|
||||
|
||||
item (a_key: STRING): detachable STRING
|
||||
-- Item associated with `a_key', if present
|
||||
-- otherwise default value of type `STRING'
|
||||
do
|
||||
Result := params.item (a_key)
|
||||
end
|
||||
|
||||
keys: LIST [STRING]
|
||||
-- arrays of currents keys
|
||||
local
|
||||
res: ARRAYED_LIST [STRING]
|
||||
do
|
||||
create res.make_from_array (params.current_keys)
|
||||
Result := res
|
||||
end
|
||||
|
||||
params: HASH_TABLE [STRING, STRING]
|
||||
-- dictionary of all the parameters for the media range
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
has_key (a_key: STRING): BOOLEAN
|
||||
-- Is there an item in the table with key `a_key'?
|
||||
do
|
||||
Result := params.has_key (a_key)
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_language_range (a_lang_range: READABLE_STRING_8)
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
create language_range.make_from_string (a_lang_range)
|
||||
i := a_lang_range.index_of ('-', 1)
|
||||
if i > 0 then
|
||||
language := a_lang_range.substring (1, i - 1)
|
||||
specialization := a_lang_range.substring (i + 1, a_lang_range.count)
|
||||
else
|
||||
language := a_lang_range
|
||||
end
|
||||
ensure
|
||||
language_range_set: language_range.same_string (a_lang_range) and a_lang_range /= language_range
|
||||
end
|
||||
|
||||
set_language (a_root_lang: READABLE_STRING_8)
|
||||
-- Set `'anguage' with `a_root_lang'
|
||||
require
|
||||
@@ -199,19 +162,47 @@ feature -- Element change
|
||||
specialization_assigned: specialization ~ a_specialization
|
||||
end
|
||||
|
||||
put (new: STRING; key: STRING)
|
||||
-- Insert `new' with `key' if there is no other item
|
||||
-- associated with the same key. If present, replace
|
||||
-- the old value with `new'
|
||||
feature -- Parameters: Access
|
||||
|
||||
parameter (a_key: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- Parameter associated with `a_key', if present
|
||||
-- otherwise default value of type `STRING'
|
||||
do
|
||||
if params.has_key (key) then
|
||||
params.replace (new, key)
|
||||
else
|
||||
params.force (new, key)
|
||||
if attached parameters as l_params then
|
||||
Result := l_params.item (a_key)
|
||||
end
|
||||
end
|
||||
|
||||
parameters: detachable HTTP_PARAMETER_TABLE
|
||||
-- Table of all parameters for the media range
|
||||
|
||||
feature -- Parameters: Status report
|
||||
|
||||
has_parameter (a_key: READABLE_STRING_8): BOOLEAN
|
||||
-- Is there an parameter in the parameters table with key `a_key'?
|
||||
do
|
||||
if attached parameters as l_params then
|
||||
Result := l_params.has_key (a_key)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Parameters: Change
|
||||
|
||||
put_parameter (a_value: READABLE_STRING_8; a_key: READABLE_STRING_8)
|
||||
-- Insert `a_value' with `a_key' if there is no other item
|
||||
-- associated with the same key. If present, replace
|
||||
-- the old value with `a_value'
|
||||
local
|
||||
l_parameters: like parameters
|
||||
do
|
||||
l_parameters := parameters
|
||||
if l_parameters = Void then
|
||||
create l_parameters.make (1)
|
||||
parameters := l_parameters
|
||||
end
|
||||
l_parameters.force (a_value, a_key)
|
||||
ensure
|
||||
has_key: params.has_key (key)
|
||||
has_item: params.has_item (new)
|
||||
is_set: attached parameters as l_params and then (l_params.has_key (a_key) and l_params.has_item (a_value))
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
note
|
||||
description: "Object that represents a results after parsing Accept(-*) headers."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HTTP_ANY_ACCEPT
|
||||
|
||||
inherit
|
||||
REFACTORING_HELPER
|
||||
|
||||
DEBUG_OUTPUT
|
||||
|
||||
create
|
||||
make_from_string
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make_from_string (a_string: READABLE_STRING_8)
|
||||
local
|
||||
l_parts: LIST [READABLE_STRING_8]
|
||||
sub_parts: LIST [READABLE_STRING_8]
|
||||
p: READABLE_STRING_8
|
||||
i: INTEGER
|
||||
do
|
||||
initialize
|
||||
i := a_string.index_of (';', 1)
|
||||
if i > 0 then
|
||||
set_value (trimmed_string (a_string.substring (1, i - 1)))
|
||||
create parameters.make_from_substring (a_string, i + 1, a_string.count)
|
||||
else
|
||||
set_value (trimmed_string (a_string))
|
||||
end
|
||||
end
|
||||
|
||||
initialize
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
value: READABLE_STRING_8
|
||||
-- Value composing an Accept(-*) header value
|
||||
|
||||
feature -- Access: parameters
|
||||
|
||||
parameter (a_key: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- Item associated with `a_key', if present
|
||||
-- otherwise default value of type `STRING'
|
||||
do
|
||||
if attached parameters as l_parameters then
|
||||
Result := l_parameters.item (a_key)
|
||||
end
|
||||
end
|
||||
|
||||
parameters: detachable HTTP_PARAMETER_TABLE
|
||||
-- Table of all parameters for the media range
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
has_parameter (a_key: READABLE_STRING_8): BOOLEAN
|
||||
-- Is there an item in the table with key `a_key'?
|
||||
do
|
||||
if attached parameters as l_parameters then
|
||||
Result := l_parameters.has_key (a_key)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_value (v: READABLE_STRING_8)
|
||||
-- Set `value' with `v'
|
||||
do
|
||||
value := v
|
||||
ensure
|
||||
value_set: attached value as l_value implies l_value.same_string (v)
|
||||
end
|
||||
|
||||
put_parameter (a_value: READABLE_STRING_8; a_key: READABLE_STRING_8)
|
||||
-- Insert `a_value' with `a_key' if there is no other item
|
||||
-- associated with the same key. If present, replace
|
||||
-- the old value with `a_value'
|
||||
local
|
||||
l_parameters: like parameters
|
||||
do
|
||||
l_parameters := parameters
|
||||
if l_parameters = Void then
|
||||
create l_parameters.make (1)
|
||||
parameters := l_parameters
|
||||
end
|
||||
l_parameters.force (a_value, a_key)
|
||||
ensure
|
||||
is_set: attached parameters as l_params and then (l_params.has_key (a_key) and l_params.has_item (a_value))
|
||||
end
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
create Result.make_from_string (value)
|
||||
end
|
||||
|
||||
feature {NONE} -- Helper
|
||||
|
||||
trimmed_string (s: READABLE_STRING_8): STRING_8
|
||||
-- Copy of `s', where whitespace were stripped from the beginning and end of the string
|
||||
do
|
||||
create Result.make_from_string (s)
|
||||
Result.left_adjust
|
||||
Result.right_adjust
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
end
|
||||
@@ -1,89 +0,0 @@
|
||||
note
|
||||
description: "Object that represents a results after parsing Accept-* headers."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HTTP_ANY_ACCEPT_HEADER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create params.make (2)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
field: detachable STRING
|
||||
|
||||
item (a_key: STRING): detachable STRING
|
||||
-- Item associated with `a_key', if present
|
||||
-- otherwise default value of type `STRING'
|
||||
do
|
||||
Result := params.item (a_key)
|
||||
end
|
||||
|
||||
keys: LIST [STRING]
|
||||
-- arrays of currents keys
|
||||
local
|
||||
res: ARRAYED_LIST [STRING]
|
||||
do
|
||||
create res.make_from_array (params.current_keys)
|
||||
Result := res
|
||||
end
|
||||
|
||||
params: HASH_TABLE [STRING, STRING]
|
||||
-- Table of all parameters for the media range
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
has_key (a_key: STRING): BOOLEAN
|
||||
-- Is there an item in the table with key `a_key'?
|
||||
do
|
||||
Result := params.has_key (a_key)
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_field (a_field: STRING)
|
||||
-- Set type with `a_field'
|
||||
do
|
||||
field := a_field
|
||||
ensure
|
||||
field_set: attached field as l_field implies l_field = a_field
|
||||
end
|
||||
|
||||
put (new: STRING; key: STRING)
|
||||
-- Insert `new' with `key' if there is no other item
|
||||
-- associated with the same key. If present, replace
|
||||
-- the old value with `new'
|
||||
do
|
||||
if params.has_key (key) then
|
||||
params.replace (new, key)
|
||||
else
|
||||
params.force (new, key)
|
||||
end
|
||||
ensure
|
||||
has_key: params.has_key (key)
|
||||
has_item: params.has_item (new)
|
||||
end
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := out
|
||||
end
|
||||
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
end
|
||||
@@ -0,0 +1,92 @@
|
||||
note
|
||||
description: "Summary description for {SERVER_CHARSET_NEGOTIATION}. Utility class to support Server Side Content Negotiation on charset "
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
description: "[
|
||||
Reference : http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.1
|
||||
Server-driven Negotiation : If the selection of the best representation for a response is made by an algorithm located at the server,
|
||||
it is called server-driven negotiation. Selection is based on the available representations of the response (the dimensions over which it can vary; e.g. language, content-coding, etc.)
|
||||
and the contents of particular header fields in the request message or on other information pertaining to the request (such as the network address of the client).
|
||||
Server-driven negotiation is advantageous when the algorithm for selecting from among the available representations is difficult to describe to the user agent,
|
||||
or when the server desires to send its "best guess" to the client along with the first response (hoping to avoid the round-trip delay of a subsequent request if the "best guess" is good enough for the user).
|
||||
In order to improve the server's guess, the user agent MAY include request header fields (Accept, Accept-Language, Accept-Encoding, etc.) which describe its preferences for such a response.
|
||||
]"
|
||||
EIS: "name=server driven negotiation", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.", "protocol=uri"
|
||||
|
||||
class
|
||||
SERVER_CHARSET_NEGOTIATION
|
||||
|
||||
inherit
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_charset_dft: READABLE_STRING_8)
|
||||
do
|
||||
create accept_charset_utilities
|
||||
set_default_charset (a_charset_dft)
|
||||
ensure
|
||||
default_charset_set: default_charset = a_charset_dft
|
||||
end
|
||||
|
||||
accept_charset_utilities: HTTP_ANY_ACCEPT_HEADER_UTILITIES
|
||||
-- Charset
|
||||
|
||||
feature -- Access: Server Side Defaults Formats
|
||||
|
||||
default_charset: READABLE_STRING_8
|
||||
-- Character set that is acceptable for the response.
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
set_default_charset (a_charset: READABLE_STRING_8)
|
||||
-- Set `default_charset' with `a_charset'
|
||||
do
|
||||
default_charset := a_charset
|
||||
ensure
|
||||
default_charset_set: a_charset = default_charset
|
||||
end
|
||||
|
||||
feature -- Charset Negotiation
|
||||
|
||||
preference (a_server_charset_supported: ITERABLE [READABLE_STRING_8]; a_header: detachable READABLE_STRING_8): HTTP_ACCEPT_CHARSET_VARIANTS
|
||||
-- `a_server_charset_supported' represent a list of character sets supported by the server.
|
||||
-- `a_header' represents the Accept-Charset header, ie, the client preferences.
|
||||
-- Return which Charset to use in a response, if the server supports
|
||||
-- the requested Charset, or empty in other case.
|
||||
note
|
||||
EIS: "name=charset", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2", "protocol=uri"
|
||||
local
|
||||
l_charset_match: READABLE_STRING_8
|
||||
do
|
||||
create Result.make
|
||||
Result.set_supported_variants (a_server_charset_supported)
|
||||
if a_header = Void or else a_header.is_empty then
|
||||
-- the request has no Accept-Charset header, ie the header is empty, in this case use default charset encoding
|
||||
Result.set_acceptable (True)
|
||||
Result.set_variant_value (default_charset)
|
||||
else
|
||||
Result.set_vary_header_value
|
||||
|
||||
-- select the best match, server support, client preferences
|
||||
l_charset_match := accept_charset_utilities.best_match (a_server_charset_supported, a_header)
|
||||
if l_charset_match.is_empty then
|
||||
-- The server does not support any of the compression types prefered by the client
|
||||
Result.set_acceptable (False)
|
||||
else
|
||||
-- Set the best match
|
||||
Result.set_variant_value (l_charset_match)
|
||||
Result.set_acceptable (True)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
end
|
||||
@@ -0,0 +1,67 @@
|
||||
note
|
||||
description: "Summary description for {SERVER_CONTENT_NEGOTIATION}. Utility class to support Server Side Content Negotiation "
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
description: "[
|
||||
Reference : http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.1
|
||||
Server-driven Negotiation : If the selection of the best representation for a response is made by an algorithm located at the server,
|
||||
it is called server-driven negotiation. Selection is based on the available representations of the response (the dimensions over which it can vary; e.g. language, content-coding, etc.)
|
||||
and the contents of particular header fields in the request message or on other information pertaining to the request (such as the network address of the client).
|
||||
Server-driven negotiation is advantageous when the algorithm for selecting from among the available representations is difficult to describe to the user agent,
|
||||
or when the server desires to send its "best guess" to the client along with the first response (hoping to avoid the round-trip delay of a subsequent request if the "best guess" is good enough for the user).
|
||||
In order to improve the server's guess, the user agent MAY include request header fields (Accept, Accept-Language, Accept-Encoding, etc.) which describe its preferences for such a response.
|
||||
]"
|
||||
EIS: "name=server driven negotiation", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.", "protocol=uri"
|
||||
|
||||
class
|
||||
SERVER_CONTENT_NEGOTIATION
|
||||
|
||||
inherit
|
||||
SERVER_MEDIA_TYPE_NEGOTIATION
|
||||
rename
|
||||
make as make_media_type,
|
||||
preference as media_type_preference
|
||||
end
|
||||
|
||||
SERVER_LANGUAGE_NEGOTIATION
|
||||
rename
|
||||
make as make_language,
|
||||
preference as language_preference
|
||||
end
|
||||
|
||||
SERVER_CHARSET_NEGOTIATION
|
||||
rename
|
||||
make as make_charset,
|
||||
preference as charset_preference
|
||||
end
|
||||
|
||||
SERVER_ENCODING_NEGOTIATION
|
||||
rename
|
||||
make as make_encoding,
|
||||
preference as encoding_preference
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_mediatype_dft: READABLE_STRING_8; a_language_dft: READABLE_STRING_8; a_charset_dft: READABLE_STRING_8; a_encoding_dft: READABLE_STRING_8)
|
||||
-- Initialize Current with default Media type, language, charset and encoding.
|
||||
do
|
||||
make_media_type (a_mediatype_dft)
|
||||
make_language (a_language_dft)
|
||||
make_charset (a_charset_dft)
|
||||
make_encoding (a_encoding_dft)
|
||||
ensure
|
||||
default_media_type_set: default_media_type = a_mediatype_dft
|
||||
default_language_set: default_language = a_language_dft
|
||||
default_charset_set: default_charset = a_charset_dft
|
||||
default_encoding_set: default_encoding = a_encoding_dft
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
end
|
||||
@@ -0,0 +1,91 @@
|
||||
note
|
||||
description: "Summary description for {SERVER_ENCODING_NEGOTIATION}. Utility class to support Server Side Content Negotiation on encoding"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
description: "[
|
||||
Reference : http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.1
|
||||
Server-driven Negotiation : If the selection of the best representation for a response is made by an algorithm located at the server,
|
||||
it is called server-driven negotiation. Selection is based on the available representations of the response (the dimensions over which it can vary; e.g. language, content-coding, etc.)
|
||||
and the contents of particular header fields in the request message or on other information pertaining to the request (such as the network address of the client).
|
||||
Server-driven negotiation is advantageous when the algorithm for selecting from among the available representations is difficult to describe to the user agent,
|
||||
or when the server desires to send its "best guess" to the client along with the first response (hoping to avoid the round-trip delay of a subsequent request if the "best guess" is good enough for the user).
|
||||
In order to improve the server's guess, the user agent MAY include request header fields (Accept, Accept-Language, Accept-Encoding, etc.) which describe its preferences for such a response.
|
||||
]"
|
||||
EIS: "name=server driven negotiation", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.", "protocol=uri"
|
||||
|
||||
class
|
||||
SERVER_ENCODING_NEGOTIATION
|
||||
|
||||
inherit
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_encoding_dft: READABLE_STRING_8)
|
||||
do
|
||||
create accept_encoding_utilities
|
||||
set_default_encoding (a_encoding_dft)
|
||||
ensure
|
||||
default_encoding_set: default_encoding = a_encoding_dft
|
||||
end
|
||||
|
||||
accept_encoding_utilities: HTTP_ANY_ACCEPT_HEADER_UTILITIES
|
||||
-- Encoding
|
||||
|
||||
feature -- Access: Server Side Defaults Formats
|
||||
|
||||
default_encoding: READABLE_STRING_8
|
||||
-- Content-coding that is acceptable in the response.
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
set_default_encoding (a_encoding: READABLE_STRING_8)
|
||||
-- Set `default_encoding' with `a_encoding'
|
||||
do
|
||||
default_encoding := a_encoding
|
||||
ensure
|
||||
default_encoding_set: a_encoding = default_encoding
|
||||
end
|
||||
|
||||
feature -- Encoding Negotiation
|
||||
|
||||
preference (a_server_encoding_supported: ITERABLE [READABLE_STRING_8]; a_header_value: detachable READABLE_STRING_8): HTTP_ACCEPT_ENCODING_VARIANTS
|
||||
-- `a_server_encoding_supported' represent a list of encoding supported by the server.
|
||||
-- `a_header_value' represent the Accept-Encoding header, ie, the client preferences.
|
||||
-- Return which Encoding to use in a response, if the server supports
|
||||
-- the requested Encoding, or empty in other case.
|
||||
note
|
||||
EIS: "name=encoding", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3", "protocol=uri"
|
||||
local
|
||||
l_compression_match: READABLE_STRING_8
|
||||
do
|
||||
create Result.make
|
||||
Result.set_supported_variants (a_server_encoding_supported)
|
||||
if a_header_value = Void or else a_header_value.is_empty then
|
||||
-- the request has no Accept-Encoding header, ie the header is empty, in this case do not compress representations
|
||||
Result.set_acceptable (True)
|
||||
Result.set_variant_value (default_encoding)
|
||||
else
|
||||
Result.set_vary_header_value
|
||||
|
||||
-- select the best match, server support, client preferences
|
||||
l_compression_match := accept_encoding_utilities.best_match (a_server_encoding_supported, a_header_value)
|
||||
if l_compression_match.is_empty then
|
||||
-- The server does not support any of the compression types prefered by the client
|
||||
Result.set_acceptable (False)
|
||||
else
|
||||
-- Set the best match
|
||||
Result.set_variant_value (l_compression_match)
|
||||
Result.set_acceptable (True)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
end
|
||||
@@ -0,0 +1,93 @@
|
||||
note
|
||||
description: "Summary description for {SERVER_LANGUAGE_NEGOTIATION}. Utility class to support Server Side Content Negotiation on language"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
description: "[
|
||||
Reference : http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.1
|
||||
Server-driven Negotiation : If the selection of the best representation for a response is made by an algorithm located at the server,
|
||||
it is called server-driven negotiation. Selection is based on the available representations of the response (the dimensions over which it can vary; e.g. language, content-coding, etc.)
|
||||
and the contents of particular header fields in the request message or on other information pertaining to the request (such as the network address of the client).
|
||||
Server-driven negotiation is advantageous when the algorithm for selecting from among the available representations is difficult to describe to the user agent,
|
||||
or when the server desires to send its "best guess" to the client along with the first response (hoping to avoid the round-trip delay of a subsequent request if the "best guess" is good enough for the user).
|
||||
In order to improve the server's guess, the user agent MAY include request header fields (Accept, Accept-Language, Accept-Encoding, etc.) which describe its preferences for such a response.
|
||||
]"
|
||||
EIS: "name=server driven negotiation", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.", "protocol=uri"
|
||||
|
||||
class
|
||||
SERVER_LANGUAGE_NEGOTIATION
|
||||
|
||||
inherit
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_language_dft: READABLE_STRING_8)
|
||||
do
|
||||
create accept_language_utilities
|
||||
set_default_language (a_language_dft)
|
||||
ensure
|
||||
default_language_set: default_language = a_language_dft
|
||||
end
|
||||
|
||||
accept_language_utilities: HTTP_ACCEPT_LANGUAGE_UTILITIES
|
||||
-- Language
|
||||
|
||||
feature -- Access: Server Side Defaults Formats
|
||||
|
||||
default_language: READABLE_STRING_8
|
||||
-- Natural language that is preferred as a response to the request.
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
set_default_language (a_language: READABLE_STRING_8)
|
||||
-- Set `default_language' with `a_language'
|
||||
do
|
||||
default_language := a_language
|
||||
ensure
|
||||
default_language_set: a_language = default_language
|
||||
end
|
||||
|
||||
feature -- Language Negotiation
|
||||
|
||||
preference (a_server_language_supported: ITERABLE [READABLE_STRING_8]; a_header_value: detachable READABLE_STRING_8): HTTP_ACCEPT_LANGUAGE_VARIANTS
|
||||
-- `a_server_language_supported' represent a list of languages supported by the server.
|
||||
-- `a_header_value' represent the Accept-Language header, ie, the client preferences.
|
||||
-- Return which Language to use in a response, if the server supports
|
||||
-- the requested Language, or empty in other case.
|
||||
note
|
||||
EIS: "name=language", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4", "protocol=uri"
|
||||
|
||||
local
|
||||
l_language_match: READABLE_STRING_8
|
||||
do
|
||||
create Result.make
|
||||
Result.set_supported_variants (a_server_language_supported)
|
||||
|
||||
if a_header_value = Void or else a_header_value.is_empty then
|
||||
-- the request has no Accept header, ie the header is empty, in this case we use the default format
|
||||
Result.set_acceptable (True)
|
||||
Result.set_variant_value (default_language)
|
||||
else
|
||||
Result.set_vary_header_value
|
||||
|
||||
-- select the best match, server support, client preferences
|
||||
l_language_match := accept_language_utilities.best_match (a_server_language_supported, a_header_value)
|
||||
if l_language_match.is_empty then
|
||||
-- The server does not support any of the media types prefered by the client
|
||||
Result.set_acceptable (False)
|
||||
else
|
||||
-- Set the best match
|
||||
Result.set_variant_value (l_language_match)
|
||||
Result.set_acceptable (True)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
end
|
||||
@@ -0,0 +1,91 @@
|
||||
note
|
||||
description: "Summary description for {SERVER_MEDIA_TYPE_NEGOTIATION}. Utility class to support Server Side Content Negotiation on media type"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
description: "[
|
||||
Reference : http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.1
|
||||
Server-driven Negotiation : If the selection of the best representation for a response is made by an algorithm located at the server,
|
||||
it is called server-driven negotiation. Selection is based on the available representations of the response (the dimensions over which it can vary; e.g. language, content-coding, etc.)
|
||||
and the contents of particular header fields in the request message or on other information pertaining to the request (such as the network address of the client).
|
||||
Server-driven negotiation is advantageous when the algorithm for selecting from among the available representations is difficult to describe to the user agent,
|
||||
or when the server desires to send its "best guess" to the client along with the first response (hoping to avoid the round-trip delay of a subsequent request if the "best guess" is good enough for the user).
|
||||
In order to improve the server's guess, the user agent MAY include request header fields (Accept, Accept-Language, Accept-Encoding, etc.) which describe its preferences for such a response.
|
||||
]"
|
||||
EIS: "name=server driven negotiation", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.", "protocol=uri"
|
||||
|
||||
class
|
||||
SERVER_MEDIA_TYPE_NEGOTIATION
|
||||
|
||||
inherit
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_mediatype_dft: READABLE_STRING_8)
|
||||
do
|
||||
create accept_media_type_utilities
|
||||
set_default_media_type (a_mediatype_dft)
|
||||
ensure
|
||||
default_media_type_set: default_media_type = a_mediatype_dft
|
||||
end
|
||||
|
||||
accept_media_type_utilities: HTTP_ACCEPT_MEDIA_TYPE_UTILITIES
|
||||
-- MIME
|
||||
|
||||
feature -- Access: Server Side Defaults Formats
|
||||
|
||||
default_media_type: READABLE_STRING_8
|
||||
-- Media type which is acceptable for the response.
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
set_default_media_type (a_mediatype: READABLE_STRING_8)
|
||||
-- Set `default_media_type' with `a_mediatype'
|
||||
do
|
||||
default_media_type := a_mediatype
|
||||
ensure
|
||||
default_media_type_set: a_mediatype = default_media_type
|
||||
end
|
||||
|
||||
feature -- Media Type Negotiation
|
||||
|
||||
preference (a_mime_types_supported: ITERABLE [READABLE_STRING_8]; a_header: detachable READABLE_STRING_8): HTTP_ACCEPT_MEDIA_TYPE_VARIANTS
|
||||
-- `a_mime_types_supported' represent media types supported by the server.
|
||||
-- `a_header represent' the Accept header, ie, the client preferences.
|
||||
-- Return which media type to use for representation in a response, if the server supports
|
||||
-- the requested media type, or empty in other case.
|
||||
note
|
||||
EIS: "name=media type", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1", "protocol=uri"
|
||||
local
|
||||
l_mime_match: READABLE_STRING_8
|
||||
do
|
||||
create Result.make
|
||||
Result.set_supported_variants (a_mime_types_supported)
|
||||
if a_header = Void or else a_header.is_empty then
|
||||
-- the request has no Accept header, ie the header is empty, in this case we use the default format
|
||||
Result.set_acceptable (True)
|
||||
Result.set_variant_value (default_media_type)
|
||||
else
|
||||
Result.set_vary_header_value
|
||||
|
||||
-- select the best match, server support, client preferences
|
||||
l_mime_match := accept_media_type_utilities.best_match (a_mime_types_supported, a_header)
|
||||
if l_mime_match.is_empty then
|
||||
-- The server does not support any of the media types preferred by the client
|
||||
Result.set_acceptable (False)
|
||||
else
|
||||
-- Set the best match
|
||||
Result.set_variant_value (l_mime_match)
|
||||
Result.set_acceptable (True)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
end
|
||||
@@ -1,31 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {SHARED_CONNEG}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
SHARED_CONNEG
|
||||
|
||||
feature
|
||||
|
||||
Mime: HTTP_ACCEPT_MEDIA_TYPE_PARSER
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
Common: HTTP_ANY_ACCEPT_HEADER_PARSER
|
||||
-- Charset and Encoding
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
Language: HTTP_ACCEPT_LANGUAGE_PARSER
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
end
|
||||
@@ -28,7 +28,7 @@ feature -- Access
|
||||
-- this indicates the Accept-* header source of the matched `variant_value' if any,
|
||||
-- if this is using the default, the `vary_header_value' is Void.
|
||||
|
||||
supported_variants: detachable LIST [READABLE_STRING_8]
|
||||
supported_variants: detachable ITERABLE [READABLE_STRING_8]
|
||||
-- Set of supported variants for the response
|
||||
|
||||
variant_value: detachable READABLE_STRING_8
|
||||
@@ -77,7 +77,7 @@ feature -- Change Element
|
||||
is_acceptable_set: is_acceptable = b
|
||||
end
|
||||
|
||||
set_supported_variants (a_supported: LIST [READABLE_STRING_8])
|
||||
set_supported_variants (a_supported: ITERABLE [READABLE_STRING_8])
|
||||
-- Set `supported variants' with `a_supported'
|
||||
do
|
||||
supported_variants := a_supported
|
||||
|
||||
@@ -16,10 +16,10 @@ feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
local
|
||||
mime_parse : HTTP_ACCEPT_MEDIA_TYPE_PARSER
|
||||
mime_parse : HTTP_ACCEPT_MEDIA_TYPE_UTILITIES
|
||||
accept : STRING
|
||||
charset_parse : HTTP_ANY_ACCEPT_HEADER_PARSER
|
||||
language : HTTP_ACCEPT_LANGUAGE_PARSER
|
||||
charset_parse : HTTP_ANY_ACCEPT_HEADER_UTILITIES
|
||||
language : HTTP_ACCEPT_LANGUAGE_UTILITIES
|
||||
do
|
||||
create mime_parse
|
||||
-- parse_result := mime_parse.parse_mime_type ("application/xhtml;q=0.5")
|
||||
|
||||
@@ -23,26 +23,24 @@ feature {NONE} -- Events
|
||||
|
||||
feature -- Helpers
|
||||
|
||||
format (a_common: HTTP_ANY_ACCEPT_HEADER): STRING
|
||||
format (a_common: HTTP_ANY_ACCEPT): STRING
|
||||
-- Representation of the current object
|
||||
do
|
||||
create Result.make_from_string ("(")
|
||||
if attached a_common.field as t then
|
||||
if attached a_common.value as t then
|
||||
Result.append_string ("'" + t + "',")
|
||||
end
|
||||
Result.append_string (" {")
|
||||
from
|
||||
a_common.params.start
|
||||
until
|
||||
a_common.params.after
|
||||
loop
|
||||
Result.append ("'" + a_common.params.key_for_iteration + "':'" + a_common.params.item_for_iteration + "',");
|
||||
a_common.params.forth
|
||||
if attached a_common.parameters as l_parameters then
|
||||
across
|
||||
l_parameters as ic
|
||||
loop
|
||||
Result.append ("'" + ic.key + "':'" + ic.item + "',");
|
||||
end
|
||||
end
|
||||
Result.append ("})")
|
||||
end
|
||||
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_parse_charsets
|
||||
@@ -74,6 +72,6 @@ feature -- Test routines
|
||||
assert ("Expected unicode-1-1", parser.best_match (charset_supported, "unicode-1-1;q=1").same_string ("unicode-1-1"))
|
||||
end
|
||||
|
||||
parser : HTTP_ANY_ACCEPT_HEADER_PARSER
|
||||
parser : HTTP_ANY_ACCEPT_HEADER_UTILITIES
|
||||
|
||||
end
|
||||
|
||||
@@ -34,8 +34,8 @@ feature -- Test routines
|
||||
media_variants := conneg.media_type_preference (mime_types_supported, "text/html")
|
||||
assert ("Expected Not Acceptable", not media_variants.is_acceptable)
|
||||
if attached media_variants.supported_variants as l_supported_variants then
|
||||
assert ("Same Value at 1",mime_types_supported.first.same_string (l_supported_variants.first))
|
||||
assert ("Same count",mime_types_supported.count = l_supported_variants.count)
|
||||
assert ("Same Value at 1", same_text (first_of (mime_types_supported), first_of (l_supported_variants)))
|
||||
assert ("Same count", count_of (mime_types_supported) = count_of (l_supported_variants))
|
||||
else
|
||||
assert ("Has supported_variants results", False)
|
||||
end
|
||||
@@ -72,8 +72,8 @@ feature -- Test routines
|
||||
charset_variants := conneg.charset_preference (charset_supported, "unicode-1-1")
|
||||
assert ("Expected Not Acceptable", not charset_variants.is_acceptable)
|
||||
if attached charset_variants.supported_variants as l_supported_variants then
|
||||
assert ("Same Value at 1",charset_supported.first.same_string (l_supported_variants.first))
|
||||
assert ("Same count",charset_supported.count = l_supported_variants.count)
|
||||
assert ("Same Value at 1", same_text (first_of (charset_supported), first_of (l_supported_variants)))
|
||||
assert ("Same count",charset_supported.count = count_of (l_supported_variants))
|
||||
else
|
||||
assert("Has supported_variants results", False)
|
||||
end
|
||||
@@ -109,8 +109,8 @@ feature -- Test routines
|
||||
compression_variants := conneg.encoding_preference (compression_supported, "gzip")
|
||||
assert ("Expected Not Acceptable", not compression_variants.is_acceptable)
|
||||
if attached compression_variants.supported_variants as l_supported_variants then
|
||||
assert ("Same Value at 1",compression_supported.first.same_string (l_supported_variants.first))
|
||||
assert ("Same count",compression_supported.count = l_supported_variants.count)
|
||||
assert ("Same Value at 1", same_text (first_of (compression_supported), first_of (l_supported_variants)))
|
||||
assert ("Same count",compression_supported.count = count_of (l_supported_variants))
|
||||
else
|
||||
assert ("Has supported_variants results", False)
|
||||
end
|
||||
@@ -153,8 +153,8 @@ feature -- Test routines
|
||||
assert ("Variant Header", attached language_variants.vary_header_value as l_variant_header and then l_variant_header.same_string ("Accept-Language"))
|
||||
assert ("Language type is Void",language_variants.language = Void)
|
||||
if attached language_variants.supported_variants as l_supported_variants then
|
||||
assert ("Same Value at 1", languages_supported.first.same_string (l_supported_variants.first))
|
||||
assert ("Same count",languages_supported.count = l_supported_variants.count)
|
||||
assert ("Same Value at 1", same_text (first_of (languages_supported), first_of (l_supported_variants)))
|
||||
assert ("Same count",languages_supported.count = count_of (l_supported_variants))
|
||||
else
|
||||
assert ("Has supported variants results", False)
|
||||
end
|
||||
@@ -175,5 +175,36 @@ feature -- Test routines
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
conneg : CONNEG_SERVER_SIDE
|
||||
conneg : SERVER_CONTENT_NEGOTIATION
|
||||
|
||||
same_text (s1,s2: detachable READABLE_STRING_8): BOOLEAN
|
||||
do
|
||||
if s1 = Void then
|
||||
Result := s2 = Void
|
||||
elseif s2 = Void then
|
||||
Result := False
|
||||
else
|
||||
Result := s1.same_string (s2)
|
||||
end
|
||||
end
|
||||
|
||||
count_of (i: ITERABLE [READABLE_STRING_8]): INTEGER
|
||||
do
|
||||
across
|
||||
i as ic
|
||||
loop
|
||||
Result := Result + 1
|
||||
end
|
||||
end
|
||||
|
||||
first_of (i: ITERABLE [READABLE_STRING_8]): detachable READABLE_STRING_8
|
||||
do
|
||||
across
|
||||
i as ic
|
||||
until
|
||||
ic.item /= Void
|
||||
loop
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -3,3 +3,16 @@ Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected REA
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
Catcall detected in {READABLE_STRING_8}.make_from_string for arg#1: expected READABLE_STRING_8 but got Void
|
||||
|
||||
@@ -34,14 +34,11 @@ feature -- Helpers
|
||||
Result.append_string (" '" + st + "',")
|
||||
end
|
||||
Result.append_string (" {")
|
||||
if attached a_language.params as l_params then
|
||||
from
|
||||
l_params.start
|
||||
until
|
||||
l_params.after
|
||||
if attached a_language.parameters as l_params then
|
||||
across
|
||||
l_params as ic
|
||||
loop
|
||||
Result.append ("'" + l_params.key_for_iteration + "':'"+ l_params.item_for_iteration + "',");
|
||||
l_params.forth
|
||||
Result.append ("'" + ic.key + "':'"+ ic.item + "',");
|
||||
end
|
||||
end
|
||||
Result.append ("})")
|
||||
@@ -137,7 +134,7 @@ feature -- Test routines
|
||||
|
||||
|
||||
|
||||
parser : HTTP_ACCEPT_LANGUAGE_PARSER
|
||||
parser : HTTP_ACCEPT_LANGUAGE_UTILITIES
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -38,13 +38,10 @@ feature -- Helper
|
||||
end
|
||||
Result.append_string (" {")
|
||||
if attached a_mediatype.parameters as l_params then
|
||||
from
|
||||
l_params.start
|
||||
until
|
||||
l_params.after
|
||||
across
|
||||
l_params as ic
|
||||
loop
|
||||
Result.append ("'" + l_params.key_for_iteration + "':'" + l_params.item_for_iteration + "',");
|
||||
l_params.forth
|
||||
Result.append ("'" + ic.key + "':'" + ic.item + "',");
|
||||
end
|
||||
end
|
||||
Result.append ("})")
|
||||
@@ -148,7 +145,7 @@ feature -- Test routines
|
||||
|
||||
|
||||
|
||||
parser : HTTP_ACCEPT_MEDIA_TYPE_PARSER
|
||||
parser : HTTP_ACCEPT_MEDIA_TYPE_UTILITIES
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -63,7 +63,6 @@ feature {NONE} -- Initialization
|
||||
t: STRING_8
|
||||
i,n: INTEGER
|
||||
p: INTEGER
|
||||
cl: CELL [INTEGER]
|
||||
do
|
||||
-- Ignore starting space (should not be any)
|
||||
from
|
||||
@@ -79,15 +78,7 @@ feature {NONE} -- Initialization
|
||||
p := s.index_of (';', i)
|
||||
if p > 0 then
|
||||
t := s.substring (i, p - 1)
|
||||
from
|
||||
create cl.put (p)
|
||||
i := p + 1
|
||||
until
|
||||
i >= n
|
||||
loop
|
||||
add_parameter_from_string (s, i, cl)
|
||||
i := cl.item
|
||||
end
|
||||
create parameters.make_from_substring (s, p + 1, s.count)
|
||||
else
|
||||
t := s.substring (i, n)
|
||||
end
|
||||
@@ -116,7 +107,7 @@ feature {NONE} -- Initialization
|
||||
subtype := type
|
||||
end
|
||||
ensure
|
||||
not has_error implies (create {HTTP_CONTENT_TYPE}.make_from_string (string)).same_string (string)
|
||||
not has_error implies (create {HTTP_MEDIA_TYPE}.make_from_string (string)).same_string (string)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
@@ -149,7 +140,7 @@ feature -- Access
|
||||
end
|
||||
end
|
||||
|
||||
parameters: detachable HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
parameters: detachable HTTP_PARAMETER_TABLE
|
||||
-- Parameters
|
||||
|
||||
feature -- Conversion
|
||||
@@ -262,7 +253,7 @@ feature -- Element change
|
||||
-- Remove parameter named `a_name'
|
||||
do
|
||||
if attached parameters as plst then
|
||||
plst.prune (a_name)
|
||||
plst.remove (a_name)
|
||||
if plst.is_empty then
|
||||
parameters := Void
|
||||
end
|
||||
@@ -270,84 +261,6 @@ feature -- Element change
|
||||
internal_string := Void
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
add_parameter_from_string (s: READABLE_STRING_8; start_index: INTEGER; out_end_index: CELL [INTEGER])
|
||||
-- Add parameter from string " attribute=value "
|
||||
-- and put in `out_end_index' the index after found parameter.
|
||||
local
|
||||
n: INTEGER
|
||||
pn,pv: STRING_8
|
||||
i: INTEGER
|
||||
p, q: INTEGER
|
||||
err: BOOLEAN
|
||||
do
|
||||
n := s.count
|
||||
-- Skip spaces
|
||||
from
|
||||
i := start_index
|
||||
until
|
||||
i > n or not s[i].is_space
|
||||
loop
|
||||
i := i + 1
|
||||
end
|
||||
if s[i] = ';' then
|
||||
-- empty parameter
|
||||
out_end_index.replace (i + 1)
|
||||
elseif i < n then
|
||||
p := s.index_of ('=', i)
|
||||
if p > 0 then
|
||||
pn := s.substring (i, p - 1)
|
||||
if p >= n then
|
||||
pv := ""
|
||||
out_end_index.replace (n + 1)
|
||||
else
|
||||
if s[p+1] = '%"' then
|
||||
q := s.index_of ('%"', p + 2)
|
||||
if q > 0 then
|
||||
pv := s.substring (p + 2, q - 1)
|
||||
from
|
||||
i := q + 1
|
||||
until
|
||||
i > n or not s[i].is_space
|
||||
loop
|
||||
i := i + 1
|
||||
end
|
||||
if s[i] = ';' then
|
||||
i := i + 1
|
||||
end
|
||||
out_end_index.replace (i)
|
||||
else
|
||||
err := True
|
||||
pv := ""
|
||||
-- missing closing double quote.
|
||||
end
|
||||
else
|
||||
q := s.index_of (';', p + 1)
|
||||
if q = 0 then
|
||||
q := n + 1
|
||||
end
|
||||
pv := s.substring (p + 1, q - 1)
|
||||
out_end_index.replace (q + 1)
|
||||
end
|
||||
pv.right_adjust
|
||||
if not err then
|
||||
add_parameter (pn, pv)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- expecting: attribute "=" value
|
||||
err := True
|
||||
end
|
||||
end
|
||||
if err then
|
||||
out_end_index.replace (n + 1)
|
||||
end
|
||||
has_error := has_error or err
|
||||
ensure
|
||||
entry_processed: out_end_index.item > start_index
|
||||
end
|
||||
|
||||
feature {NONE} -- Internal
|
||||
|
||||
internal_string: detachable STRING_8
|
||||
|
||||
150
library/network/protocol/http/src/http_parameter_table.e
Normal file
150
library/network/protocol/http/src/http_parameter_table.e
Normal file
@@ -0,0 +1,150 @@
|
||||
note
|
||||
description: "[
|
||||
Table representing parameters of the form q=1.0;note="blabla";foo=bar
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HTTP_PARAMETER_TABLE
|
||||
|
||||
inherit
|
||||
HASH_TABLE [READABLE_STRING_8, STRING_8]
|
||||
redefine
|
||||
empty_duplicate
|
||||
end
|
||||
|
||||
create
|
||||
make,
|
||||
make_from_string,
|
||||
make_from_substring
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_from_string (s: READABLE_STRING_8)
|
||||
-- Build table of parameters for `s'
|
||||
do
|
||||
make_from_substring (s, 1, s.count)
|
||||
end
|
||||
|
||||
make_from_substring (s: READABLE_STRING_8; a_start_index: INTEGER; a_end_index: INTEGER)
|
||||
-- Build table of parameters for `s.substring (a_start_index, a_end_index)'
|
||||
local
|
||||
cl: CELL [INTEGER]
|
||||
i: INTEGER
|
||||
do
|
||||
make (1)
|
||||
from
|
||||
i := a_start_index
|
||||
create cl.put (i)
|
||||
until
|
||||
i >= a_end_index
|
||||
loop
|
||||
force_substring (s, i, cl)
|
||||
i := cl.item
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_error: BOOLEAN
|
||||
-- Current has error?
|
||||
--| Mainly in relation with `make_from_string' and `force_substring'
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
force_substring (s: READABLE_STRING_8; start_index: INTEGER; out_end_index: CELL [INTEGER])
|
||||
-- Add parameter from string " attribute=value "
|
||||
-- and put in `out_end_index' the index after found parameter.
|
||||
local
|
||||
n: INTEGER
|
||||
pn,pv: STRING_8
|
||||
i: INTEGER
|
||||
p, q: INTEGER
|
||||
err: BOOLEAN
|
||||
do
|
||||
n := s.count
|
||||
-- Skip spaces
|
||||
from
|
||||
i := start_index
|
||||
until
|
||||
i > n or not s[i].is_space
|
||||
loop
|
||||
i := i + 1
|
||||
end
|
||||
if s[i] = ';' then
|
||||
-- empty parameter
|
||||
out_end_index.replace (i + 1)
|
||||
elseif i < n then
|
||||
p := s.index_of ('=', i)
|
||||
if p > 0 then
|
||||
pn := s.substring (i, p - 1)
|
||||
if p >= n then
|
||||
pv := ""
|
||||
out_end_index.replace (n + 1)
|
||||
else
|
||||
if s[p+1] = '%"' then
|
||||
q := s.index_of ('%"', p + 2)
|
||||
if q > 0 then
|
||||
pv := s.substring (p + 2, q - 1)
|
||||
from
|
||||
i := q + 1
|
||||
until
|
||||
i > n or not s[i].is_space
|
||||
loop
|
||||
i := i + 1
|
||||
end
|
||||
if s[i] = ';' then
|
||||
i := i + 1
|
||||
end
|
||||
out_end_index.replace (i)
|
||||
else
|
||||
err := True
|
||||
pv := ""
|
||||
-- missing closing double quote.
|
||||
end
|
||||
else
|
||||
q := s.index_of (';', p + 1)
|
||||
if q = 0 then
|
||||
q := n + 1
|
||||
end
|
||||
pv := s.substring (p + 1, q - 1)
|
||||
out_end_index.replace (q + 1)
|
||||
end
|
||||
pv.right_adjust
|
||||
if not err then
|
||||
force (pv, pn)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- expecting: attribute "=" value
|
||||
err := True
|
||||
end
|
||||
end
|
||||
if err then
|
||||
out_end_index.replace (n + 1)
|
||||
end
|
||||
has_error := has_error or err
|
||||
ensure
|
||||
entry_processed: out_end_index.item > start_index
|
||||
end
|
||||
|
||||
feature {NONE} -- Duplication
|
||||
|
||||
empty_duplicate (n: INTEGER): like Current
|
||||
-- Create an empty copy of Current that can accommodate `n' items
|
||||
do
|
||||
Result := Precursor (n)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
@@ -167,12 +167,12 @@ feature -- Content negotiation
|
||||
res_attached: res /= Void
|
||||
a_handler_attached: a_handler /= Void
|
||||
local
|
||||
l_conneg: CONNEG_SERVER_SIDE
|
||||
l_conneg: SERVER_CONTENT_NEGOTIATION
|
||||
h: HTTP_HEADER
|
||||
l_media: MEDIA_TYPE_VARIANT_RESULTS
|
||||
l_lang: LANGUAGE_VARIANT_RESULTS
|
||||
l_charset: CHARACTER_ENCODING_VARIANT_RESULTS
|
||||
l_encoding: COMPRESSION_VARIANT_RESULTS
|
||||
l_media: like {SERVER_CONTENT_NEGOTIATION}.media_type_preference
|
||||
l_lang: like {SERVER_CONTENT_NEGOTIATION}.language_preference
|
||||
l_charset: like {SERVER_CONTENT_NEGOTIATION}.charset_preference
|
||||
l_encoding: like {SERVER_CONTENT_NEGOTIATION}.encoding_preference
|
||||
l_mime_types, l_langs, l_charsets, l_encodings: LIST [STRING]
|
||||
l_vary_star: BOOLEAN
|
||||
do
|
||||
@@ -188,7 +188,7 @@ feature -- Content negotiation
|
||||
l_conneg := a_handler.conneg (req)
|
||||
l_mime_types := a_handler.mime_types_supported (req)
|
||||
l_media := l_conneg.media_type_preference (l_mime_types, req.http_accept)
|
||||
if not l_vary_star and l_mime_types.count > 1 and attached l_media.variant_header as l_media_variant then
|
||||
if not l_vary_star and l_mime_types.count > 1 and attached l_media.media_type as l_media_variant then
|
||||
h.add_header_key_value ({HTTP_HEADER_NAMES}.header_vary, l_media_variant)
|
||||
end
|
||||
if not l_media.is_acceptable then
|
||||
@@ -196,26 +196,26 @@ feature -- Content negotiation
|
||||
else
|
||||
l_langs := a_handler.languages_supported (req)
|
||||
l_lang := l_conneg.language_preference (l_langs, req.http_accept_language)
|
||||
if not l_vary_star and l_langs.count > 1 and attached l_lang.variant_header as l_lang_variant then
|
||||
if not l_vary_star and l_langs.count > 1 and attached l_lang.language as l_lang_variant then
|
||||
h.add_header_key_value ({HTTP_HEADER_NAMES}.header_vary, l_lang_variant)
|
||||
end
|
||||
if not l_lang.is_acceptable then
|
||||
handle_not_acceptable ("None of the requested languages were acceptable", l_langs, req, res)
|
||||
else
|
||||
if attached l_lang.type as l_language_type then
|
||||
if attached l_lang.language as l_language_type then
|
||||
h.put_content_language (l_language_type)
|
||||
req.set_execution_variable (a_handler.Negotiated_language_execution_variable, l_language_type)
|
||||
end
|
||||
l_charsets := a_handler.charsets_supported (req)
|
||||
l_charset := l_conneg.charset_preference (l_charsets, req.http_accept_charset)
|
||||
if not l_vary_star and l_charsets.count > 1 and attached l_charset.variant_header as l_charset_variant then
|
||||
if not l_vary_star and l_charsets.count > 1 and attached l_charset.charset as l_charset_variant then
|
||||
h.add_header_key_value ({HTTP_HEADER_NAMES}.header_vary, l_charset_variant)
|
||||
end
|
||||
if not l_charset.is_acceptable then
|
||||
handle_not_acceptable ("None of the requested character encodings were acceptable", l_charsets, req, res)
|
||||
else
|
||||
if attached l_media.type as l_media_type then
|
||||
if attached l_charset.type as l_character_type then
|
||||
if attached l_media.media_type as l_media_type then
|
||||
if attached l_charset.charset as l_character_type then
|
||||
h.put_content_type (l_media_type + "; charset=" + l_character_type)
|
||||
req.set_execution_variable (a_handler.Negotiated_charset_execution_variable, l_charset)
|
||||
else
|
||||
@@ -225,13 +225,13 @@ feature -- Content negotiation
|
||||
end
|
||||
l_encodings := a_handler.encodings_supported (req)
|
||||
l_encoding := l_conneg.encoding_preference (l_encodings, req.http_accept_encoding)
|
||||
if not l_vary_star and l_encodings.count > 1 and attached l_encoding.variant_header as l_encoding_variant then
|
||||
if not l_vary_star and l_encodings.count > 1 and attached l_encoding.encoding as l_encoding_variant then
|
||||
h.add_header_key_value ({HTTP_HEADER_NAMES}.header_vary, l_encoding_variant)
|
||||
end
|
||||
if not l_encoding.is_acceptable then
|
||||
handle_not_acceptable ("None of the requested transfer encodings were acceptable", l_encodings, req, res)
|
||||
else
|
||||
if attached l_encoding.type as l_compression_type then
|
||||
if attached l_encoding.encoding as l_compression_type then
|
||||
h.put_content_encoding (l_compression_type)
|
||||
req.set_execution_variable (a_handler.Negotiated_encoding_execution_variable, l_compression_type)
|
||||
end
|
||||
|
||||
@@ -89,7 +89,7 @@ feature -- Access
|
||||
deferred
|
||||
end
|
||||
|
||||
conneg (req: WSF_REQUEST): CONNEG_SERVER_SIDE
|
||||
conneg (req: WSF_REQUEST): SERVER_CONTENT_NEGOTIATION
|
||||
-- Content negotiation for `req';
|
||||
-- This would normally be a once object, ignoring `req'.
|
||||
require
|
||||
@@ -103,7 +103,7 @@ feature -- Access
|
||||
req_attached: req /= Void
|
||||
deferred
|
||||
ensure
|
||||
mime_types_supported_includes_default: Result.has (conneg (req).mime_default)
|
||||
mime_types_supported_includes_default: Result.has (conneg (req).default_media_type)
|
||||
end
|
||||
|
||||
languages_supported (req: WSF_REQUEST): LIST [STRING]
|
||||
@@ -112,7 +112,7 @@ feature -- Access
|
||||
req_attached: req /= Void
|
||||
deferred
|
||||
ensure
|
||||
languages_supported_includes_default: Result.has (conneg (req).language_default)
|
||||
languages_supported_includes_default: Result.has (conneg (req).default_language)
|
||||
end
|
||||
|
||||
charsets_supported (req: WSF_REQUEST): LIST [STRING]
|
||||
@@ -121,7 +121,7 @@ feature -- Access
|
||||
req_attached: req /= Void
|
||||
deferred
|
||||
ensure
|
||||
charsets_supported_includes_default: Result.has (conneg (req).charset_default)
|
||||
charsets_supported_includes_default: Result.has (conneg (req).default_charset)
|
||||
end
|
||||
|
||||
encodings_supported (req: WSF_REQUEST): LIST [STRING]
|
||||
@@ -130,7 +130,7 @@ feature -- Access
|
||||
req_attached: req /= Void
|
||||
deferred
|
||||
ensure
|
||||
encodings_supported_includes_default: Result.has (conneg (req).encoding_default)
|
||||
encodings_supported_includes_default: Result.has (conneg (req).default_encoding)
|
||||
end
|
||||
|
||||
additional_variant_headers (req: WSF_REQUEST): detachable LIST [STRING]
|
||||
|
||||
Reference in New Issue
Block a user