diff --git a/library/network/protocol/content_negotiation/README.md b/library/network/protocol/content_negotiation/README.md
index d86bcedb..09a53547 100644
--- a/library/network/protocol/content_negotiation/README.md
+++ b/library/network/protocol/content_negotiation/README.md
@@ -1,7 +1,6 @@
-CONNEG is a library that provides utilities to select the best repesentation of a resource for a client
-where there are multiple representations available.
+CONNEG is a library that provides utilities to select the best repesentation of a resource for a client where there are multiple representations available.
-Using this labrary you can retrieve the best Variant for media type, language preference, enconding and compression.
+Using this library you can retrieve the best variant for media type, language preference, enconding and compression.
The library is based on eMIME Eiffel MIME library based on Joe Gregorio code
Take into account that the library is under development so is expected that the API change.
@@ -9,7 +8,7 @@ Take into account that the library is under development so is expected that the
The library contains utilities that deal with content negotiation (server driven negotiation).This utility class
is based on ideas taken from the Book Restful WebServices Cookbook
-The class CONNEG_SERVER_SIDE contains several features that helps to write different type of negotiations (media type, language,
+The class CONNEG_SERVER_SIDE contains several features that helps to write different types of negotiation (media type, language,
charset and compression).
So for each of the following questions, you will have a corresponding method to help in the solution.
diff --git a/library/network/protocol/content_negotiation/conneg-safe.ecf b/library/network/protocol/content_negotiation/conneg-safe.ecf
index 06a7bda6..2bb7d7b2 100644
--- a/library/network/protocol/content_negotiation/conneg-safe.ecf
+++ b/library/network/protocol/content_negotiation/conneg-safe.ecf
@@ -13,6 +13,12 @@
-
+
+
+ /implementation
+
+
+
+
diff --git a/library/network/protocol/content_negotiation/conneg.ecf b/library/network/protocol/content_negotiation/conneg.ecf
index a4db8e63..6677144a 100644
--- a/library/network/protocol/content_negotiation/conneg.ecf
+++ b/library/network/protocol/content_negotiation/conneg.ecf
@@ -13,6 +13,12 @@
-
+
+
+ /implementation
+
+
+
+
diff --git a/library/network/protocol/content_negotiation/src/conneg_server_side.e b/library/network/protocol/content_negotiation/src/conneg_server_side.e
index 7440a799..37e4dbdc 100644
--- a/library/network/protocol/content_negotiation/src/conneg_server_side.e
+++ b/library/network/protocol/content_negotiation/src/conneg_server_side.e
@@ -17,81 +17,96 @@ class
CONNEG_SERVER_SIDE
inherit
-
- SHARED_CONNEG
-
REFACTORING_HELPER
create
make
-feature -- Initialization
+feature {NONE} -- Initialization
- make (a_mime: READABLE_STRING_8; a_language: READABLE_STRING_8; a_charset: READABLE_STRING_8; a_encoding: READABLE_STRING_8)
+ 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
- set_mime_default (a_mime)
- set_language_default (a_language)
- set_charset_default (a_charset)
- set_encoding_default (a_encoding)
+ 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
- mime_default_set: mime_default = a_mime
- language_default_set: language_default = a_language
- charset_default_set: charset_default = a_charset
- encoding_default_set: encoding_default = a_encoding
+ 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
-feature -- AccessServer Side Defaults Formats
+ initialize
+ -- Initialize Current
+ do
+ create accept_media_type_parser
+ create any_header_parser
+ create accept_language_parser
+ end
- mime_default: READABLE_STRING_8
+ 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.
- language_default: READABLE_STRING_8
+ default_language: READABLE_STRING_8
-- Natural language that is preferred as a response to the request.
- charset_default: READABLE_STRING_8
+ default_charset: READABLE_STRING_8
-- Character set that is acceptable for the response.
- encoding_default: READABLE_STRING_8
+ default_encoding: READABLE_STRING_8
-- Content-coding that is acceptable in the response.
feature -- Change Element
- set_mime_default (a_mime: READABLE_STRING_8)
- -- Set the mime_default with `a_mime'
+ set_default_media_type (a_mediatype: READABLE_STRING_8)
+ -- Set `default_media_type' with `a_mediatype'
do
- mime_default := a_mime
+ default_media_type := a_mediatype
ensure
- mime_default_set: a_mime = mime_default
+ default_media_type_set: a_mediatype = default_media_type
end
- set_language_default (a_language: READABLE_STRING_8)
- -- Set the language_default with `a_language'
+ set_default_language (a_language: READABLE_STRING_8)
+ -- Set `default_language' with `a_language'
do
- language_default := a_language
+ default_language := a_language
ensure
- language_default_set: a_language = language_default
+ default_language_set: a_language = default_language
end
- set_charset_default (a_charset: READABLE_STRING_8)
- -- Set the charset_default with `a_charset'
+ set_default_charset (a_charset: READABLE_STRING_8)
+ -- Set `default_charset' with `a_charset'
do
- charset_default := a_charset
+ default_charset := a_charset
ensure
- charset_default_set: a_charset = charset_default
+ default_charset_set: a_charset = default_charset
end
- set_encoding_default (a_encoding: READABLE_STRING_8)
+ set_default_encoding (a_encoding: READABLE_STRING_8)
+ -- Set `default_encoding' with `a_encoding'
do
- encoding_default := a_encoding
+ default_encoding := a_encoding
ensure
- encoding_default_set: a_encoding = encoding_default
+ 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): MEDIA_TYPE_VARIANT_RESULTS
+ 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
@@ -101,30 +116,31 @@ feature -- Media Type Negotiation
local
l_mime_match: READABLE_STRING_8
do
- create Result
+ 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_type (mime_default)
+ 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 := mime.best_match (a_mime_types_supported, a_header)
+ 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)
- Result.set_supported_variants (a_mime_types_supported)
else
-- Set the best match
- Result.set_type (l_mime_match)
+ Result.set_variant_value (l_mime_match)
Result.set_acceptable (True)
- Result.set_variant_header
end
end
end
feature -- Encoding Negotiation
- charset_preference (a_server_charset_supported: LIST [READABLE_STRING_8]; a_header: detachable READABLE_STRING_8): CHARACTER_ENCODING_VARIANT_RESULTS
+ 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
@@ -134,32 +150,33 @@ feature -- Encoding Negotiation
local
l_charset_match: READABLE_STRING_8
do
- create Result
+ 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_type (charset_default)
+ 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 := common.best_match (a_server_charset_supported, a_header)
+ 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)
- Result.set_supported_variants (a_server_charset_supported)
else
-- Set the best match
- Result.set_type (l_charset_match)
+ Result.set_variant_value (l_charset_match)
Result.set_acceptable (True)
- Result.set_variant_header
end
end
end
feature -- Compression Negotiation
- encoding_preference (a_server_encoding_supported: LIST [READABLE_STRING_8]; a_header: detachable READABLE_STRING_8): COMPRESSION_VARIANT_RESULTS
+ 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' represent the Accept-Encoding header, ie, the client preferences.
+ -- `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
@@ -167,32 +184,33 @@ feature -- Compression Negotiation
local
l_compression_match: READABLE_STRING_8
do
- create Result
- if a_header = Void or else a_header.is_empty then
+ 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_type (encoding_default)
+ 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 := common.best_match (a_server_encoding_supported, a_header)
+ 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)
- Result.set_supported_variants (a_server_encoding_supported)
else
-- Set the best match
- Result.set_type (l_compression_match)
+ Result.set_variant_value (l_compression_match)
Result.set_acceptable (True)
- Result.set_variant_header
end
end
end
feature -- Language Negotiation
- language_preference (a_server_language_supported: LIST [READABLE_STRING_8]; a_header: detachable READABLE_STRING_8): LANGUAGE_VARIANT_RESULTS
+ 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' represent the Accept-Language header, ie, the client preferences.
+ -- `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
@@ -201,28 +219,29 @@ feature -- Language Negotiation
local
l_language_match: READABLE_STRING_8
do
- create Result
- if a_header = Void or else a_header.is_empty then
+ 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_type (language_default)
+ 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 := language.best_match (a_server_language_supported, a_header)
+ 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)
- Result.set_supported_variants (a_server_language_supported)
else
-- Set the best match
- Result.set_type (l_language_match)
+ Result.set_variant_value (l_language_match)
Result.set_acceptable (True)
- Result.set_variant_header
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)"
diff --git a/library/network/protocol/content_negotiation/src/parsers/fitness_and_quality.e b/library/network/protocol/content_negotiation/src/implementation/fitness_and_quality.e
similarity index 75%
rename from library/network/protocol/content_negotiation/src/parsers/fitness_and_quality.e
rename to library/network/protocol/content_negotiation/src/implementation/fitness_and_quality.e
index a851ecde..0b7ab39f 100644
--- a/library/network/protocol/content_negotiation/src/parsers/fitness_and_quality.e
+++ b/library/network/protocol/content_negotiation/src/implementation/fitness_and_quality.e
@@ -1,6 +1,5 @@
note
description: "Summary description for {FITNESS_AND_QUALITY}."
- author: ""
date: "$Date$"
revision: "$Revision$"
@@ -24,7 +23,7 @@ feature -- Initialization
do
fitness := a_fitness
quality := a_quality
- create mime_type.make_empty
+ create {STRING_8} entity.make_empty
ensure
fitness_assigned : fitness = a_fitness
quality_assigned : quality = a_quality
@@ -36,17 +35,17 @@ feature -- Access
quality: REAL_64
- mime_type: STRING
+ entity: READABLE_STRING_8
-- optionally used
-- empty by default
-
+ --| Could be a mime type, an encoding, ...
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
- create Result.make_from_string (mime_type)
+ create Result.make_from_string (entity)
Result.append (" (")
Result.append ("quality=" + quality.out)
Result.append (" ; fitness=" + fitness.out)
@@ -55,12 +54,12 @@ feature -- Status report
feature -- Element Change
- set_mime_type (a_mime_type: STRING)
- -- set mime_type with `a_mime_type'
+ set_entity (a_entity: READABLE_STRING_8)
+ -- set `entity' with `a_entity'
do
- mime_type := a_mime_type
+ entity := a_entity
ensure
- mime_type_assigned : mime_type.same_string (a_mime_type)
+ entity_assigned : entity.same_string (a_entity)
end
feature -- Comparision
@@ -75,7 +74,7 @@ feature -- Comparision
end
end
note
- copyright: "2011-2011, Javier Velilla, Jocelyn Fiat and others"
+ 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
diff --git a/library/network/protocol/content_negotiation/src/parsers/http_accept_language_parser.e b/library/network/protocol/content_negotiation/src/parsers/http_accept_language_parser.e
new file mode 100644
index 00000000..4f7b08d2
--- /dev/null
+++ b/library/network/protocol/content_negotiation/src/parsers/http_accept_language_parser.e
@@ -0,0 +1,269 @@
+note
+ description: "[
+ {HTTP_ACCEPT_LANGUAGE_PARSER} is encharge to parse language tags defined as follow:
+
+ Accept-Language = "Accept-Language" ":"
+ 1#( language-l_range [ ";" "q" "=" qvalue ] )
+ language-l_range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
+
+ Example:
+ Accept-Language: da, en-gb;q=0.8, en;q=0.7
+
+ ]"
+ date: "$Date$"
+ revision: "$Revision$"
+ EIS: "name=Accept-Language", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4", "protocol=uri"
+
+class
+ HTTP_ACCEPT_LANGUAGE_PARSER
+
+inherit
+
+ HTTP_HEADER_PARSER
+
+ REFACTORING_HELPER
+
+feature -- Parser
+
+ accept_language_list (a_header_value: READABLE_STRING_8): LIST [HTTP_ACCEPT_LANGUAGE]
+ -- Languages-ranges are languages with wild-cards and a 'q' quality parameter.
+ -- For example, the language l_range ('en-* ;q=0.5') would get parsed into:
+ -- ('en', '*', {'q', '0.5'})
+ -- In addition this function also guarantees that there is a value for 'q'
+ -- in the params dictionary, filling it in with a proper default if
+ -- necessary.
+ local
+ l_res: LIST [READABLE_STRING_8]
+ l_lang: HTTP_ACCEPT_LANGUAGE
+ do
+ l_res := a_header_value.split (',')
+ create {ARRAYED_LIST [HTTP_ACCEPT_LANGUAGE]} Result.make (l_res.count)
+
+ from
+ l_res.start
+ until
+ l_res.after
+ loop
+ create l_lang.make_from_string (l_res.item_for_iteration)
+ Result.force (l_lang)
+ l_res.forth
+ end
+ end
+
+ accept_language (a_accept_language_item: READABLE_STRING_8): HTTP_ACCEPT_LANGUAGE
+ -- Languages-ranges are languages with wild-cards and a 'q' quality parameter.
+ -- For example, the language l_range ('en-* ;q=0.5') would get parsed into:
+ -- ('en', '*', {'q', '0.5'})
+ -- In addition this function also guarantees that there is a value for 'q'
+ -- in the params dictionary, filling it in with a proper default if
+ -- necessary.
+ do
+ create Result.make_from_string (a_accept_language_item)
+ end
+
+ quality (a_language: READABLE_STRING_8; a_ranges: READABLE_STRING_8): REAL_64
+ -- Returns the quality 'q' of a `a_language' when compared against the
+ -- language l_range in `a_ranges'.
+ do
+ 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
+ -- 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))
+ l_weighted_matches.force (l_fitness_and_quality)
+ a_supported.forth
+ end
+
+ --| Keep only top quality+fitness types
+ from
+ l_weighted_matches.start
+ l_first_one := l_weighted_matches.item
+ l_weighted_matches.forth
+ until
+ l_weighted_matches.after
+ loop
+ l_fitness_and_quality := l_weighted_matches.item
+ if l_first_one < l_fitness_and_quality then
+ l_first_one := l_fitness_and_quality
+ if not l_weighted_matches.isfirst then
+ from
+ l_weighted_matches.back
+ until
+ l_weighted_matches.before
+ loop
+ l_weighted_matches.remove
+ l_weighted_matches.back
+ end
+ l_weighted_matches.forth
+ end
+ check
+ l_weighted_matches.item = l_fitness_and_quality
+ end
+ l_weighted_matches.forth
+ elseif l_first_one ~ l_fitness_and_quality then
+ l_weighted_matches.forth
+ else
+ check
+ l_first_one > l_fitness_and_quality
+ end
+ l_weighted_matches.remove
+ end
+ end
+ if l_first_one /= Void and then l_first_one.quality /= 0.0 then
+ if l_weighted_matches.count = 1 then
+ Result := l_first_one.entity
+ else
+ from
+ l_fitness_and_quality := Void
+ l_header_results.start
+ until
+ l_header_results.after or l_fitness_and_quality /= Void
+ loop
+ s := l_header_results.item.language_range
+ from
+ l_weighted_matches.start
+ until
+ l_weighted_matches.after or l_fitness_and_quality /= Void
+ loop
+ l_fitness_and_quality := l_weighted_matches.item
+ if l_fitness_and_quality.entity.same_string (s) then
+ --| Found
+ else
+ l_fitness_and_quality := Void
+ l_weighted_matches.forth
+ end
+ end
+ l_header_results.forth
+ end
+ if l_fitness_and_quality /= Void then
+ Result := l_fitness_and_quality.entity
+ else
+ Result := l_first_one.entity
+ end
+ end
+ else
+ Result := ""
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ fitness_and_quality_from_list (a_language: READABLE_STRING_8; a_parsed_ranges: LIST [HTTP_ACCEPT_LANGUAGE]): FITNESS_AND_QUALITY
+ -- Find the best match for a given `a_language' against a list of language ranges `a_parsed_ranges'
+ -- that have already been parsed by parse_language_range.
+ local
+ l_best_fitness: INTEGER
+ l_target_q: REAL_64
+ l_best_fit_q: REAL_64
+ 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
+ do
+ l_best_fitness := -1
+ l_best_fit_q := 0.0
+ create l_target.make_from_string (a_language)
+ l_target_q := l_target.quality
+
+ l_target_type := l_target.language
+ from
+ a_parsed_ranges.start
+ until
+ a_parsed_ranges.after
+ loop
+ l_range := a_parsed_ranges.item_for_iteration
+ if
+ attached l_range.language as l_range_type and then
+ ( l_target_type.same_string (l_range_type)
+ or l_range_type.same_string ("*")
+ 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
+ end
+ l_keys.forth
+ end
+ if l_range_type.same_string (l_target_type) then
+ l_fitness := 100
+ else
+ l_fitness := 0
+ end
+ if
+ attached l_range.specialization as l_range_sub_type and then
+ attached l_target.specialization as l_target_sub_type and then
+ ( l_target_sub_type.same_string (l_range_sub_type)
+ or l_range_sub_type.same_string ("*")
+ or l_target_sub_type.same_string ("*")
+ )
+ then
+ if l_range_sub_type.same_string (l_target_sub_type) then
+ l_fitness := l_fitness + 10
+ end
+ end
+ 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")
+ if l_element /= Void then
+ l_best_fit_q := l_element.to_real_64.min (l_target_q)
+ else
+ l_best_fit_q := 0.0
+ end
+ end
+ end
+ a_parsed_ranges.forth
+ end
+ create Result.make (l_best_fitness, l_best_fit_q)
+ end
+
+ quality_from_list (a_language: READABLE_STRING_8; a_parsed_ranges: LIST [HTTP_ACCEPT_LANGUAGE]): REAL_64
+ -- Find the best match for a given `a_language' against a list of ranges `parsed_ranges' that
+ -- have already been parsed by parse_language_range. Returns the 'q' quality
+ -- parameter of the best match, 0 if no match was found. This function
+ -- bahaves the same as quality except that 'a_parsed_ranges' must be a list
+ -- of parsed language ranges.
+ do
+ Result := fitness_and_quality_from_list (a_language, a_parsed_ranges).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)"
+
+end
diff --git a/library/network/protocol/content_negotiation/src/parsers/mime_parse.e b/library/network/protocol/content_negotiation/src/parsers/http_accept_media_type_parser.e
similarity index 83%
rename from library/network/protocol/content_negotiation/src/parsers/mime_parse.e
rename to library/network/protocol/content_negotiation/src/parsers/http_accept_media_type_parser.e
index 8be798a8..b29369be 100644
--- a/library/network/protocol/content_negotiation/src/parsers/mime_parse.e
+++ b/library/network/protocol/content_negotiation/src/parsers/http_accept_media_type_parser.e
@@ -1,6 +1,6 @@
note
description: "[
- {MIME_PARSE}. is encharge to parse Accept request-header field defined as follow:
+ {HTTP_ACCEPT_MEDIA_TYPE_PARSER}. is encharge to parse Accept request-header field defined as follow:
Accept = "Accept" ":"
#( media-range [ accept-params ] )
@@ -20,26 +20,17 @@
EIS: "name=Accept", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1", "protocol=uri"
class
- MIME_PARSE
+ HTTP_ACCEPT_MEDIA_TYPE_PARSER
-inherit {NONE}
+inherit
- MIME_TYPE_PARSER_UTILITIES
+ HTTP_HEADER_PARSER
REFACTORING_HELPER
feature -- Parser
- parse_mime_type (a_mime_type: READABLE_STRING_8): HTTP_MEDIA_TYPE
- -- Parses a mime-type into its component parts.
- -- For example, the media range 'application/xhtml;q=0.5' would get parsed
- -- into:
- -- ('application', 'xhtml', {'q', '0.5'})
- do
- create Result.make_from_string (a_mime_type)
- end
-
- parse_media_range (a_range: READABLE_STRING_8): HTTP_MEDIA_TYPE
+ media_type (a_range: READABLE_STRING_8): HTTP_MEDIA_TYPE
-- Media-ranges are mime-types with wild-cards and a 'q' quality parameter.
-- For example, the media range 'application/*;q=0.5' would get parsed into:
-- ('application', '*', {'q', '0.5'})
@@ -48,11 +39,11 @@ feature -- Parser
-- necessary.
do
fixme ("Improve the code!!!")
- Result := parse_mime_type (a_range)
+ create Result.make_from_string (a_range)
if attached Result.parameter ("q") as q then
if
q.is_double and then
- attached {REAL_64} q.to_double as r and then
+ attached {REAL_64} q.to_real_64 as r and then
(r >= 0.0 and r <= 1.0)
then
--| Keep current value
@@ -68,8 +59,136 @@ feature -- Parser
end
end
+ quality (a_mime_type: READABLE_STRING_8; ranges: READABLE_STRING_8): REAL_64
+ -- Returns the quality 'q' of a mime-type when compared against the
+ -- mediaRanges in ranges.
+ local
+ l_ranges : LIST [READABLE_STRING_8]
+ res : ARRAYED_LIST [HTTP_MEDIA_TYPE]
+ p_res : HTTP_MEDIA_TYPE
+ do
+ l_ranges := ranges.split (',')
+ from
+ create res.make (10);
+ l_ranges.start
+ until
+ l_ranges.after
+ loop
+ p_res := media_type (l_ranges.item_for_iteration)
+ res.force (p_res)
+ l_ranges.forth
+ end
+ Result := quality_from_list (a_mime_type, res)
+ end
- fitness_and_quality_parsed (a_mime_type: READABLE_STRING_8; parsed_ranges: LIST [HTTP_MEDIA_TYPE]): FITNESS_AND_QUALITY
+ best_match (supported: LIST [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]
+ weighted_matches: LIST [FITNESS_AND_QUALITY]
+ l_res: LIST [READABLE_STRING_8]
+ p_res: HTTP_MEDIA_TYPE
+ fitness_and_quality, first_one: detachable FITNESS_AND_QUALITY
+ s: READABLE_STRING_8
+ do
+ l_res := header.split (',')
+ create {ARRAYED_LIST [HTTP_MEDIA_TYPE]} l_header_results.make (l_res.count)
+
+ fixme("Extract method!!!")
+ from
+ l_res.start
+ until
+ l_res.after
+ loop
+ p_res := media_type (l_res.item_for_iteration)
+ l_header_results.force (p_res)
+ l_res.forth
+ end
+
+ create {ARRAYED_LIST [FITNESS_AND_QUALITY]} weighted_matches.make (supported.count)
+
+ 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))
+ weighted_matches.force (fitness_and_quality)
+ supported.forth
+ end
+
+ --| Keep only top quality+fitness types
+ from
+ weighted_matches.start
+ first_one := weighted_matches.item
+ weighted_matches.forth
+ until
+ weighted_matches.after
+ loop
+ fitness_and_quality := weighted_matches.item
+ if first_one < fitness_and_quality then
+ first_one := fitness_and_quality
+ if not weighted_matches.isfirst then
+ from
+ weighted_matches.back
+ until
+ weighted_matches.before
+ loop
+ weighted_matches.remove
+ weighted_matches.back
+ end
+ weighted_matches.forth
+ end
+ check weighted_matches.item = fitness_and_quality end
+ weighted_matches.forth
+ elseif first_one.is_equal (fitness_and_quality) then
+ weighted_matches.forth
+ else
+ check first_one > fitness_and_quality end
+ weighted_matches.remove
+ end
+ end
+ if first_one /= Void and then first_one.quality /= 0.0 then
+ if weighted_matches.count = 1 then
+ Result := first_one.entity
+ else
+ from
+ fitness_and_quality := Void
+ l_header_results.start
+ until
+ l_header_results.after or fitness_and_quality /= Void
+ loop
+ s := l_header_results.item.simple_type
+ from
+ weighted_matches.start
+ until
+ weighted_matches.after or fitness_and_quality /= Void
+ loop
+ fitness_and_quality := weighted_matches.item
+ if fitness_and_quality.entity.same_string (s) then
+ --| Found
+ else
+ fitness_and_quality := Void
+ weighted_matches.forth
+ end
+ end
+ l_header_results.forth
+ end
+ if fitness_and_quality /= Void then
+ Result := fitness_and_quality.entity
+ else
+ Result := first_one.entity
+ end
+ end
+ else
+ Result := ""
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ fitness_and_quality_from_list (a_mime_type: READABLE_STRING_8; parsed_ranges: LIST [HTTP_MEDIA_TYPE]): FITNESS_AND_QUALITY
-- Find the best match for a given mimeType against a list of media_ranges
-- that have already been parsed by parse_media_range.
local
@@ -84,7 +203,7 @@ feature -- Parser
do
best_fitness := -1
best_fit_q := 0.0
- target := parse_media_range (a_mime_type)
+ target := media_type (a_mime_type)
if attached target.parameter ("q") as q and then q.is_double then
target_q := q.to_double
if target_q < 0.0 then
@@ -163,142 +282,16 @@ feature -- Parser
create Result.make (best_fitness, best_fit_q)
end
- quality_parsed (a_mime_type: READABLE_STRING_8; parsed_ranges: LIST [HTTP_MEDIA_TYPE]): REAL_64
+ quality_from_list (a_mime_type: READABLE_STRING_8; parsed_ranges: LIST [HTTP_MEDIA_TYPE]): REAL_64
-- Find the best match for a given mime-type against a list of ranges that
-- have already been parsed by parse_media_range. Returns the 'q' quality
-- parameter of the best match, 0 if no match was found. This function
-- bahaves the same as quality except that 'parsed_ranges' must be a list
-- of parsed media ranges.
do
- Result := fitness_and_quality_parsed (a_mime_type, parsed_ranges).quality
+ Result := fitness_and_quality_from_list (a_mime_type, parsed_ranges).quality
end
- quality (a_mime_type: READABLE_STRING_8; ranges: READABLE_STRING_8): REAL_64
- -- Returns the quality 'q' of a mime-type when compared against the
- -- mediaRanges in ranges.
- local
- l_ranges : LIST [READABLE_STRING_8]
- res : ARRAYED_LIST [HTTP_MEDIA_TYPE]
- p_res : HTTP_MEDIA_TYPE
- do
- l_ranges := ranges.split (',')
- from
- create res.make (10);
- l_ranges.start
- until
- l_ranges.after
- loop
- p_res := parse_media_range (l_ranges.item_for_iteration)
- res.force (p_res)
- l_ranges.forth
- end
- Result := quality_parsed (a_mime_type, res)
- end
-
- best_match (supported: LIST [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]
- weighted_matches: LIST [FITNESS_AND_QUALITY]
- l_res: LIST [READABLE_STRING_8]
- p_res: HTTP_MEDIA_TYPE
- fitness_and_quality, first_one: detachable FITNESS_AND_QUALITY
- s: READABLE_STRING_8
- do
- l_res := header.split (',')
- create {ARRAYED_LIST [HTTP_MEDIA_TYPE]} l_header_results.make (l_res.count)
-
- fixme("Extract method!!!")
- from
- l_res.start
- until
- l_res.after
- loop
- p_res := parse_media_range (l_res.item_for_iteration)
- l_header_results.force (p_res)
- l_res.forth
- end
-
- create {ARRAYED_LIST [FITNESS_AND_QUALITY]} weighted_matches.make (supported.count)
-
- from
- supported.start
- until
- supported.after
- loop
- fitness_and_quality := fitness_and_quality_parsed (supported.item_for_iteration, l_header_results)
- fitness_and_quality.set_mime_type (mime_type (supported.item_for_iteration))
- weighted_matches.force (fitness_and_quality)
- supported.forth
- end
-
- --| Keep only top quality+fitness types
- from
- weighted_matches.start
- first_one := weighted_matches.item
- weighted_matches.forth
- until
- weighted_matches.after
- loop
- fitness_and_quality := weighted_matches.item
- if first_one < fitness_and_quality then
- first_one := fitness_and_quality
- if not weighted_matches.isfirst then
- from
- weighted_matches.back
- until
- weighted_matches.before
- loop
- weighted_matches.remove
- weighted_matches.back
- end
- weighted_matches.forth
- end
- check weighted_matches.item = fitness_and_quality end
- weighted_matches.forth
- elseif first_one.is_equal (fitness_and_quality) then
- weighted_matches.forth
- else
- check first_one > fitness_and_quality end
- weighted_matches.remove
- end
- end
- if first_one /= Void and then first_one.quality /= 0.0 then
- if weighted_matches.count = 1 then
- Result := first_one.mime_type
- else
- from
- fitness_and_quality := Void
- l_header_results.start
- until
- l_header_results.after or fitness_and_quality /= Void
- loop
- s := l_header_results.item.simple_type
- from
- weighted_matches.start
- until
- weighted_matches.after or fitness_and_quality /= Void
- loop
- fitness_and_quality := weighted_matches.item
- if fitness_and_quality.mime_type.same_string (s) then
- --| Found
- else
- fitness_and_quality := Void
- weighted_matches.forth
- end
- end
- l_header_results.forth
- end
- if fitness_and_quality /= Void then
- Result := fitness_and_quality.mime_type
- else
- Result := first_one.mime_type
- end
- end
- else
- Result := ""
- end
- end
note
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
diff --git a/library/network/protocol/content_negotiation/src/parsers/common_accept_header_parser.e b/library/network/protocol/content_negotiation/src/parsers/http_any_accept_header_parser.e
similarity index 56%
rename from library/network/protocol/content_negotiation/src/parsers/common_accept_header_parser.e
rename to library/network/protocol/content_negotiation/src/parsers/http_any_accept_header_parser.e
index de3e8040..b0d4931f 100644
--- a/library/network/protocol/content_negotiation/src/parsers/common_accept_header_parser.e
+++ b/library/network/protocol/content_negotiation/src/parsers/http_any_accept_header_parser.e
@@ -1,6 +1,6 @@
note
description: "[
- COMMON_ACCEPT_HEADER_PARSER, this class allows to parse Accept-Charset and Accept-Encoding headers
+ HTTP_ANY_ACCEPT_HEADER_PARSER, this class allows to parse Accept-* headers
]"
date: "$Date$"
@@ -9,17 +9,15 @@ note
EIS: "name=Encoding", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3", "protocol=uri"
class
- COMMON_ACCEPT_HEADER_PARSER
-
-inherit {NONE}
-
- MIME_TYPE_PARSER_UTILITIES
+ HTTP_ANY_ACCEPT_HEADER_PARSER
+inherit
+ HTTP_HEADER_PARSER
feature -- Parser
- parse_common (header: READABLE_STRING_8): COMMON_RESULTS
- -- Parses `header' charset/encoding into its component parts.
+ header (a_header: READABLE_STRING_8): HTTP_ANY_ACCEPT_HEADER
+ -- 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'})
@@ -31,7 +29,7 @@ feature -- Parser
l_header: READABLE_STRING_8
do
create Result.make
- l_parts := header.split (';')
+ l_parts := a_header.split (';')
if l_parts.count = 1 then
Result.put ("1.0", "q")
else
@@ -40,7 +38,7 @@ feature -- Parser
until
i > l_parts.count
loop
- p := l_parts.at (i)
+ p := l_parts [i]
sub_parts := p.split ('=')
if sub_parts.count = 2 then
Result.put (trim (sub_parts [2]), trim (sub_parts [1]))
@@ -52,7 +50,141 @@ feature -- Parser
Result.set_field (trim (l_header))
end
- fitness_and_quality_parsed (a_field: READABLE_STRING_8; a_parsed_charsets: LIST [COMMON_RESULTS]): FITNESS_AND_QUALITY
+ quality (a_field: READABLE_STRING_8; a_commons: 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
+ do
+ l_commons := a_commons.split (',')
+ from
+ create res.make (10)
+ l_commons.start
+ until
+ l_commons.after
+ loop
+ p_res := header (l_commons.item_for_iteration)
+ res.force (p_res)
+ l_commons.forth
+ end
+ Result := quality_from_list (a_field, res)
+ end
+
+ best_match (a_supported: LIST [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_weighted_matches: LIST [FITNESS_AND_QUALITY]
+ l_res: LIST [READABLE_STRING_8]
+ p_res: HTTP_ANY_ACCEPT_HEADER
+ 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)
+ from
+ l_res.start
+ until
+ l_res.after
+ loop
+ p_res := header (l_res.item_for_iteration)
+ 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))
+ l_weighted_matches.force (l_fitness_and_quality)
+ a_supported.forth
+ end
+
+ --| Keep only top quality+fitness types
+ --| TODO extract method
+ from
+ l_weighted_matches.start
+ l_first_one := l_weighted_matches.item
+ l_weighted_matches.forth
+ until
+ l_weighted_matches.after
+ loop
+ l_fitness_and_quality := l_weighted_matches.item
+ if l_first_one < l_fitness_and_quality then
+ l_first_one := l_fitness_and_quality
+ if not l_weighted_matches.isfirst then
+ from
+ l_weighted_matches.back
+ until
+ l_weighted_matches.before
+ loop
+ l_weighted_matches.remove
+ l_weighted_matches.back
+ end
+ l_weighted_matches.forth
+ end
+ check
+ l_weighted_matches.item = l_fitness_and_quality
+ end
+ l_weighted_matches.forth
+ elseif l_first_one.is_equal (l_fitness_and_quality) then
+ l_weighted_matches.forth
+ else
+ check
+ l_first_one > l_fitness_and_quality
+ end
+ l_weighted_matches.remove
+ end
+ end
+ if l_first_one /= Void and then l_first_one.quality /= 0.0 then
+ if l_weighted_matches.count = 1 then
+ Result := l_first_one.entity
+ else
+ from
+ l_fitness_and_quality := Void
+ l_header_results.start
+ until
+ l_header_results.after or l_fitness_and_quality /= Void
+ loop
+ if attached l_header_results.item.field as l_field then
+ from
+ l_weighted_matches.start
+ until
+ l_weighted_matches.after or l_fitness_and_quality /= Void
+ loop
+ l_fitness_and_quality := l_weighted_matches.item
+ if l_fitness_and_quality.entity.same_string (l_field) then
+ --| Found
+ else
+ l_fitness_and_quality := Void
+ l_weighted_matches.forth
+ end
+ end
+ else
+ check
+ has_field: False
+ end
+ end
+ l_header_results.forth
+ end
+ if l_fitness_and_quality /= Void then
+ Result := l_fitness_and_quality.entity
+ else
+ Result := l_first_one.entity
+ end
+ end
+ else
+ Result := ""
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ fitness_and_quality_from_list (a_field: READABLE_STRING_8; a_parsed_charsets: LIST [HTTP_ANY_ACCEPT_HEADER]): 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
@@ -62,14 +194,14 @@ feature -- Parser
best_fitness: INTEGER
target_q: REAL_64
best_fit_q: REAL_64
- target: COMMON_RESULTS
- range: COMMON_RESULTS
+ target: HTTP_ANY_ACCEPT_HEADER
+ range: HTTP_ANY_ACCEPT_HEADER
element: detachable READABLE_STRING_8
l_fitness: INTEGER
do
best_fitness := -1
best_fit_q := 0.0
- target := parse_common (a_field)
+ target := header (a_field)
if attached target.item ("q") as q and then q.is_double then
target_q := q.to_double
if target_q < 0.0 then
@@ -111,146 +243,15 @@ feature -- Parser
create Result.make (best_fitness, best_fit_q)
end
- quality_parsed (a_field: READABLE_STRING_8; parsed_common: LIST [COMMON_RESULTS]): REAL_64
+ quality_from_list (a_field: READABLE_STRING_8; a_parsed_common: LIST [HTTP_ANY_ACCEPT_HEADER]): 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
-- bahaves the same as quality()
do
- Result := fitness_and_quality_parsed (a_field, parsed_common).quality
+ Result := fitness_and_quality_from_list (a_field, a_parsed_common).quality
end
- quality (a_field: READABLE_STRING_8; commons: 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 [COMMON_RESULTS]
- p_res: COMMON_RESULTS
- do
- l_commons := commons.split (',')
- from
- create res.make (10)
- l_commons.start
- until
- l_commons.after
- loop
- p_res := parse_common (l_commons.item_for_iteration)
- res.force (p_res)
- l_commons.forth
- end
- Result := quality_parsed (a_field, res)
- end
-
- best_match (supported: LIST [READABLE_STRING_8]; 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 [COMMON_RESULTS]
- weighted_matches: LIST [FITNESS_AND_QUALITY]
- l_res: LIST [READABLE_STRING_8]
- p_res: COMMON_RESULTS
- fitness_and_quality, first_one: detachable FITNESS_AND_QUALITY
- do
- l_res := header.split (',')
- create {ARRAYED_LIST [COMMON_RESULTS]} l_header_results.make (l_res.count)
- from
- l_res.start
- until
- l_res.after
- loop
- p_res := parse_common (l_res.item_for_iteration)
- l_header_results.force (p_res)
- l_res.forth
- end
- create {ARRAYED_LIST [FITNESS_AND_QUALITY]} weighted_matches.make (supported.count)
- from
- supported.start
- until
- supported.after
- loop
- fitness_and_quality := fitness_and_quality_parsed (supported.item_for_iteration, l_header_results)
- fitness_and_quality.set_mime_type (mime_type (supported.item_for_iteration))
- weighted_matches.force (fitness_and_quality)
- supported.forth
- end
-
- --| Keep only top quality+fitness types
- --| TODO extract method
- from
- weighted_matches.start
- first_one := weighted_matches.item
- weighted_matches.forth
- until
- weighted_matches.after
- loop
- fitness_and_quality := weighted_matches.item
- if first_one < fitness_and_quality then
- first_one := fitness_and_quality
- if not weighted_matches.isfirst then
- from
- weighted_matches.back
- until
- weighted_matches.before
- loop
- weighted_matches.remove
- weighted_matches.back
- end
- weighted_matches.forth
- end
- check
- weighted_matches.item = fitness_and_quality
- end
- weighted_matches.forth
- elseif first_one.is_equal (fitness_and_quality) then
- weighted_matches.forth
- else
- check
- first_one > fitness_and_quality
- end
- weighted_matches.remove
- end
- end
- if first_one /= Void and then first_one.quality /= 0.0 then
- if weighted_matches.count = 1 then
- Result := first_one.mime_type
- else
- from
- fitness_and_quality := Void
- l_header_results.start
- until
- l_header_results.after or fitness_and_quality /= Void
- loop
- if attached l_header_results.item.field as l_field then
- from
- weighted_matches.start
- until
- weighted_matches.after or fitness_and_quality /= Void
- loop
- fitness_and_quality := weighted_matches.item
- if fitness_and_quality.mime_type.same_string (l_field) then
- --| Found
- else
- fitness_and_quality := Void
- weighted_matches.forth
- end
- end
- else
- check
- has_field: False
- end
- end
- l_header_results.forth
- end
- if fitness_and_quality /= Void then
- Result := fitness_and_quality.mime_type
- else
- Result := first_one.mime_type
- end
- end
- else
- Result := ""
- end
- end
note
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
diff --git a/library/network/protocol/content_negotiation/src/parsers/mime_type_parser_utilities.e b/library/network/protocol/content_negotiation/src/parsers/http_header_parser.e
similarity index 58%
rename from library/network/protocol/content_negotiation/src/parsers/mime_type_parser_utilities.e
rename to library/network/protocol/content_negotiation/src/parsers/http_header_parser.e
index 7011a93b..0d08278e 100644
--- a/library/network/protocol/content_negotiation/src/parsers/mime_type_parser_utilities.e
+++ b/library/network/protocol/content_negotiation/src/parsers/http_header_parser.e
@@ -1,14 +1,15 @@
note
- description: "{MIME_TYPE_PARSER_UTILITIES}."
+ description: "Summary description for {HTTP_HEADER_PARSER}."
+ author: ""
date: "$Date$"
revision: "$Revision$"
-class
- MIME_TYPE_PARSER_UTILITIES
+deferred class
+ HTTP_HEADER_PARSER
-feature {NONE} -- Implementation
+feature {NONE} -- Helpers
- mime_type (a_str: READABLE_STRING_8): READABLE_STRING_8
+ entity_value (a_str: READABLE_STRING_8): READABLE_STRING_8
-- `s' with any trailing parameters stripped
local
p: INTEGER
@@ -21,20 +22,17 @@ feature {NONE} -- Implementation
end
end
- trim (a_string: READABLE_STRING_8): READABLE_STRING_8
+ trim (a_string: READABLE_STRING_8): STRING_8
-- trim whitespace from the beginning and end of a string
-- `a_string'
require
valid_argument : a_string /= Void
- local
- l_result: STRING
do
- l_result := a_string.as_string_8
- l_result.left_adjust
- l_result.right_adjust
- Result := l_result
+ create Result.make_from_string (a_string)
+ Result.left_adjust
+ Result.right_adjust
ensure
- result_same_as_argument: Result.same_string_general (a_string)
+ result_trimmed: a_string.has_substring (Result)
end
note
diff --git a/library/network/protocol/content_negotiation/src/parsers/language_parse.e b/library/network/protocol/content_negotiation/src/parsers/language_parse.e
deleted file mode 100644
index b5ef3584..00000000
--- a/library/network/protocol/content_negotiation/src/parsers/language_parse.e
+++ /dev/null
@@ -1,312 +0,0 @@
-note
- description: "[
- {LANGUAGE_PARSE} is encharge to parse language tags defined as follow:
-
- Accept-Language = "Accept-Language" ":"
- 1#( language-range [ ";" "q" "=" qvalue ] )
- language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
-
- Example:
- Accept-Language: da, en-gb;q=0.8, en;q=0.7
-
- ]"
- date: "$Date$"
- revision: "$Revision$"
- EIS: "name=Accept-Language", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4", "protocol=uri"
-
-class
- LANGUAGE_PARSE
-
-inherit {NONE}
-
- MIME_TYPE_PARSER_UTILITIES
-
- REFACTORING_HELPER
-
-feature -- Parser
-
- parse_language (a_accept_language: READABLE_STRING_8): LANGUAGE_RESULTS
- -- Parses `a_accept_language' request-header field into its component parts.
- -- For example, the language range 'en-gb;q=0.8' would get parsed
- -- into:
- -- ('en-gb', {'q':'0.8',})
- local
- l_parts: LIST [READABLE_STRING_8]
- p: READABLE_STRING_8
- sub_parts: LIST [READABLE_STRING_8]
- i: INTEGER
- l_full_type: READABLE_STRING_8
- l_types: LIST [READABLE_STRING_8]
- do
- fixme ("Improve code!!!")
- create Result.make
- l_parts := a_accept_language.split (';')
- from
- i := 1
- until
- i > l_parts.count
- loop
- p := l_parts.at (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
-
- l_full_type := trim (l_parts [1])
- if l_full_type.same_string ("*") then
- l_full_type := "*"
- end
- l_types := l_full_type.split ('-')
- if l_types.count = 1 then
- Result.set_type (trim (l_types [1]))
- else
- Result.set_type (trim (l_types [1]))
- Result.set_sub_type (trim (l_types [2]))
- end
- end
-
- parse_language_range (a_language_range: READABLE_STRING_8): LANGUAGE_RESULTS
- -- Languages-ranges are languages with wild-cards and a 'q' quality parameter.
- -- For example, the language range ('en-* ;q=0.5') would get parsed into:
- -- ('en', '*', {'q', '0.5'})
- -- In addition this function also guarantees that there is a value for 'q'
- -- in the params dictionary, filling it in with a proper default if
- -- necessary.
- do
- fixme ("Improve the code!!!")
- Result := parse_language (a_language_range)
- if attached Result.item ("q") as q then
- if q.is_double and then attached {REAL_64} q.to_double as r and then (r >= 0.0 and r <= 1.0) then
- --| Keep current value
- if q.same_string ("1") then
- --| Use 1.0 formatting
- Result.put ("1.0", "q")
- end
- else
- Result.put ("1.0", "q")
- end
- else
- Result.put ("1.0", "q")
- end
- end
-
- fitness_and_quality_parsed (a_language: READABLE_STRING_8; a_parsed_ranges: LIST [LANGUAGE_RESULTS]): FITNESS_AND_QUALITY
- -- Find the best match for a given `a_language' against a list of language ranges `a_parsed_ranges'
- -- that have already been parsed by parse_language_range.
- local
- best_fitness: INTEGER
- target_q: REAL_64
- best_fit_q: REAL_64
- target: LANGUAGE_RESULTS
- range: LANGUAGE_RESULTS
- keys: LIST [READABLE_STRING_8]
- param_matches: INTEGER
- element: detachable READABLE_STRING_8
- l_fitness: INTEGER
- do
- best_fitness := -1
- best_fit_q := 0.0
- target := parse_language_range (a_language)
- if attached target.item ("q") as q and then q.is_double then
- target_q := q.to_double
- if target_q < 0.0 then
- target_q := 0.0
- elseif target_q > 1.0 then
- target_q := 1.0
- end
- else
- target_q := 1.0
- end
- if attached target.type as l_target_type then
- from
- a_parsed_ranges.start
- until
- a_parsed_ranges.after
- loop
- range := a_parsed_ranges.item_for_iteration
- if (attached range.type as l_range_type and then (l_target_type.same_string (l_range_type) or l_range_type.same_string ("*") or l_target_type.same_string ("*"))) then
- from
- param_matches := 0
- keys := target.keys
- keys.start
- until
- keys.after
- loop
- element := keys.item_for_iteration
- if not element.same_string ("q") and then range.has_key (element) and then (attached target.item (element) as t_item and attached range.item (element) as r_item) and then t_item.same_string (r_item) then
- param_matches := param_matches + 1
- end
- keys.forth
- end
- if l_range_type.same_string (l_target_type) then
- l_fitness := 100
- else
- l_fitness := 0
- end
- if (attached range.sub_type as l_range_sub_type and then attached target.sub_type as l_target_sub_type and then (l_target_sub_type.same_string (l_range_sub_type) or l_range_sub_type.same_string ("*") or l_target_sub_type.same_string ("*"))) then
- if l_range_sub_type.same_string (l_target_sub_type) then
- l_fitness := l_fitness + 10
- end
- end
- l_fitness := l_fitness + param_matches
- if l_fitness > best_fitness then
- best_fitness := l_fitness
- element := range.item ("q")
- if element /= Void then
- best_fit_q := element.to_double.min (target_q)
- else
- best_fit_q := 0.0
- end
- end
- end
- a_parsed_ranges.forth
- end
- end
- create Result.make (best_fitness, best_fit_q)
- end
-
- quality_parsed (a_language: READABLE_STRING_8; a_parsed_ranges: LIST [LANGUAGE_RESULTS]): REAL_64
- -- Find the best match for a given `a_language' against a list of ranges `parsed_ranges' that
- -- have already been parsed by parse_language_range. Returns the 'q' quality
- -- parameter of the best match, 0 if no match was found. This function
- -- bahaves the same as quality except that 'a_parsed_ranges' must be a list
- -- of parsed language ranges.
- do
- Result := fitness_and_quality_parsed (a_language, a_parsed_ranges).quality
- end
-
- quality (a_language: READABLE_STRING_8; a_ranges: READABLE_STRING_8): REAL_64
- -- Returns the quality 'q' of a `a_language' when compared against the
- -- language range in `a_ranges'.
- local
- l_ranges: LIST [READABLE_STRING_8]
- res: ARRAYED_LIST [LANGUAGE_RESULTS]
- p_res: LANGUAGE_RESULTS
- do
- l_ranges := a_ranges.split (',')
- from
- create res.make (10);
- l_ranges.start
- until
- l_ranges.after
- loop
- p_res := parse_language_range (l_ranges.item_for_iteration)
- res.force (p_res)
- l_ranges.forth
- end
- Result := quality_parsed (a_language, res)
- end
-
- best_match (a_supported: LIST [READABLE_STRING_8]; a_header: READABLE_STRING_8): READABLE_STRING_8
- -- Choose the `language' with the highest fitness score and quality ('q') from a list of candidates.
- local
- l_header_results: LIST [LANGUAGE_RESULTS]
- weighted_matches: LIST [FITNESS_AND_QUALITY]
- l_res: LIST [READABLE_STRING_8]
- p_res: LANGUAGE_RESULTS
- fitness_and_quality, first_one: detachable FITNESS_AND_QUALITY
- s: READABLE_STRING_8
- do
- l_res := a_header.split (',')
- create {ARRAYED_LIST [LANGUAGE_RESULTS]} l_header_results.make (l_res.count)
- fixme ("Extract method!!!")
- from
- l_res.start
- until
- l_res.after
- loop
- p_res := parse_language_range (l_res.item_for_iteration)
- l_header_results.force (p_res)
- l_res.forth
- end
- create {ARRAYED_LIST [FITNESS_AND_QUALITY]} weighted_matches.make (a_supported.count)
- from
- a_supported.start
- until
- a_supported.after
- loop
- fitness_and_quality := fitness_and_quality_parsed (a_supported.item_for_iteration, l_header_results)
- fitness_and_quality.set_mime_type (mime_type (a_supported.item_for_iteration))
- weighted_matches.force (fitness_and_quality)
- a_supported.forth
- end
-
- --| Keep only top quality+fitness types
- from
- weighted_matches.start
- first_one := weighted_matches.item
- weighted_matches.forth
- until
- weighted_matches.after
- loop
- fitness_and_quality := weighted_matches.item
- if first_one < fitness_and_quality then
- first_one := fitness_and_quality
- if not weighted_matches.isfirst then
- from
- weighted_matches.back
- until
- weighted_matches.before
- loop
- weighted_matches.remove
- weighted_matches.back
- end
- weighted_matches.forth
- end
- check
- weighted_matches.item = fitness_and_quality
- end
- weighted_matches.forth
- elseif first_one.is_equal (fitness_and_quality) then
- weighted_matches.forth
- else
- check
- first_one > fitness_and_quality
- end
- weighted_matches.remove
- end
- end
- if first_one /= Void and then first_one.quality /= 0.0 then
- if weighted_matches.count = 1 then
- Result := first_one.mime_type
- else
- from
- fitness_and_quality := Void
- l_header_results.start
- until
- l_header_results.after or fitness_and_quality /= Void
- loop
- s := l_header_results.item.mime_type
- from
- weighted_matches.start
- until
- weighted_matches.after or fitness_and_quality /= Void
- loop
- fitness_and_quality := weighted_matches.item
- if fitness_and_quality.mime_type.same_string (s) then
- --| Found
- else
- fitness_and_quality := Void
- weighted_matches.forth
- end
- end
- l_header_results.forth
- end
- if fitness_and_quality /= Void then
- Result := fitness_and_quality.mime_type
- else
- Result := first_one.mime_type
- end
- end
- else
- Result := ""
- 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
diff --git a/library/network/protocol/content_negotiation/src/results/http_accept_language.e b/library/network/protocol/content_negotiation/src/results/http_accept_language.e
new file mode 100644
index 00000000..afbf8a9c
--- /dev/null
+++ b/library/network/protocol/content_negotiation/src/results/http_accept_language.e
@@ -0,0 +1,251 @@
+note
+ description: "Object that represents a result after parsing Language Headers."
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ HTTP_ACCEPT_LANGUAGE
+
+inherit
+ REFACTORING_HELPER
+
+ DEBUG_OUTPUT
+
+create
+ make_from_string,
+ make,
+ make_with_language,
+ make_default
+
+feature {NONE} -- Initialization
+
+ make_from_string (a_accept_language_item: READABLE_STRING_8)
+ -- Instantiate Current from part of accept-language header, i.e language tag and parameters.
+ --
+ -- Languages-ranges are languages with specialization and a 'q' quality parameter.
+ -- For example, the language l_range ('en-* ;q=0.5') would get parsed into:
+ -- ('en', '*', {'q', '0.5'})
+ -- 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
+ 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 q.same_string ("1") then
+ --| Use 1.0 formatting
+ put ("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 ?
+ elseif r >= 1.0 then
+ quality := 1.0
+ else
+ quality := r
+ end
+ else
+ put ("1.0", "q")
+ quality := 1.0
+ end
+ else
+ put ("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
+ ensure
+ language_range_set: language_range.same_string (a_lang_tag) and a_lang_tag /= language_range
+ end
+
+ make (a_root_lang: READABLE_STRING_8; a_specialization: detachable READABLE_STRING_8)
+ -- Instantiate Current with `a_root_lang' and `a_specialization'.
+ do
+ initialize
+ create language_range.make_empty
+ language := a_root_lang
+ specialization := a_specialization
+ update_language_range (a_root_lang, a_specialization)
+ end
+
+ make_default
+ -- Instantiate Current with default "*" language.
+ do
+ make ("*", Void)
+ end
+
+ initialize
+ -- Initialize Current
+ do
+ create params.make (2)
+ quality := 1.0
+ end
+
+feature -- Access
+
+ language_range: STRING_8
+ -- language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
+
+ language: READABLE_STRING_8
+ -- First part of the language range, i.e the root language
+
+ specialization: detachable READABLE_STRING_8
+ -- Optional second part of the language range, i.e the dialect, or specialized language type
+
+ quality: REAL_64
+ -- Associated quality, by default 1.0
+
+feature -- Status report
+
+ debug_output: STRING
+ -- String that should be displayed in debugger to represent `Current'.
+ do
+ create Result.make_from_string (language_range)
+ Result.append_character (';')
+ Result.append ("q=")
+ 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 (a_root_lang: READABLE_STRING_8)
+ -- Set `'anguage' with `a_root_lang'
+ require
+ a_root_lang_attached: a_root_lang /= Void
+ do
+ language := a_root_lang
+ update_language_range (a_root_lang, specialization)
+ ensure
+ type_assigned: language ~ a_root_lang
+ end
+
+ set_specialization (a_specialization: detachable READABLE_STRING_8)
+ -- Set `specialization' with `a_specialization'
+ do
+ specialization := a_specialization
+ update_language_range (language, a_specialization)
+ ensure
+ 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'
+ 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 {NONE} -- Implementation
+
+ update_language_range (a_lang: like language; a_specialization: like specialization)
+ -- Update `language_range' with `a_lang' and `a_specialization'
+ local
+ l_language_range: like language_range
+ do
+ l_language_range := language_range -- Reuse same object, be careful not to keep reference on existing string at first.
+ l_language_range.wipe_out
+ l_language_range.append (a_lang)
+
+ if a_specialization /= Void then
+ l_language_range.append_character ('-')
+ l_language_range.append (a_specialization)
+ end
+ 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
+
+invariant
+ valid_quality: 0.0 <= quality and quality <= 1.0
+
+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
diff --git a/library/network/protocol/content_negotiation/src/results/common_results.e b/library/network/protocol/content_negotiation/src/results/http_any_accept_header.e
similarity index 88%
rename from library/network/protocol/content_negotiation/src/results/common_results.e
rename to library/network/protocol/content_negotiation/src/results/http_any_accept_header.e
index 627ba520..502ee3cc 100644
--- a/library/network/protocol/content_negotiation/src/results/common_results.e
+++ b/library/network/protocol/content_negotiation/src/results/http_any_accept_header.e
@@ -1,10 +1,10 @@
note
- description: "Object that represents a results after parsing Charset or Encoding Accept headers."
+ description: "Object that represents a results after parsing Accept-* headers."
date: "$Date$"
revision: "$Revision$"
class
- COMMON_RESULTS
+ HTTP_ANY_ACCEPT_HEADER
create
make
@@ -36,9 +36,8 @@ feature -- Access
Result := res
end
-
params: HASH_TABLE [STRING, STRING]
- --dictionary of all the parameters for the media range
+ -- Table of all parameters for the media range
feature -- Status Report
@@ -51,7 +50,7 @@ feature -- Status Report
feature -- Element change
set_field (a_field: STRING)
- -- Set type with `a_charset'
+ -- Set type with `a_field'
do
field := a_field
ensure
diff --git a/library/network/protocol/content_negotiation/src/results/language_results.e b/library/network/protocol/content_negotiation/src/results/language_results.e
deleted file mode 100644
index 23211c03..00000000
--- a/library/network/protocol/content_negotiation/src/results/language_results.e
+++ /dev/null
@@ -1,112 +0,0 @@
-note
- description: "Object that represents a result after parsing Language Headers."
- date: "$Date$"
- revision: "$Revision$"
-
-class
- LANGUAGE_RESULTS
-
-create
- make
-
-feature -- Initialization
-
- make
- --Create an object LANGUAGE_RESULTS.
- do
- create params.make (2)
- create mime_type.make_from_string ("*")
- end
-
-feature -- Access
-
- type: detachable STRING
-
- sub_type: detachable STRING
-
- mime_type: 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]
- --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_type (a_type: STRING)
- -- Set type with `a_type'
- do
- type := a_type
- if attached sub_type as st then
- mime_type := a_type + "-" + st
- else
- mime_type := a_type
- end
- ensure
- type_assigned: type ~ a_type
- end
-
- set_sub_type (a_sub_type: STRING)
- -- Set sub_type with `a_sub_type
- do
- sub_type := a_sub_type
- if attached type as t then
- mime_type := t + "-" + a_sub_type
- else
- mime_type := "*"
- end
- ensure
- sub_type_assigned: sub_type ~ a_sub_type
- 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
diff --git a/library/network/protocol/content_negotiation/src/shared_conneg.e b/library/network/protocol/content_negotiation/src/shared_conneg.e
index 08c8d174..fdfd9fdd 100644
--- a/library/network/protocol/content_negotiation/src/shared_conneg.e
+++ b/library/network/protocol/content_negotiation/src/shared_conneg.e
@@ -8,18 +8,18 @@ class
feature
- Mime: MIME_PARSE
+ Mime: HTTP_ACCEPT_MEDIA_TYPE_PARSER
once
create Result
end
- Common: COMMON_ACCEPT_HEADER_PARSER
+ Common: HTTP_ANY_ACCEPT_HEADER_PARSER
-- Charset and Encoding
once
create Result
end
- Language: LANGUAGE_PARSE
+ Language: HTTP_ACCEPT_LANGUAGE_PARSER
once
create Result
end
diff --git a/library/network/protocol/content_negotiation/src/variants/character_encoding_variant_results.e b/library/network/protocol/content_negotiation/src/variants/http_accept_charset_variants.e
similarity index 67%
rename from library/network/protocol/content_negotiation/src/variants/character_encoding_variant_results.e
rename to library/network/protocol/content_negotiation/src/variants/http_accept_charset_variants.e
index 862507cd..3a36e0a8 100644
--- a/library/network/protocol/content_negotiation/src/variants/character_encoding_variant_results.e
+++ b/library/network/protocol/content_negotiation/src/variants/http_accept_charset_variants.e
@@ -1,6 +1,6 @@
note
description: "[
- {CHARACTER_ENCODING_VARIANT_RESULTS}
+ {HTTP_ACCEPT_CHARSET_VARIANTS}
Represent the character sets results between client preferences and character sets variants supported by the server.
If the server is unable to supports the requested Accept-Charset values, the server can build
a response with the list of supported character sets.
@@ -10,20 +10,22 @@ note
revision: "$Revision$"
class
- CHARACTER_ENCODING_VARIANT_RESULTS
+ HTTP_ACCEPT_CHARSET_VARIANTS
inherit
+ HTTP_ACCEPT_VARIANTS
+ rename
+ variant_value as charset
+ end
- VARIANT_RESULTS
+create
+ make
+feature -- Change
-feature -- Change Element
-
-
- set_variant_header
- -- Set variant header as `Accept-Charset'
+ set_vary_header_value
do
- variant_header := {HTTP_HEADER_NAMES}.header_accept_charset -- "Accept-Charset"
+ vary_header_value := {HTTP_HEADER_NAMES}.header_accept_charset -- "Accept-Charset"
end
note
diff --git a/library/network/protocol/content_negotiation/src/variants/compression_variant_results.e b/library/network/protocol/content_negotiation/src/variants/http_accept_encoding_variants.e
similarity index 52%
rename from library/network/protocol/content_negotiation/src/variants/compression_variant_results.e
rename to library/network/protocol/content_negotiation/src/variants/http_accept_encoding_variants.e
index 22d0893d..805bf1a9 100644
--- a/library/network/protocol/content_negotiation/src/variants/compression_variant_results.e
+++ b/library/network/protocol/content_negotiation/src/variants/http_accept_encoding_variants.e
@@ -1,28 +1,31 @@
note
description: "[
- {COMPRESSION_VARIANT_RESULTS}
- Represent the compression results between client preferences and ccompression variants supported by the server.
+ {HTTP_ACCEPT_ENCODING_VARIANTS}
+ Represent the encoding results between client preferences and encoding variants supported by the server.
If the server is unable to supports the requested Accept-Encoding values, the server can build
- a response with the list of supported encodings/compressions
+ a response with the list of supported encodings
]"
date: "$Date$"
revision: "$Revision$"
EIS: "name= Compression", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3", "protocol=uri"
class
- COMPRESSION_VARIANT_RESULTS
+ HTTP_ACCEPT_ENCODING_VARIANTS
inherit
+ HTTP_ACCEPT_VARIANTS
+ rename
+ variant_value as encoding
+ end
- VARIANT_RESULTS
+create
+ make
+feature -- Change
-feature -- Change Element
-
- set_variant_header
- -- Set variant_header as `Accept-Encoding'
+ set_vary_header_value
do
- variant_header := {HTTP_HEADER_NAMES}.header_accept_encoding -- "Accept-Encoding"
+ vary_header_value := {HTTP_HEADER_NAMES}.header_accept_encoding -- "Accept-Encoding"
end
note
diff --git a/library/network/protocol/content_negotiation/src/variants/language_variant_results.e b/library/network/protocol/content_negotiation/src/variants/http_accept_language_variants.e
similarity index 65%
rename from library/network/protocol/content_negotiation/src/variants/language_variant_results.e
rename to library/network/protocol/content_negotiation/src/variants/http_accept_language_variants.e
index 7bfb6059..f51b1f87 100644
--- a/library/network/protocol/content_negotiation/src/variants/language_variant_results.e
+++ b/library/network/protocol/content_negotiation/src/variants/http_accept_language_variants.e
@@ -1,6 +1,6 @@
note
description: "[
- {LANGUAGE_VARIANT_RESULTS}.
+ {HTTP_ACCEPT_LANGUAGE_VARIANTS}.
Represent the language results between client preferences and language variants supported by the server.
If the server is unable to supports the requested Accept-Language values, the server can build
a response with the list of supported languages
@@ -9,18 +9,22 @@ note
revision: "$Revision$"
class
- LANGUAGE_VARIANT_RESULTS
+ HTTP_ACCEPT_LANGUAGE_VARIANTS
inherit
+ HTTP_ACCEPT_VARIANTS
+ rename
+ variant_value as language
+ end
- VARIANT_RESULTS
+create
+ make
-feature -- Change Element
+feature -- Change
- set_variant_header
- -- Set variant header as 'Accept-Language'
+ set_vary_header_value
do
- variant_header := {HTTP_HEADER_NAMES}.header_accept_language -- "Accept-Language"
+ vary_header_value := {HTTP_HEADER_NAMES}.header_accept_language -- "Accept-Language"
end
note
diff --git a/library/network/protocol/content_negotiation/src/variants/media_type_variant_results.e b/library/network/protocol/content_negotiation/src/variants/http_accept_media_type_variants.e
similarity index 52%
rename from library/network/protocol/content_negotiation/src/variants/media_type_variant_results.e
rename to library/network/protocol/content_negotiation/src/variants/http_accept_media_type_variants.e
index 988f8cad..00900ce3 100644
--- a/library/network/protocol/content_negotiation/src/variants/media_type_variant_results.e
+++ b/library/network/protocol/content_negotiation/src/variants/http_accept_media_type_variants.e
@@ -1,7 +1,7 @@
note
description: "[
- {MEDIA_TYPE_VARIANT_RESULTS}.
- Represent the media type results between client preferences and media type variants supported by the server..
+ {HTTP_ACCEPT_MEDIA_TYPE_VARIANTS}.
+ Represents the media type results between client preferences and media type variants supported by the server..
If the server is unable to supports the requested Accept values, the server can build
a response with the list of supported representations
]"
@@ -9,18 +9,22 @@ note
revision: "$Revision$"
class
- MEDIA_TYPE_VARIANT_RESULTS
+ HTTP_ACCEPT_MEDIA_TYPE_VARIANTS
inherit
+ HTTP_ACCEPT_VARIANTS
+ rename
+ variant_value as media_type
+ end
- VARIANT_RESULTS
+create
+ make
-feature -- Change Element
+feature -- Change
- set_variant_header
- -- Set variant header as `Accept'
+ set_vary_header_value
do
- variant_header := {HTTP_HEADER_NAMES}.header_accept -- "Accept"
+ vary_header_value := {HTTP_HEADER_NAMES}.header_accept -- "Accept"
end
note
diff --git a/library/network/protocol/content_negotiation/src/variants/http_accept_variants.e b/library/network/protocol/content_negotiation/src/variants/http_accept_variants.e
new file mode 100644
index 00000000..86295d8b
--- /dev/null
+++ b/library/network/protocol/content_negotiation/src/variants/http_accept_variants.e
@@ -0,0 +1,92 @@
+note
+ description: "Generic {HTTP_ACCEPT_VARIANTS}.with common functionality to most header variants.."
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ HTTP_ACCEPT_VARIANTS
+
+feature {NONE} -- Initialization
+
+ make
+ do
+ end
+
+feature -- Change
+
+ set_vary_header_value
+ -- Set the `vary_header_value'
+ deferred
+ ensure
+ is_valid_header_set : is_valid_header_name (vary_header_value)
+ end
+
+feature -- Access
+
+ vary_header_value: detachable READABLE_STRING_8
+ -- Name of header to be added to the Vary header of the response
+ -- 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]
+ -- Set of supported variants for the response
+
+ variant_value: detachable READABLE_STRING_8
+ -- Associated value, it could be value of:
+ -- content type
+ -- language
+ -- character set
+ -- encoding.
+
+feature -- Status_Report
+
+ is_acceptable: BOOLEAN
+ -- is the current variant accepted?
+
+ is_valid_header_name (a_header_name: detachable READABLE_STRING_8): BOOLEAN
+ -- is `a_header_name' a valid accept header name?
+ note
+ EIS:"name=Accept", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1", "protocol=uri"
+ EIS:"name=Accept-Charset", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2", "protocol=uri"
+ EIS:"name=Accept-Encoding", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3", "protocol=uri"
+ EIS:"name=Accept-Language", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4", "protocol=uri"
+ do
+ if a_header_name /= Void then
+ Result := a_header_name.same_string ({HTTP_HEADER_NAMES}.header_accept) -- "Accept",
+ or else a_header_name.same_string ({HTTP_HEADER_NAMES}.header_accept_language) -- "Accept-Language",
+ or else a_header_name.same_string ({HTTP_HEADER_NAMES}.header_accept_encoding) -- "Accept-Encoding",
+ or else a_header_name.same_string ({HTTP_HEADER_NAMES}.header_accept_charset) -- "Accept-Charset"
+ end
+ end
+
+feature -- Change Element
+
+ set_variant_value (v: READABLE_STRING_8)
+ -- Set `variant_value' as `v'
+ do
+ variant_value := v
+ ensure
+ type_set: attached variant_value as l_variant implies l_variant = v
+ end
+
+ set_acceptable (b: BOOLEAN)
+ -- Set `is_acceptable' with `b'
+ do
+ is_acceptable := b
+ ensure
+ is_acceptable_set: is_acceptable = b
+ end
+
+ set_supported_variants (a_supported: LIST [READABLE_STRING_8])
+ -- Set `supported variants' with `a_supported'
+ do
+ supported_variants := a_supported
+ ensure
+ set_supported_variants: attached supported_variants as l_supported_variants implies l_supported_variants = a_supported
+ 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
diff --git a/library/network/protocol/content_negotiation/src/variants/variant_results.e b/library/network/protocol/content_negotiation/src/variants/variant_results.e
deleted file mode 100644
index bb48cacf..00000000
--- a/library/network/protocol/content_negotiation/src/variants/variant_results.e
+++ /dev/null
@@ -1,91 +0,0 @@
-note
- description: "Generic {VARIANT_RESULTS}.with common functionality to most header variants.."
- date: "$Date$"
- revision: "$Revision$"
-
-deferred class
- VARIANT_RESULTS
-
-feature -- Access
-
- variant_header: detachable READABLE_STRING_8
- -- Name of variant header to be added to the Vary header of the response
-
- supported_variants: detachable LIST [READABLE_STRING_8]
- -- Set of supported variants for the response
-
- is_acceptable: BOOLEAN
- -- is the current variant accepted?
-
- type: detachable READABLE_STRING_8
- -- Associated type, it could be:
- -- media type
- -- language
- -- character_sets
- -- encoding.
-
-feature {NONE} -- Implementation
-
- accept_headers_set: ARRAY [READABLE_STRING_8]
- -- Set of valid accept headers headers
- note
- EIS:"name=Accept", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1", "protocol=uri"
- EIS:"name=Accept-Charset", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2", "protocol=uri"
- EIS:"name=Accept-Encoding", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3", "protocol=uri"
- EIS:"name=Accept-Language", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4", "protocol=uri"
- once
- Result:= <<
- {HTTP_HEADER_NAMES}.header_accept, -- "Accept",
- {HTTP_HEADER_NAMES}.header_accept_language, -- "Accept-Language",
- {HTTP_HEADER_NAMES}.header_accept_encoding, -- "Accept-Encoding",
- {HTTP_HEADER_NAMES}.header_accept_charset --"Accept-Charset"
- >>
- Result.compare_objects
- end
-
-feature -- Status_Report
-
- is_valid_header (a_header: READABLE_STRING_8): BOOLEAN
- -- is `a_header' a valid accept header?
- do
- Result := accept_headers_set.has (a_header)
- end
-
-feature -- Change Element
-
- set_type (a_type: READABLE_STRING_8)
- -- Set `type' as `a_type'
- do
- type := a_type
- ensure
- type_set: attached type as l_type implies l_type = a_type
- end
-
- set_acceptable (acceptable: BOOLEAN)
- -- Set `is_acceptable' with `acceptable'
- do
- is_acceptable := acceptable
- ensure
- is_acceptable_set: is_acceptable = acceptable
- end
-
- set_variant_header
- -- Set variant header
- deferred
- ensure
- is_valid_header_set : attached variant_header as l_header implies is_valid_header (l_header)
- end
-
- set_supported_variants (a_supported: LIST [READABLE_STRING_8])
- -- Set `supported variants' with `a_supported'
- do
- supported_variants := a_supported
- ensure
- set_supported_variants: attached supported_variants as l_supported_variants implies l_supported_variants = a_supported
- 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
diff --git a/library/network/protocol/content_negotiation/test/application.e b/library/network/protocol/content_negotiation/test/application.e
index a7078001..b7152129 100644
--- a/library/network/protocol/content_negotiation/test/application.e
+++ b/library/network/protocol/content_negotiation/test/application.e
@@ -16,10 +16,10 @@ feature {NONE} -- Initialization
make
local
- mime_parse : MIME_PARSE
+ mime_parse : HTTP_ACCEPT_MEDIA_TYPE_PARSER
accept : STRING
- charset_parse : COMMON_ACCEPT_HEADER_PARSER
- language : LANGUAGE_PARSE
+ charset_parse : HTTP_ANY_ACCEPT_HEADER_PARSER
+ language : HTTP_ACCEPT_LANGUAGE_PARSER
do
create mime_parse
-- parse_result := mime_parse.parse_mime_type ("application/xhtml;q=0.5")
@@ -59,12 +59,12 @@ feature {NONE} -- Initialization
print ("%N"+mime_parse.quality ("*/*;q=0.1", accept).out)
accept := "application/atom+xml"
- print ("%N"+mime_parse.parse_mime_type (accept).out)
+ print ("%N"+mime_parse.media_type (accept).out)
create charset_parse
accept := "iso-8859-5"
- print ("%N" + charset_parse.parse_common (accept).out)
+ print ("%N" + charset_parse.header (accept).out)
accept := "unicode-1-1;q=0.8"
- print ("%N" + charset_parse.parse_common (accept).out)
+ print ("%N" + charset_parse.header (accept).out)
accept:= "iso-8859-5, unicode-1-1;q=0.8"
@@ -78,10 +78,10 @@ feature {NONE} -- Initialization
print (language.best_match (accept.split (','), "da"))
print (language.best_match (accept.split (','), "en-*"))
- print ("%N"+language.parse_language_range ("da").out)
- print ("%N"+language.parse_language_range ("en-gb;q=0.8").out)
- print ("%N"+language.parse_language_range ("en;q=0.7").out)
- print ("%N"+language.parse_language_range ("en-*").out)
+ print ("%N"+language.accept_language ("da").out)
+ print ("%N"+language.accept_language ("en-gb;q=0.8").out)
+ print ("%N"+language.accept_language ("en;q=0.7").out)
+ print ("%N"+language.accept_language ("en-*").out)
end
end
diff --git a/library/network/protocol/content_negotiation/test/common_accept_header_parser_test.e b/library/network/protocol/content_negotiation/test/common_accept_header_parser_test.e
index 9cd88ad5..3c3dcbf6 100644
--- a/library/network/protocol/content_negotiation/test/common_accept_header_parser_test.e
+++ b/library/network/protocol/content_negotiation/test/common_accept_header_parser_test.e
@@ -23,7 +23,7 @@ feature {NONE} -- Events
feature -- Helpers
- format (a_common: COMMON_RESULTS): STRING
+ format (a_common: HTTP_ANY_ACCEPT_HEADER): STRING
-- Representation of the current object
do
create Result.make_from_string ("(")
@@ -47,9 +47,9 @@ feature -- Test routines
test_parse_charsets
do
- assert ("Expected ('iso-8859-5', {'q':'1.0',})", format (parser.parse_common("iso-8859-5")).same_string("('iso-8859-5', {'q':'1.0',})") )
- assert ("Expected ('unicode-1-1', {'q':'0.8',})", format (parser.parse_common("unicode-1-1;q=0.8")).same_string("('unicode-1-1', {'q':'0.8',})") )
- assert ("Expected ('*', {'q':'1.0',})", format (parser.parse_common("*")).same_string("('*', {'q':'1.0',})") )
+ assert ("Expected ('iso-8859-5', {'q':'1.0',})", format (parser.header("iso-8859-5")).same_string("('iso-8859-5', {'q':'1.0',})") )
+ assert ("Expected ('unicode-1-1', {'q':'0.8',})", format (parser.header("unicode-1-1;q=0.8")).same_string("('unicode-1-1', {'q':'0.8',})") )
+ assert ("Expected ('*', {'q':'1.0',})", format (parser.header("*")).same_string("('*', {'q':'1.0',})") )
end
@@ -74,6 +74,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 : COMMON_ACCEPT_HEADER_PARSER
+ parser : HTTP_ANY_ACCEPT_HEADER_PARSER
end
diff --git a/library/network/protocol/content_negotiation/test/conneg_server_side_test.e b/library/network/protocol/content_negotiation/test/conneg_server_side_test.e
index 1ff829d2..d0c1e518 100644
--- a/library/network/protocol/content_negotiation/test/conneg_server_side_test.e
+++ b/library/network/protocol/content_negotiation/test/conneg_server_side_test.e
@@ -24,7 +24,7 @@ feature {NONE} -- Events
feature -- Test routines
test_media_type_negotiation
local
- media_variants : MEDIA_TYPE_VARIANT_RESULTS
+ media_variants : HTTP_ACCEPT_MEDIA_TYPE_VARIANTS
mime_types_supported : LIST [STRING]
l_types : STRING
do
@@ -39,22 +39,22 @@ feature -- Test routines
else
assert ("Has supported_variants results", False)
end
- assert ("Variant header is void",media_variants.variant_header = Void)
- assert ("Media type is void",media_variants.type = Void)
+ assert ("Variant Header", attached media_variants.vary_header_value as l_variant_header and then l_variant_header.same_string ("Accept"))
+ assert ("Media type is void",media_variants.media_type = Void)
-- Scenario 2, the client doesnt send values in the header, Accept:
media_variants := conneg.media_type_preference (mime_types_supported, "")
assert ("Expected Acceptable", media_variants.is_acceptable)
- assert ("Variants is dettached",media_variants.supported_variants = Void)
- assert ("Mime is default", attached media_variants.type as l_type and then conneg.mime_default.is_equal (l_type))
- assert ("Variant header", media_variants.variant_header = Void)
+ assert ("Variants is set",media_variants.supported_variants = mime_types_supported)
+ assert ("Mime is default", attached media_variants.media_type as l_media_type and then conneg.default_media_type.same_string (l_media_type))
+ assert ("Variant header", media_variants.vary_header_value = Void)
--Scenario 3, the server select the best match, and set the vary header
- media_variants := conneg.media_type_preference (mime_types_supported, "text/*,application/json;q=0.5")
+ media_variants := conneg.media_type_preference (mime_types_supported, "text/*,application/xml;q=0.5,application/json;q=0.6")
assert ("Expected Acceptable", media_variants.is_acceptable)
- assert ("Variants is dettached",media_variants.supported_variants = Void)
- assert ("Variant Header", attached media_variants.variant_header as l_variant_header and then l_variant_header.same_string ("Accept"))
- assert ("Media Type is application/json", attached media_variants.type as l_type and then l_type.same_string ("application/json"))
+ assert ("Variants is set",media_variants.supported_variants = mime_types_supported)
+ assert ("Variant Header", attached media_variants.vary_header_value as l_variant_header and then l_variant_header.same_string ("Accept"))
+ assert ("Media Type is application/json", attached media_variants.media_type as l_media_type and then l_media_type.same_string ("application/json"))
end
@@ -62,13 +62,13 @@ feature -- Test routines
test_charset_negotiation
local
- charset_variants : CHARACTER_ENCODING_VARIANT_RESULTS
+ charset_variants : HTTP_ACCEPT_CHARSET_VARIANTS
charset_supported : LIST [STRING]
- l_charset : STRING
+ l_charset_value : STRING
do
-- Scenario 1, the server side does not support client preferences
- l_charset := "UTF-8, iso-8859-5"
- charset_supported := l_charset.split(',')
+ l_charset_value := "UTF-8, iso-8859-5"
+ charset_supported := l_charset_value.split(',')
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
@@ -77,29 +77,29 @@ feature -- Test routines
else
assert("Has supported_variants results", False)
end
- assert ("Variant header is void",charset_variants.variant_header = Void)
- assert ("Character type is void",charset_variants.type = Void)
+ assert ("Variant Header", attached charset_variants.vary_header_value as l_variant_header and then l_variant_header.same_string ("Accept-Charset"))
+ assert ("Character type is void",charset_variants.charset = Void)
-- Scenario 2, the client doesnt send values in the header, Accept-Charset:
charset_variants := conneg.charset_preference (charset_supported, "")
assert ("Expected Acceptable", charset_variants.is_acceptable)
- assert ("Variants is dettached",charset_variants.supported_variants = Void)
- assert ("Charset is defaul", attached charset_variants.type as l_type and then conneg.charset_default.is_equal (l_type))
- assert ("Variant header", charset_variants.variant_header = Void)
+ assert ("Variants is set",charset_variants.supported_variants = charset_supported)
+ assert ("Charset is default", attached charset_variants.charset as l_charset and then conneg.default_charset.same_string (l_charset))
+ assert ("Variant header", charset_variants.vary_header_value = Void)
--Scenario 3, the server select the best match, and set the vary header
charset_variants := conneg.charset_preference (charset_supported, "unicode-1-1, UTF-8;q=0.3, iso-8859-5")
assert ("Expected Acceptable", charset_variants.is_acceptable)
- assert ("Variants is dettached",charset_variants.supported_variants = Void)
- assert ("Variant Header", attached charset_variants.variant_header as l_variant_header and then l_variant_header.same_string ("Accept-Charset"))
- assert ("Character Type is iso-8859-5", attached charset_variants.type as l_type and then l_type.same_string ("iso-8859-5"))
+ assert ("Variants is set",charset_variants.supported_variants = charset_supported)
+ assert ("Variant Header", attached charset_variants.vary_header_value as l_variant_header and then l_variant_header.same_string ("Accept-Charset"))
+ assert ("Character Type is iso-8859-5", attached charset_variants.charset as l_charset and then l_charset.same_string ("iso-8859-5"))
end
test_compression_negotiation
local
- compression_variants : COMPRESSION_VARIANT_RESULTS
+ compression_variants : HTTP_ACCEPT_ENCODING_VARIANTS
compression_supported : LIST [STRING]
l_compression : STRING
do
@@ -109,39 +109,39 @@ 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.at (1).is_equal (l_supported_variants.first))
+ assert ("Same Value at 1",compression_supported.first.same_string (l_supported_variants.first))
assert ("Same count",compression_supported.count = l_supported_variants.count)
else
assert ("Has supported_variants results", False)
end
- assert ("Variant header is void",compression_variants.variant_header = Void)
- assert ("Compression type is void",compression_variants.type = Void)
+ assert ("Variant Header", attached compression_variants.vary_header_value as l_variant_header and then l_variant_header.same_string ("Accept-Encoding"))
+ assert ("Compression type is void",compression_variants.encoding = Void)
-- Scenario 2, the client doesnt send values in the header, Accept-Encoding
compression_variants := conneg.encoding_preference (compression_supported, "")
assert ("Expected Acceptable", compression_variants.is_acceptable)
- assert ("Variants is dettached",compression_variants.supported_variants = Void)
- assert ("Compression is defaul", attached compression_variants.type as l_type and then conneg.encoding_default.same_string (l_type))
- assert ("Variant header", compression_variants.variant_header = Void)
+ assert ("Variants is set",compression_variants.supported_variants = compression_supported)
+ assert ("Compression is default", attached compression_variants.encoding as l_encoding and then conneg.default_encoding.same_string (l_encoding))
+ assert ("Variant header", compression_variants.vary_header_value = Void)
--Scenario 3, the server select the best match, and set the vary header
l_compression := "gzip"
compression_supported := l_compression.split(',')
- conneg.set_encoding_default("gzip")
+ conneg.set_default_encoding("gzip")
compression_variants := conneg.encoding_preference (compression_supported, "compress,gzip;q=0.7")
assert ("Expected Acceptable", compression_variants.is_acceptable)
- assert ("Variants is dettached",compression_variants.supported_variants = Void)
- assert ("Variant Header", attached compression_variants.variant_header as l_variant_header and then l_variant_header.same_string ("Accept-Encoding"))
- assert ("Encoding Type is gzip", attached compression_variants.type as l_type and then l_type.same_string ("gzip"))
+ assert ("Variants is set",compression_variants.supported_variants = compression_supported)
+ assert ("Variant Header", attached compression_variants.vary_header_value as l_variant_header and then l_variant_header.same_string ("Accept-Encoding"))
+ assert ("Encoding Type is gzip", attached compression_variants.encoding as l_type and then l_type.same_string ("gzip"))
end
test_language_negotiation
local
- language_variants : LANGUAGE_VARIANT_RESULTS
+ language_variants : HTTP_ACCEPT_LANGUAGE_VARIANTS
languages_supported : LIST [STRING]
l_languages : STRING
do
@@ -150,8 +150,8 @@ feature -- Test routines
languages_supported := l_languages.split(',')
language_variants := conneg.language_preference (languages_supported, "de")
assert ("Expected Not Acceptable", not language_variants.is_acceptable)
- assert ("Variant header is void",language_variants.variant_header = Void)
- assert ("Language type is void",language_variants.type = Void)
+ 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)
@@ -159,21 +159,19 @@ feature -- Test routines
assert ("Has supported variants results", False)
end
-
-- Scenario 2, the client doesnt send values in the header, Accept-Language:
language_variants := conneg.language_preference (languages_supported, "")
assert ("Expected Acceptable", language_variants.is_acceptable)
- assert ("Variants is dettached",language_variants.supported_variants = Void)
- assert ("Language is default", attached language_variants.type as l_type and then conneg.language_default.same_string (l_type))
- assert ("Variant header", language_variants.variant_header = Void)
-
+ assert ("Variants is attached",language_variants.supported_variants = languages_supported)
+ assert ("Language is default", attached language_variants.language as l_lang and then conneg.default_language.same_string (l_lang))
+ assert ("Variant header", language_variants.vary_header_value = Void)
--Scenario 3, the server select the best match, and set the vary header
language_variants := conneg.language_preference (languages_supported, "fr,es;q=0.4")
assert ("Expected Acceptable", language_variants.is_acceptable)
- assert ("Variants is dettached",language_variants.supported_variants = Void)
- assert ("Variant Header", attached language_variants.variant_header as l_variant_header and then l_variant_header.same_string ("Accept-Language"))
- assert ("Language Type is fr", attached language_variants.type as l_type and then l_type.same_string ("fr"))
+ assert ("Variants is detached",language_variants.supported_variants = languages_supported)
+ 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 fr", attached language_variants.language as l_lang and then l_lang.same_string ("fr"))
end
feature -- Implementation
diff --git a/library/network/protocol/content_negotiation/test/exception_trace.log b/library/network/protocol/content_negotiation/test/exception_trace.log
new file mode 100644
index 00000000..3d5d5442
--- /dev/null
+++ b/library/network/protocol/content_negotiation/test/exception_trace.log
@@ -0,0 +1,5 @@
+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
diff --git a/library/network/protocol/content_negotiation/test/language_parser_test.e b/library/network/protocol/content_negotiation/test/language_parser_test.e
index fe557164..42acbbb8 100644
--- a/library/network/protocol/content_negotiation/test/language_parser_test.e
+++ b/library/network/protocol/content_negotiation/test/language_parser_test.e
@@ -23,14 +23,14 @@ feature {NONE} -- Events
feature -- Helpers
- format (a_language: LANGUAGE_RESULTS): STRING
+ format (a_language: HTTP_ACCEPT_LANGUAGE): STRING
-- Representation of the current object
do
create Result.make_from_string ("(")
- if attached a_language.type as t then
+ if attached a_language.language as t then
Result.append_string ("'" + t + "',")
end
- if attached a_language.sub_type as st then
+ if attached a_language.specialization as st then
Result.append_string (" '" + st + "',")
end
Result.append_string (" {")
@@ -52,10 +52,10 @@ feature -- Test routines
test_parse_language
do
- assert ("Expected ('da', {'q':'1.0',})", format (parser.parse_language_range ("da")).same_string ("('da', {'q':'1.0',})"));
- assert ("Expected ('en', 'gb', {'q':'0.8',})", format (parser.parse_language_range ("en-gb;q=0.8")).same_string ("('en', 'gb', {'q':'0.8',})"));
- assert ("Expected ('en', {'q':'0.7',})", format (parser.parse_language_range ("en;q=0.7")).same_string ("('en', {'q':'0.7',})"));
- assert ("Expected ('en', '*', {'q':'1.0',})", format (parser.parse_language_range ("en-*")).same_string ("('en', '*', {'q':'1.0',})"));
+ assert ("Expected ('da', {'q':'1.0',})", format (parser.accept_language ("da")).same_string ("('da', {'q':'1.0',})"));
+ assert ("Expected ('en', 'gb', {'q':'0.8',})", format (parser.accept_language ("en-gb;q=0.8")).same_string ("('en', 'gb', {'q':'0.8',})"));
+ assert ("Expected ('en', {'q':'0.7',})", format (parser.accept_language ("en;q=0.7")).same_string ("('en', {'q':'0.7',})"));
+ assert ("Expected ('en', '*', {'q':'1.0',})", format (parser.accept_language ("en-*")).same_string ("('en', '*', {'q':'1.0',})"));
end
@@ -73,53 +73,53 @@ feature -- Test routines
test_best_match
local
- mime_types_supported : LIST [STRING]
+ langs_supported : LIST [STRING]
l_types : STRING
do
l_types := "en-gb,en-us"
- mime_types_supported := l_types.split(',')
- assert ("Expected en-us", parser.best_match (mime_types_supported, "en-us").same_string ("en-us"))
- assert ("Direct match with a q parameter", parser.best_match (mime_types_supported, "en-gb;q=1").same_string ("en-gb"))
- assert ("Direct match second choice with a q parameter", parser.best_match (mime_types_supported, "en-us;q=1").same_string ("en-us"))
- assert ("Direct match using a subtype wildcard", parser.best_match (mime_types_supported, "en-*;q=1").is_equal ("en-gb"))
- assert ("Match using a type wildcard", parser.best_match (mime_types_supported, "*").same_string ("en-gb"))
+ langs_supported := l_types.split(',')
+ assert ("Expected en-us", parser.best_match (langs_supported, "en-us").same_string ("en-us"))
+ assert ("Direct match with a q parameter", parser.best_match (langs_supported, "en-gb;q=1").same_string ("en-gb"))
+ assert ("Direct match second choice with a q parameter", parser.best_match (langs_supported, "en-us;q=1").same_string ("en-us"))
+ assert ("Direct match using a subtype wildcard", parser.best_match (langs_supported, "en-*;q=1").is_equal ("en-gb"))
+ assert ("Match using a type wildcard", parser.best_match (langs_supported, "*").same_string ("en-gb"))
l_types := "en-gb,es"
- mime_types_supported := l_types.split(',')
- assert ("Match using a type versus a lower weighted subtype", parser.best_match (mime_types_supported, "es-*;q=0.5,*;q=0.1").same_string ("es"))
- assert ("Fail to match anything",parser.best_match (mime_types_supported, "fr; q=0.9").same_string (""))
+ langs_supported := l_types.split(',')
+ assert ("Match using a type versus a lower weighted subtype", parser.best_match (langs_supported, "es-*;q=0.5,*;q=0.1").same_string ("es"))
+ assert ("Fail to match anything",parser.best_match (langs_supported, "fr; q=0.9").same_string (""))
l_types := "en-gb,en-us"
- mime_types_supported := l_types.split(',')
- assert ("Test 1 verify fitness ordering", parser.best_match (mime_types_supported, "en-gb,en-us,*").same_string ("en-gb"))
+ langs_supported := l_types.split(',')
+ assert ("Test 1 verify fitness ordering", parser.best_match (langs_supported, "en-gb,en-us,*").same_string ("en-gb"))
l_types := "es,en-gb;q=1.0,fr;q=0.6"
- mime_types_supported := l_types.split(',')
- assert ("Match default es at first position", parser.best_match (mime_types_supported, "es;q=1.0,*;q=0.1,fr").same_string ("es"))
+ langs_supported := l_types.split(',')
+ assert ("Match default es at first position", parser.best_match (langs_supported, "es;q=1.0,*;q=0.1,fr").same_string ("es"))
l_types := "en-gb;q=1.0,fr;q=0.6,es"
- mime_types_supported := l_types.split(',')
- assert ("Match default es at last position", parser.best_match (mime_types_supported, "es;q=1.0,*;q=0.1,fr").same_string ("es"))
+ langs_supported := l_types.split(',')
+ assert ("Match default es at last position", parser.best_match (langs_supported, "es;q=1.0,*;q=0.1,fr").same_string ("es"))
l_types := "en-gb;q=1.0,fr,es"
- mime_types_supported := l_types.split(',')
- assert ("Match first top quality and fitness", parser.best_match (mime_types_supported, "es;q=1.0,*;q=0.1,fr").same_string ("es"))
+ langs_supported := l_types.split(',')
+ assert ("Match first top quality and fitness", parser.best_match (langs_supported, "es;q=1.0,*;q=0.1,fr").same_string ("es"))
l_types := "fr;q=1.0,en,es"
- mime_types_supported := l_types.split(',')
- assert ("Test 1", parser.best_match (mime_types_supported, "es;q=1.0,*/*;q=0.1,en;q=0.9").same_string ("es"))
+ langs_supported := l_types.split(',')
+ assert ("Test 1", parser.best_match (langs_supported, "es;q=1.0,*/*;q=0.1,en;q=0.9").same_string ("es"))
l_types := "fr;q=1.0,en,es"
- mime_types_supported := l_types.split(',')
- assert ("Test 1", parser.best_match (mime_types_supported, "es,*/*;q=0.1,en").same_string ("es"))
+ langs_supported := l_types.split(',')
+ assert ("Test 1", parser.best_match (langs_supported, "es,*/*;q=0.1,en").same_string ("es"))
l_types := "fr;q=1.0,en,es"
- mime_types_supported := l_types.split(',')
- assert ("Test 2", parser.best_match (mime_types_supported, "en,es,*/*;q=0.1").same_string ("en"))
+ langs_supported := l_types.split(',')
+ assert ("Test 2", parser.best_match (langs_supported, "en,es,*/*;q=0.1").same_string ("en"))
l_types := "es,en;q=0.6"
- mime_types_supported := l_types.split(',')
- assert ("Test 2", parser.best_match (mime_types_supported, "fr;q=1.0, en;q=0.6, es").same_string ("es"))
+ langs_supported := l_types.split(',')
+ assert ("Test 2", parser.best_match (langs_supported, "fr;q=1.0, en;q=0.6, es").same_string ("es"))
end
@@ -137,7 +137,7 @@ feature -- Test routines
- parser : LANGUAGE_PARSE
+ parser : HTTP_ACCEPT_LANGUAGE_PARSER
end
diff --git a/library/network/protocol/content_negotiation/test/mime_parser_test.e b/library/network/protocol/content_negotiation/test/mime_parser_test.e
index a63b8505..0dbe8034 100644
--- a/library/network/protocol/content_negotiation/test/mime_parser_test.e
+++ b/library/network/protocol/content_negotiation/test/mime_parser_test.e
@@ -54,15 +54,15 @@ feature -- Test routines
test_parse_media_range
do
- assert ("Expected ('application', 'xml', {'q':'1',})", format (parser.parse_media_range("application/xml;q=1")).same_string("('application', 'xml', {'q':'1.0',})") )
+ assert ("Expected ('application', 'xml', {'q':'1',})", format (parser.media_type("application/xml;q=1")).same_string("('application', 'xml', {'q':'1.0',})") )
- assert ("Expected ('application', 'xml', {'q':'1',})", format (parser.parse_media_range("application/xml")).same_string("('application', 'xml', {'q':'1.0',})") )
- assert ("Expected ('application', 'xml', {'q':'1',})", format (parser.parse_media_range("application/xml;q=")).same_string("('application', 'xml', {'q':'1.0',})") )
- assert ("Expected ('application', 'xml', {'q':'1',})", format (parser.parse_media_range("application/xml ; q=")).same_string("('application', 'xml', {'q':'1.0',})") )
- assert ("Expected ('application', 'xml', {'q':'1','b':'other',})", format (parser.parse_media_range("application/xml ; q=1;b=other")).same_string("('application', 'xml', {'q':'1.0','b':'other',})") )
- assert ("Expected ('application', 'xml', {'q':'1','b':'other',})", format (parser.parse_media_range("application/xml ; q=2;b=other")).same_string("('application', 'xml', {'q':'1.0','b':'other',})") )
+ assert ("Expected ('application', 'xml', {'q':'1',})", format (parser.media_type("application/xml")).same_string("('application', 'xml', {'q':'1.0',})") )
+ assert ("Expected ('application', 'xml', {'q':'1',})", format (parser.media_type("application/xml;q=")).same_string("('application', 'xml', {'q':'1.0',})") )
+ assert ("Expected ('application', 'xml', {'q':'1',})", format (parser.media_type("application/xml ; q=")).same_string("('application', 'xml', {'q':'1.0',})") )
+ assert ("Expected ('application', 'xml', {'q':'1','b':'other',})", format (parser.media_type("application/xml ; q=1;b=other")).same_string("('application', 'xml', {'q':'1.0','b':'other',})") )
+ assert ("Expected ('application', 'xml', {'q':'1','b':'other',})", format (parser.media_type("application/xml ; q=2;b=other")).same_string("('application', 'xml', {'q':'1.0','b':'other',})") )
-- Accept header that includes *
- assert ("Expected ('*', '*', {'q':'.2',})", format (parser.parse_media_range(" *; q=.2")).same_string("('*', '*', {'q':'.2',})"))
+ assert ("Expected ('*', '*', {'q':'.2',})", format (parser.media_type(" *; q=.2")).same_string("('*', '*', {'q':'.2',})"))
end
@@ -148,7 +148,7 @@ feature -- Test routines
- parser : MIME_PARSE
+ parser : HTTP_ACCEPT_MEDIA_TYPE_PARSER
end