diff --git a/library/network/protocol/CONNEG/run_test.rb b/library/network/protocol/CONNEG/run_test.rb deleted file mode 100644 index 4ee95c80..00000000 --- a/library/network/protocol/CONNEG/run_test.rb +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env ruby -# Niklaus Giger, 15.01.2011 -# Small ruby-script run all tests using ec (the Eiffel compiler) -# we assumen that ec outputs everything in english! - -# For the command line options look at -# http://docs.eiffel.com/book/eiffelstudio/eiffelstudio-command-line-options -# we use often the -batch open. -# -# TODO: Fix problems when compiling takes too long and/or there -# are ec process lingering around from a previous failed build - -require 'tempfile' -require 'fileutils' - -# Override system command. -# run command. if not successful, complain and exit with error -def system(cmd) - puts cmd - res = Kernel.system(cmd) - if !res - puts "Failed running: #{cmd}" - exit 2 - end -end - - -def runTestForProject(where) - if !File.directory?(where) - puts "Directory #{where} does not exist" - exit 2 - end - - # create a temporary file with input for the - # interactive mode of ec - commands2run=< 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 - --Java URLConnection class sends an Accept header that includes a - --single "*" - Turn it into a legal wildcard. - - 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_media_range (a_range: STRING): LANGUAGE_RESULTS - -- 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'}) - -- 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_mime_type (a_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_mime_type: STRING; parsed_ranges: LIST [LANGUAGE_RESULTS]): 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. Returns a - -- tuple of the fitness value and the value of the 'q' quality parameter of - -- the best match, or (-1, 0) if no match was found. Just as for - -- quality_parsed(), 'parsed_ranges' must be a list of parsed media ranges. - local - best_fitness: INTEGER - target_q: REAL_64 - best_fit_q: REAL_64 - target: LANGUAGE_RESULTS - range: LANGUAGE_RESULTS - keys: LIST [STRING] - param_matches: INTEGER - element: detachable STRING - l_fitness: INTEGER - do - best_fitness := -1 - best_fit_q := 0.0 - target := parse_media_range (a_mime_type) - 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 - parsed_ranges.start - until - parsed_ranges.after - loop - range := 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 - parsed_ranges.forth - end - end - create Result.make (best_fitness, best_fit_q) - end - - quality_parsed (a_mime_type: STRING; parsed_ranges: LIST [LANGUAGE_RESULTS]): REAL_64 - -- Find the best match for a given mime-type against a list of ranges that - -- have already been parsed by parseMediaRange(). 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 - end - - quality (a_mime_type: STRING; ranges: STRING): REAL_64 - -- Returns the quality 'q' of a mime-type when compared against the - -- mediaRanges in ranges. - local - l_ranges : LIST [STRING] - res : ARRAYED_LIST [LANGUAGE_RESULTS] - p_res : LANGUAGE_RESULTS - 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.put_left (p_res) - l_ranges.forth - end - Result := quality_parsed (a_mime_type, res) - end - - best_match (supported: LIST [STRING]; header: STRING): STRING - -- Choose the mime-type 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 [STRING] - p_res: LANGUAGE_RESULTS - fitness_and_quality, first_one: detachable FITNESS_AND_QUALITY - s: STRING - do - l_res := 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_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.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 - -feature {NONE} -- Implementation - - mime_type (s: STRING): STRING - local - p: INTEGER - do - p := s.index_of (';', 1) - if p > 0 then - Result := trim (s.substring (1, p - 1)) - else - Result := trim (s.string) - end - end - - trim (a_string: STRING): STRING - -- trim whitespace from the beginning and end of a string - require - valid_argument : a_string /= Void - do - a_string.left_adjust - a_string.right_justify - Result := a_string - ensure - result_same_as_argument: a_string = Result - end - -note - copyright: "2011-2011, Javier Velilla, Jocelyn Fiat and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" -end diff --git a/library/network/protocol/CONNEG/src/language_variant_results.e b/library/network/protocol/CONNEG/src/language_variant_results.e deleted file mode 100644 index 096f4293..00000000 --- a/library/network/protocol/CONNEG/src/language_variant_results.e +++ /dev/null @@ -1,46 +0,0 @@ -note - description: "Summary description for {LANGUAGE_VARIANT_RESULTS}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - LANGUAGE_VARIANT_RESULTS - -feature - language_type : detachable STRING - set_language_type ( a_language_type: STRING) - do - language_type := a_language_type - ensure - set_language_type : a_language_type ~ language_type - end - - variant_header : detachable STRING - set_variant_header - do - variant_header := "Accept-Language" - end - - supported_variants : detachable LIST[STRING] - set_supported_variants (a_supported : LIST[STRING]) - do - supported_variants := a_supported - ensure - set_supported_variants : supported_variants = a_supported - end - - is_acceptable : BOOLEAN - - set_acceptable ( acceptable : BOOLEAN) - do - is_acceptable := acceptable - ensure - is_acceptable = acceptable - end - - -note - copyright: "2011-2011, Javier Velilla, Jocelyn Fiat and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" -end diff --git a/library/network/protocol/CONNEG/src/media_type_variant_results.e b/library/network/protocol/CONNEG/src/media_type_variant_results.e deleted file mode 100644 index 8e4a6234..00000000 --- a/library/network/protocol/CONNEG/src/media_type_variant_results.e +++ /dev/null @@ -1,47 +0,0 @@ -note - description: "Summary description for {MEDIA_TYPE_VARIANT_RESULTS}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - MEDIA_TYPE_VARIANT_RESULTS - -feature - - media_type : detachable STRING - set_media_type ( a_media_type: STRING) - do - media_type := a_media_type - ensure - set_media_type : a_media_type ~ media_type - end - - variant_header : detachable STRING - set_variant_header - do - variant_header := "Accept" - end - - supported_variants : detachable LIST[STRING] - set_supported_variants (a_supported : LIST[STRING]) - do - supported_variants := a_supported - ensure - set_supported_variants : supported_variants = a_supported - end - - is_acceptable : BOOLEAN - - set_acceptable ( acceptable : BOOLEAN) - do - is_acceptable := acceptable - ensure - is_acceptable = acceptable - end - - -note - copyright: "2011-2011, Javier Velilla, Jocelyn Fiat and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" -end diff --git a/library/network/protocol/CONNEG/src/variant_results.e b/library/network/protocol/CONNEG/src/variant_results.e deleted file mode 100644 index 65272762..00000000 --- a/library/network/protocol/CONNEG/src/variant_results.e +++ /dev/null @@ -1,58 +0,0 @@ -note - description: "Summary description for {VARIANT_RESULTS}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - VARIANT_RESULTS - -feature -- Mime, Language, Charset and Encoding Results - - mime_result : detachable STRING - - set_mime_result ( a_mime: STRING) - -- set the mime_result with `a_mime' - do - mime_result := a_mime - ensure - set_mime_result: a_mime ~ mime_result - end - - - language_result : detachable STRING - - set_language_result (a_language : STRING) - -- set the language_result with `a_language' - do - language_result := a_language - ensure - set_language : a_language ~ language_result - end - - - charset_result : detachable STRING - - set_charset_result (a_charset : STRING) - -- set the charset_result with `a_charset' - do - charset_result := a_charset - ensure - set_charset : a_charset ~ charset_result - end - - - encoding_result : detachable STRING - - set_encoding_defautl (an_encoding : STRING) - do - encoding_result := an_encoding - ensure - set_encoding : an_encoding ~ encoding_result - end - - -note - copyright: "2011-2011, Javier Velilla, Jocelyn Fiat and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" -end diff --git a/library/network/protocol/CONNEG/test/.gitignore b/library/network/protocol/CONNEG/test/.gitignore deleted file mode 100644 index ac53b3c2..00000000 --- a/library/network/protocol/CONNEG/test/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*~ -EIFGEN* # ignore all files in the EIFGENs/ directory - - diff --git a/library/network/protocol/CONNEG/test/test.rc b/library/network/protocol/CONNEG/test/test.rc deleted file mode 100644 index 8b137891..00000000 --- a/library/network/protocol/CONNEG/test/test.rc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/library/network/protocol/CONNEG/.gitignore b/library/network/protocol/content_negotation/.gitignore similarity index 100% rename from library/network/protocol/CONNEG/.gitignore rename to library/network/protocol/content_negotation/.gitignore diff --git a/library/network/protocol/CONNEG/README.md b/library/network/protocol/content_negotation/README.md similarity index 100% rename from library/network/protocol/CONNEG/README.md rename to library/network/protocol/content_negotation/README.md diff --git a/library/network/protocol/CONNEG/conneg-safe.ecf b/library/network/protocol/content_negotation/conneg-safe.ecf similarity index 92% rename from library/network/protocol/CONNEG/conneg-safe.ecf rename to library/network/protocol/content_negotation/conneg-safe.ecf index 42207d69..06a7bda6 100644 --- a/library/network/protocol/CONNEG/conneg-safe.ecf +++ b/library/network/protocol/content_negotation/conneg-safe.ecf @@ -12,7 +12,7 @@ - + diff --git a/library/network/protocol/CONNEG/conneg.ecf b/library/network/protocol/content_negotation/conneg.ecf similarity index 100% rename from library/network/protocol/CONNEG/conneg.ecf rename to library/network/protocol/content_negotation/conneg.ecf diff --git a/library/network/protocol/CONNEG/license.lic b/library/network/protocol/content_negotation/license.lic similarity index 100% rename from library/network/protocol/CONNEG/license.lic rename to library/network/protocol/content_negotation/license.lic diff --git a/library/network/protocol/CONNEG/src/.gitignore b/library/network/protocol/content_negotation/src/.gitignore similarity index 100% rename from library/network/protocol/CONNEG/src/.gitignore rename to library/network/protocol/content_negotation/src/.gitignore diff --git a/library/network/protocol/content_negotation/src/conneg_server_side.e b/library/network/protocol/content_negotation/src/conneg_server_side.e new file mode 100644 index 00000000..620fbed8 --- /dev/null +++ b/library/network/protocol/content_negotation/src/conneg_server_side.e @@ -0,0 +1,230 @@ +note + description: "Summary description for {CONNEG_SERVER_SIDE}. Utility class to support Server Side Content Negotiation " + date: "$Date$" + revision: "$Revision$" + description: "[ + Reference : http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.1 + Server-driven Negotiation : If the selection of the best representation for a response is made by an algorithm located at the server, + it is called server-driven negotiation. Selection is based on the available representations of the response (the dimensions over which it can vary; e.g. language, content-coding, etc.) + and the contents of particular header fields in the request message or on other information pertaining to the request (such as the network address of the client). + Server-driven negotiation is advantageous when the algorithm for selecting from among the available representations is difficult to describe to the user agent, + or when the server desires to send its "best guess" to the client along with the first response (hoping to avoid the round-trip delay of a subsequent request if the "best guess" is good enough for the user). + In order to improve the server's guess, the user agent MAY include request header fields (Accept, Accept-Language, Accept-Encoding, etc.) which describe its preferences for such a response. + ]" + EIS: "name=server driven negotiation", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12.", "protocol=uri" + +class + CONNEG_SERVER_SIDE + +inherit + + SHARED_CONNEG + + REFACTORING_HELPER + +create + make + +feature -- Initialization + + make (a_mime: READABLE_STRING_8; a_language: READABLE_STRING_8; a_charset: READABLE_STRING_8; a_encoding: READABLE_STRING_8) + do + set_mime_default (a_mime) + set_language_default (a_language) + set_charset_default (a_charset) + set_encoding_default (a_encoding) + ensure + mime_default_set: mime = a_mime + language_default_set: language_default = a_language + charset_default_set: charset_default = a_charset + encoding_default_set: encoding_default = a_encoding + end + +feature -- AccessServer Side Defaults Formats + + mime_default: READABLE_STRING_8 + -- Media type which is acceptable for the response. + + language_default: READABLE_STRING_8 + -- Natural language that is preferred as a response to the request. + + charset_default: READABLE_STRING_8 + -- Character set that is acceptable for the response. + + encoding_default: 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' + do + mime_default := a_mime + ensure + mime_default_set: a_mime = mime_default + end + + set_language_default (a_language: READABLE_STRING_8) + -- Set the language_default with `a_language' + do + language_default := a_language + ensure + language_default_set: a_language = language_default + end + + set_charset_default (a_charset: READABLE_STRING_8) + -- Set the charset_default with `a_charset' + do + charset_default := a_charset + ensure + charset_default_set: a_charset = charset_default + end + + set_encoding_default (a_encoding: READABLE_STRING_8) + do + encoding_default := a_encoding + ensure + encoding_default_set: a_encoding = encoding_default + 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 + -- `a_mime_types_supported' represent media types supported by the server. + -- `a_header represent' the Accept header, ie, the client preferences. + -- Return which media type to use for representation in a response, if the server supports + -- the requested media type, or empty in other case. + note + EIS: "name=media type", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1", "protocol=uri" + local + l_mime_match: READABLE_STRING_8 + do + create Result + 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) + else + -- select the best match, server support, client preferences + l_mime_match := mime.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_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 + -- `a_server_charset_supported' represent a list of character sets supported by the server. + -- `a_header' represents the Accept-Charset header, ie, the client preferences. + -- Return which Charset to use in a response, if the server supports + -- the requested Charset, or empty in other case. + note + EIS: "name=charset", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2", "protocol=uri" + local + l_charset_match: READABLE_STRING_8 + do + create Result + 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) + else + -- select the best match, server support, client preferences + l_charset_match := common.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_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 + -- `a_server_encoding_supported' represent a list of encoding supported by the server. + -- `a_header' represent the Accept-Encoding header, ie, the client preferences. + -- Return which Encoding to use in a response, if the server supports + -- the requested Encoding, or empty in other case. + note + EIS: "name=encoding", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3", "protocol=uri" + local + l_compression_match: READABLE_STRING_8 + do + create Result + if a_header = Void or else a_header.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) + else + -- select the best match, server support, client preferences + l_compression_match := common.best_match (a_server_encoding_supported, a_header) + 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_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 + -- `a_server_language_supported' represent a list of languages supported by the server. + -- `a_header' represent the Accept-Language header, ie, the client preferences. + -- Return which Language to use in a response, if the server supports + -- the requested Language, or empty in other case. + note + EIS: "name=language", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4", "protocol=uri" + + local + l_language_match: READABLE_STRING_8 + do + create Result + 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 (language_default) + else + -- select the best match, server support, client preferences + l_language_match := language.best_match (a_server_language_supported, a_header) + 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_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)" + +end diff --git a/library/network/protocol/CONNEG/src/common_accept_header_parser.e b/library/network/protocol/content_negotation/src/parsers/common_accept_header_parser.e similarity index 74% rename from library/network/protocol/CONNEG/src/common_accept_header_parser.e rename to library/network/protocol/content_negotation/src/parsers/common_accept_header_parser.e index f95e6751..9a8e983f 100644 --- a/library/network/protocol/CONNEG/src/common_accept_header_parser.e +++ b/library/network/protocol/content_negotation/src/parsers/common_accept_header_parser.e @@ -1,34 +1,39 @@ note - description: "COMMON_ACCEPT_HEADER_PARSER, this class allows to parse Accept-Charset and Accept-Encoding headers" - author: "" + description: "[ + COMMON_ACCEPT_HEADER_PARSER, this class allows to parse Accept-Charset and Accept-Encoding headers + + ]" date: "$Date$" revision: "$Revision$" - description : "[ - Charset Reference : http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2 - Encoding Reference : http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3 - ]" + EIS: "name=Charset", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2", "protocol=uri" + 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 + feature -- Parser - parse_common (header: STRING): COMMON_RESULTS + + parse_common (header: READABLE_STRING_8): COMMON_RESULTS -- Parses `header' charset/encoding into its component parts. -- For example, the charset 'iso-8889-5' would get parsed -- into: -- ('iso-8889-5', {'q':'1.0'}) local - l_parts: LIST [STRING] - sub_parts: LIST [STRING] - p: STRING + l_parts: LIST [READABLE_STRING_8] + sub_parts: LIST [READABLE_STRING_8] + p: READABLE_STRING_8 i: INTEGER - l_header: STRING + l_header: READABLE_STRING_8 do create Result.make l_parts := header.split (';') if l_parts.count = 1 then - Result.put ("1.0", "q") + Result.put ("1.0", "q") else from i := 1 @@ -38,17 +43,16 @@ feature -- Parser 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])) + Result.put (trim (sub_parts [2]), trim (sub_parts [1])) end i := i + 1 end end - l_header := trim (l_parts[1]) + l_header := trim (l_parts [1]) Result.set_field (trim (l_header)) end - - fitness_and_quality_parsed (a_field: STRING; parsed_charsets: LIST [COMMON_RESULTS]): FITNESS_AND_QUALITY + fitness_and_quality_parsed (a_field: READABLE_STRING_8; parsed_charsets: LIST [COMMON_RESULTS]): 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 @@ -60,12 +64,12 @@ feature -- Parser best_fit_q: REAL_64 target: COMMON_RESULTS range: COMMON_RESULTS - element: detachable STRING + element: detachable READABLE_STRING_8 l_fitness: INTEGER do best_fitness := -1 best_fit_q := 0.0 - target := parse_common(a_field) + target := parse_common (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 @@ -76,9 +80,7 @@ feature -- Parser else target_q := 1.0 end - - if attached target.field as l_target_field - then + if attached target.field as l_target_field then from parsed_charsets.start until @@ -86,7 +88,7 @@ feature -- Parser loop range := parsed_charsets.item_for_iteration if attached range.field as l_range_common then - if l_target_field.same_string (l_range_common) or l_target_field.same_string ("*") or l_range_common.same_string ("*") then + if l_target_field.same_string (l_range_common) or l_target_field.same_string ("*") or l_range_common.same_string ("*") then if l_range_common.same_string (l_target_field) then l_fitness := 100 else @@ -109,8 +111,7 @@ feature -- Parser create Result.make (best_fitness, best_fit_q) end - - quality_parsed (a_field: STRING; parsed_common: LIST [COMMON_RESULTS]): REAL_64 + quality_parsed (a_field: READABLE_STRING_8; parsed_common: LIST [COMMON_RESULTS]): 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 @@ -119,14 +120,13 @@ feature -- Parser Result := fitness_and_quality_parsed (a_field, parsed_common).quality end - - quality (a_field: STRING; commons: STRING): REAL_64 + 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 [STRING] - res : ARRAYED_LIST [COMMON_RESULTS] - p_res : COMMON_RESULTS + l_commons: LIST [READABLE_STRING_8] + res: ARRAYED_LIST [COMMON_RESULTS] + p_res: COMMON_RESULTS do l_commons := commons.split (',') from @@ -142,19 +142,17 @@ feature -- Parser Result := quality_parsed (a_field, res) end - best_match (supported: LIST [STRING]; header: STRING): STRING + 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 [STRING] + 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 @@ -164,9 +162,7 @@ feature -- Parser 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 @@ -201,12 +197,16 @@ feature -- Parser end weighted_matches.forth end - check weighted_matches.item = fitness_and_quality 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 + check + first_one > fitness_and_quality + end weighted_matches.remove end end @@ -228,14 +228,16 @@ feature -- Parser loop fitness_and_quality := weighted_matches.item if fitness_and_quality.mime_type.same_string (l_field) then - --| Found + --| Found else fitness_and_quality := Void weighted_matches.forth end end else - check has_field: False end + check + has_field: False + end end l_header_results.forth end @@ -250,33 +252,8 @@ feature -- Parser end end -feature -- Util - - mime_type (s: STRING): STRING - local - p: INTEGER - do - p := s.index_of (';', 1) - if p > 0 then - Result := trim (s.substring (1, p - 1)) - else - Result := trim (s.string) - end - end - - trim (a_string: STRING): STRING - -- trim whitespace from the beginning and end of a string - require - valid_argument : a_string /= Void - do - a_string.left_adjust - a_string.right_justify - Result := a_string - ensure - result_same_as_argument: a_string = Result - 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/CONNEG/src/fitness_and_quality.e b/library/network/protocol/content_negotation/src/parsers/fitness_and_quality.e similarity index 100% rename from library/network/protocol/CONNEG/src/fitness_and_quality.e rename to library/network/protocol/content_negotation/src/parsers/fitness_and_quality.e diff --git a/library/network/protocol/content_negotation/src/parsers/language_parse.e b/library/network/protocol/content_negotation/src/parsers/language_parse.e new file mode 100644 index 00000000..bbb39cb9 --- /dev/null +++ b/library/network/protocol/content_negotation/src/parsers/language_parse.e @@ -0,0 +1,312 @@ +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.put_left (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/CONNEG/src/mime_parse.e b/library/network/protocol/content_negotation/src/parsers/mime_parse.e similarity index 62% rename from library/network/protocol/CONNEG/src/mime_parse.e rename to library/network/protocol/content_negotation/src/parsers/mime_parse.e index 9d92ba36..5e9dd923 100644 --- a/library/network/protocol/CONNEG/src/mime_parse.e +++ b/library/network/protocol/content_negotation/src/parsers/mime_parse.e @@ -1,58 +1,45 @@ note - description: "Summary description for {MIME_PARSE}." - author: "" + description: "[ + {MIME_PARSE}. is encharge to parse Accept request-header field defined as follow: + + Accept = "Accept" ":" + #( media-range [ accept-params ] ) + media-range = ( "*/*" + | ( type "/" "*" ) + | ( type "/" subtype ) + ) *( ";" parameter ) + accept-params = ";" "q" "=" qvalue *( accept-extension ) + accept-extension = ";" token [ "=" ( token | quoted-string ) ] + + Example: + + Accept: text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c + ]" date: "$Date$" revision: "$Revision$" - description : "Accept Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1" + EIS: "name=Accept", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1", "protocol=uri" + class MIME_PARSE -inherit +inherit {NONE} + + MIME_TYPE_PARSER_UTILITIES + REFACTORING_HELPER feature -- Parser - parse_mime_type (a_mime_type: STRING): PARSE_RESULTS + 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'}) - local - l_parts: LIST [STRING] - p: STRING - sub_parts: LIST [STRING] - i: INTEGER - l_full_type: STRING - l_types: LIST [STRING] do - fixme ("Improve code!!!") - create Result.make - l_parts := a_mime_type.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 - --Java URLConnection class sends an Accept header that includes a - --single "*" - Turn it into a legal wildcard. - - l_full_type := trim (l_parts[1]) - if l_full_type.same_string ("*") then - l_full_type := "*/*" - end - l_types := l_full_type.split ('/') - Result.set_type (trim (l_types[1])) - Result.set_sub_type (trim (l_types[2])) + create Result.make_from_string (a_mime_type) end - parse_media_range (a_range: STRING): PARSE_RESULTS + parse_media_range (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'}) @@ -62,7 +49,7 @@ feature -- Parser do fixme ("Improve the code!!!") Result := parse_mime_type (a_range) - if attached Result.item ("q") as q then + if attached Result.parameter ("q") as q then if q.is_double and then attached {REAL_64} q.to_double as r and then @@ -71,38 +58,34 @@ feature -- Parser --| Keep current value if q.same_string ("1") then --| Use 1.0 formatting - Result.put ("1.0", "q") + Result.add_parameter ("q", "1.0") end else - Result.put ("1.0", "q") + Result.add_parameter ("q", "1.0") end else - Result.put ("1.0", "q") + Result.add_parameter ("q", "1.0") end end - fitness_and_quality_parsed (a_mime_type: STRING; parsed_ranges: LIST [PARSE_RESULTS]): FITNESS_AND_QUALITY + fitness_and_quality_parsed (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. Returns a - -- tuple of the fitness value and the value of the 'q' quality parameter of - -- the best match, or (-1, 0) if no match was found. Just as for - -- quality_parsed(), 'parsed_ranges' must be a list of parsed media ranges. + -- that have already been parsed by parse_media_range. local best_fitness: INTEGER target_q: REAL_64 best_fit_q: REAL_64 - target: PARSE_RESULTS - range: PARSE_RESULTS - keys: LIST [STRING] + target: HTTP_MEDIA_TYPE + range: HTTP_MEDIA_TYPE param_matches: INTEGER - element: detachable STRING + element: detachable READABLE_STRING_8 l_fitness: INTEGER do best_fitness := -1 best_fit_q := 0.0 target := parse_media_range (a_mime_type) - if attached target.item ("q") as q and then q.is_double then + if attached target.parameter ("q") as q and then q.is_double then target_q := q.to_double if target_q < 0.0 then target_q := 0.0 @@ -115,7 +98,7 @@ feature -- Parser if attached target.type as l_target_type and - attached target.sub_type as l_target_sub_type + attached target.subtype as l_target_sub_type then from parsed_ranges.start @@ -129,29 +112,29 @@ feature -- Parser (l_target_type.same_string (l_range_type) or l_range_type.same_string ("*") or l_target_type.same_string ("*")) ) and ( - attached range.sub_type as l_range_sub_type and then + attached range.subtype as l_range_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 - 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 + if attached target.parameters as l_keys then + from + param_matches := 0 + l_keys.start + until + l_keys.after + loop + element := l_keys.key_for_iteration + if + not element.same_string ("q") and then + range.has_parameter (element) and then + (attached target.parameter (element) as t_item and attached range.parameter (element) as r_item) and then + t_item.same_string (r_item) + then + param_matches := param_matches + 1 + end + l_keys.forth end - keys.forth end - if l_range_type.same_string (l_target_type) then l_fitness := 100 else @@ -166,7 +149,7 @@ feature -- Parser if l_fitness > best_fitness then best_fitness := l_fitness - element := range.item ("q") + element := range.parameter ("q") if element /= Void then best_fit_q := element.to_double.min (target_q) else @@ -180,23 +163,23 @@ feature -- Parser create Result.make (best_fitness, best_fit_q) end - quality_parsed (a_mime_type: STRING; parsed_ranges: LIST [PARSE_RESULTS]): REAL_64 + quality_parsed (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 parseMediaRange(). Returns the 'q' quality + -- 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 + -- 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 end - quality (a_mime_type: STRING; ranges: STRING): REAL_64 + 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 [STRING] - res : ARRAYED_LIST [PARSE_RESULTS] - p_res : PARSE_RESULTS + l_ranges : LIST [READABLE_STRING_8] + res : ARRAYED_LIST [HTTP_MEDIA_TYPE] + p_res : HTTP_MEDIA_TYPE do l_ranges := ranges.split (',') from @@ -212,18 +195,18 @@ feature -- Parser Result := quality_parsed (a_mime_type, res) end - best_match (supported: LIST [STRING]; header: STRING): STRING + 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 [PARSE_RESULTS] + l_header_results: LIST [HTTP_MEDIA_TYPE] weighted_matches: LIST [FITNESS_AND_QUALITY] - l_res: LIST [STRING] - p_res: PARSE_RESULTS + l_res: LIST [READABLE_STRING_8] + p_res: HTTP_MEDIA_TYPE fitness_and_quality, first_one: detachable FITNESS_AND_QUALITY - s: STRING + s: READABLE_STRING_8 do l_res := header.split (',') - create {ARRAYED_LIST [PARSE_RESULTS]} l_header_results.make (l_res.count) + create {ARRAYED_LIST [HTTP_MEDIA_TYPE]} l_header_results.make (l_res.count) fixme("Extract method!!!") from @@ -290,7 +273,7 @@ feature -- Parser until l_header_results.after or fitness_and_quality /= Void loop - s := l_header_results.item.mime_type + s := l_header_results.item.simple_type from weighted_matches.start until @@ -317,33 +300,7 @@ feature -- Parser end end -feature {NONE} -- Implementation - - mime_type (s: STRING): STRING - local - p: INTEGER - do - p := s.index_of (';', 1) - if p > 0 then - Result := trim (s.substring (1, p - 1)) - else - Result := trim (s.string) - end - end - - trim (a_string: STRING): STRING - -- trim whitespace from the beginning and end of a string - require - valid_argument : a_string /= Void - do - a_string.left_adjust - a_string.right_justify - Result := a_string - ensure - result_same_as_argument: a_string = Result - 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_negotation/src/parsers/mime_type_parser_utilities.e b/library/network/protocol/content_negotation/src/parsers/mime_type_parser_utilities.e new file mode 100644 index 00000000..7011a93b --- /dev/null +++ b/library/network/protocol/content_negotation/src/parsers/mime_type_parser_utilities.e @@ -0,0 +1,43 @@ +note + description: "{MIME_TYPE_PARSER_UTILITIES}." + date: "$Date$" + revision: "$Revision$" + +class + MIME_TYPE_PARSER_UTILITIES + +feature {NONE} -- Implementation + + mime_type (a_str: READABLE_STRING_8): READABLE_STRING_8 + -- `s' with any trailing parameters stripped + local + p: INTEGER + do + p := a_str.index_of (';', 1) + if p > 0 then + Result := trim (a_str.substring (1, p - 1)) + else + Result := trim (a_str.string) + end + end + + trim (a_string: READABLE_STRING_8): READABLE_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 + ensure + result_same_as_argument: Result.same_string_general (a_string) + 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/CONNEG/src/common_results.e b/library/network/protocol/content_negotation/src/results/common_results.e similarity index 90% rename from library/network/protocol/CONNEG/src/common_results.e rename to library/network/protocol/content_negotation/src/results/common_results.e index 5d71a733..fa77caee 100644 --- a/library/network/protocol/CONNEG/src/common_results.e +++ b/library/network/protocol/content_negotation/src/results/common_results.e @@ -1,12 +1,13 @@ note description: "Summary description for {COMMON_RESULTS}." - author: "" date: "$Date$" revision: "$Revision$" class COMMON_RESULTS + inherit + ANY redefine out @@ -31,7 +32,6 @@ feature -- Access field: detachable STRING - item (a_key: STRING): detachable STRING -- Item associated with `a_key', if present -- otherwise default value of type `STRING' @@ -57,15 +57,14 @@ feature -- Access feature -- Element change set_field (a_field: STRING) - -- Set type with `a_charset' + -- Set type with `a_charset' do field := a_field ensure - field_assigned: field ~ field + field_set: attached field as l_field implies l_field = a_field end - - put (new: STRING; key: STRING) + 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' @@ -90,7 +89,6 @@ feature -- Status Report Result.append_string ("'" + t + "',") end Result.append_string (" {") - from params.start until @@ -113,7 +111,10 @@ feature {NONE} -- Implementation params: HASH_TABLE [STRING, STRING] --dictionary of all the parameters for the media range -;note - copyright: "2011-2011, Javier Velilla, Jocelyn Fiat and others" + ; + +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/CONNEG/src/language_results.e b/library/network/protocol/content_negotation/src/results/language_results.e similarity index 93% rename from library/network/protocol/CONNEG/src/language_results.e rename to library/network/protocol/content_negotation/src/results/language_results.e index fe8d0aa0..37e11244 100644 --- a/library/network/protocol/CONNEG/src/language_results.e +++ b/library/network/protocol/content_negotation/src/results/language_results.e @@ -1,12 +1,13 @@ note description: "Summary description for {LANGUAGE_RESULTS}." - author: "" date: "$Date$" revision: "$Revision$" class LANGUAGE_RESULTS + inherit + ANY redefine out @@ -61,7 +62,7 @@ feature -- Access feature -- Element change set_type (a_type: STRING) - -- Set type with `a_type' + -- Set type with `a_type' do type := a_type if attached sub_type as st then @@ -74,7 +75,7 @@ feature -- Element change end set_sub_type (a_sub_type: STRING) - -- Set sub_type with `a_sub_type + -- Set sub_type with `a_sub_type do sub_type := a_sub_type if attached type as t then @@ -86,7 +87,7 @@ feature -- Element change sub_type_assigned: sub_type ~ a_sub_type end - put (new: STRING; key: STRING) + 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' @@ -114,7 +115,6 @@ feature -- Status Report Result.append_string (" '" + st + "',") end Result.append_string (" {") - from params.start until @@ -137,7 +137,10 @@ feature {NONE} -- Implementation params: HASH_TABLE [STRING, STRING] --dictionary of all the parameters for the media range -;note - copyright: "2011-2011, Javier Velilla, Jocelyn Fiat and others" + ; + +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/CONNEG/src/parse_results.e b/library/network/protocol/content_negotation/src/results/parse_results.e similarity index 93% rename from library/network/protocol/CONNEG/src/parse_results.e rename to library/network/protocol/content_negotation/src/results/parse_results.e index 185995ea..9fee2bb5 100644 --- a/library/network/protocol/CONNEG/src/parse_results.e +++ b/library/network/protocol/content_negotation/src/results/parse_results.e @@ -1,6 +1,5 @@ note description: "Summary description for {PARSE_RESULTS}." - author: "" date: "$Date$" revision: "$Revision$" @@ -8,6 +7,7 @@ class PARSE_RESULTS inherit + ANY redefine out @@ -62,7 +62,7 @@ feature -- Access feature -- Element change set_type (a_type: STRING) - -- Set type with `a_type' + -- Set type with `a_type' do type := a_type if attached sub_type as st then @@ -75,7 +75,7 @@ feature -- Element change end set_sub_type (a_sub_type: STRING) - -- Set sub_type with `a_sub_type + -- Set sub_type with `a_sub_type do sub_type := a_sub_type if attached type as t then @@ -87,7 +87,7 @@ feature -- Element change sub_type_assigned: sub_type ~ a_sub_type end - put (new: STRING; key: STRING) + 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' @@ -115,7 +115,6 @@ feature -- Status Report Result.append_string (" '" + st + "',") end Result.append_string (" {") - from params.start until @@ -138,7 +137,10 @@ feature {NONE} -- Implementation params: HASH_TABLE [STRING, STRING] --dictionary of all the parameters for the media range -;note - copyright: "2011-2011, Javier Velilla, Jocelyn Fiat and others" + ; + +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/CONNEG/src/shared_conneg.e b/library/network/protocol/content_negotation/src/shared_conneg.e similarity index 51% rename from library/network/protocol/CONNEG/src/shared_conneg.e rename to library/network/protocol/content_negotation/src/shared_conneg.e index ffa6a47f..08c8d174 100644 --- a/library/network/protocol/CONNEG/src/shared_conneg.e +++ b/library/network/protocol/content_negotation/src/shared_conneg.e @@ -1,5 +1,5 @@ note - description: "Summary description for {SHARED_MIME}." + description: "Summary description for {SHARED_CONNEG}." date: "$Date$" revision: "$Revision$" @@ -8,23 +8,24 @@ class feature - mime: MIME_PARSE + Mime: MIME_PARSE once create Result end - common: COMMON_ACCEPT_HEADER_PARSER - -- Charset and Encoding + Common: COMMON_ACCEPT_HEADER_PARSER + -- Charset and Encoding once create Result end - language: LANGUAGE_PARSE + Language: LANGUAGE_PARSE once create Result 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_negotation/src/variants/character_encoding_variant_results.e b/library/network/protocol/content_negotation/src/variants/character_encoding_variant_results.e new file mode 100644 index 00000000..c627332c --- /dev/null +++ b/library/network/protocol/content_negotation/src/variants/character_encoding_variant_results.e @@ -0,0 +1,33 @@ +note + description: "[ + {CHARACTER_ENCODING_VARIANT_RESULTS} + 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. + ]" + + date: "$Date$" + revision: "$Revision$" + +class + CHARACTER_ENCODING_VARIANT_RESULTS + +inherit + + VARIANT_RESULTS + + +feature -- Change Element + + + set_variant_header + -- Set variant header as `Accept-Charset' + do + variant_header := "Accept-Charset" + 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_negotation/src/variants/compression_variant_results.e b/library/network/protocol/content_negotation/src/variants/compression_variant_results.e new file mode 100644 index 00000000..9cc0f7ca --- /dev/null +++ b/library/network/protocol/content_negotation/src/variants/compression_variant_results.e @@ -0,0 +1,32 @@ +note + description: "[ + {COMPRESSION_VARIANT_RESULTS} + Represent the compression results between client preferences and ccompression 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 + ]" + 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 + +inherit + + VARIANT_RESULTS + + +feature -- Change Element + + set_variant_header + -- Set variant_header as `Accept-Encoding' + do + variant_header := "Accept-Encoding" + 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_negotation/src/variants/language_variant_results.e b/library/network/protocol/content_negotation/src/variants/language_variant_results.e new file mode 100644 index 00000000..178d718c --- /dev/null +++ b/library/network/protocol/content_negotation/src/variants/language_variant_results.e @@ -0,0 +1,33 @@ +note + description: "[ + {LANGUAGE_VARIANT_RESULTS}. + 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 + ]" + date: "$Date$" + revision: "$Revision$" + +class + LANGUAGE_VARIANT_RESULTS + +inherit + + VARIANT_RESULTS + + +feature -- Change Element + + + set_variant_header + -- Set variant header as 'Accept-Language' + do + variant_header := "Accept-Language" + 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_negotation/src/variants/media_type_variant_results.e b/library/network/protocol/content_negotation/src/variants/media_type_variant_results.e new file mode 100644 index 00000000..27f46baa --- /dev/null +++ b/library/network/protocol/content_negotation/src/variants/media_type_variant_results.e @@ -0,0 +1,32 @@ +note + description: "[ + {MEDIA_TYPE_VARIANT_RESULTS}. + Represent 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 + ]" + date: "$Date$" + revision: "$Revision$" + +class + MEDIA_TYPE_VARIANT_RESULTS + +inherit + + VARIANT_RESULTS + + +feature -- Change Element + + set_variant_header + -- Set variant header as `Accept' + do + variant_header := "Accept" + 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_negotation/src/variants/variant_results.e b/library/network/protocol/content_negotation/src/variants/variant_results.e new file mode 100644 index 00000000..60467cc2 --- /dev/null +++ b/library/network/protocol/content_negotation/src/variants/variant_results.e @@ -0,0 +1,83 @@ +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 + -- the type could be: media type, language, chracter_sets and 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:= <<"Accept","Accept-Language","Accept-Encoding","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/CONNEG/test/application.e b/library/network/protocol/content_negotation/test/application.e similarity index 92% rename from library/network/protocol/CONNEG/test/application.e rename to library/network/protocol/content_negotation/test/application.e index 2c16ebe1..a7078001 100644 --- a/library/network/protocol/CONNEG/test/application.e +++ b/library/network/protocol/content_negotation/test/application.e @@ -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_media_range ("da").out) - print ("%N"+language.parse_media_range ("en-gb;q=0.8").out) - print ("%N"+language.parse_media_range ("en;q=0.7").out) - print ("%N"+language.parse_media_range ("en-*").out) + 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) end end diff --git a/library/network/protocol/CONNEG/test/common_accept_header_parser_test.e b/library/network/protocol/content_negotation/test/common_accept_header_parser_test.e similarity index 100% rename from library/network/protocol/CONNEG/test/common_accept_header_parser_test.e rename to library/network/protocol/content_negotation/test/common_accept_header_parser_test.e diff --git a/library/network/protocol/CONNEG/test/conneg_server_side_test.e b/library/network/protocol/content_negotation/test/conneg_server_side_test.e similarity index 89% rename from library/network/protocol/CONNEG/test/conneg_server_side_test.e rename to library/network/protocol/content_negotation/test/conneg_server_side_test.e index e9d181f4..e53d28c9 100644 --- a/library/network/protocol/CONNEG/test/conneg_server_side_test.e +++ b/library/network/protocol/content_negotation/test/conneg_server_side_test.e @@ -36,13 +36,13 @@ feature -- Test routines assert ("Same Value at 1",mime_types_supported.at (1).is_equal (media_variants.supported_variants.at (1))) assert ("Same count",mime_types_supported.count = media_variants.supported_variants.count) assert ("Variant header is void",media_variants.variant_header = Void) - assert ("Media type is void",media_variants.media_type = Void) + assert ("Media type is void",media_variants.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 defaul", conneg.mime_default.is_equal (media_variants.media_type)) + assert ("Mime is defaul", conneg.mime_default.is_equal (media_variants.type)) assert ("Variant header", media_variants.variant_header = Void) --Scenario 3, the server select the best match, and set the vary header @@ -50,7 +50,7 @@ feature -- Test routines assert ("Expected Acceptable", media_variants.is_acceptable) assert ("Variants is dettached",media_variants.supported_variants = Void) assert ("Variant Header", media_variants.variant_header.is_equal ("Accept")) - assert ("Media Type is application/json", media_variants.media_type.is_equal ("application/json")) + assert ("Media Type is application/json", media_variants.type.is_equal ("application/json")) end @@ -70,14 +70,14 @@ feature -- Test routines assert ("Same Value at 1",charset_supported.at (1).is_equal (charset_variants.supported_variants.at (1))) assert ("Same count",charset_supported.count = charset_variants.supported_variants.count) assert ("Variant header is void",charset_variants.variant_header = Void) - assert ("Character type is void",charset_variants.character_type = Void) + assert ("Character type is void",charset_variants.type = 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", conneg.charset_default.is_equal (charset_variants.character_type)) + assert ("Charset is defaul", conneg.charset_default.is_equal (charset_variants.type)) assert ("Variant header", charset_variants.variant_header = Void) @@ -86,7 +86,7 @@ feature -- Test routines assert ("Expected Acceptable", charset_variants.is_acceptable) assert ("Variants is dettached",charset_variants.supported_variants = Void) assert ("Variant Header", charset_variants.variant_header.is_equal ("Accept-Charset")) - assert ("Character Type is iso-8859-5", charset_variants.character_type.is_equal ("iso-8859-5")) + assert ("Character Type is iso-8859-5", charset_variants.type.is_equal ("iso-8859-5")) end test_compression_negotiation @@ -103,26 +103,26 @@ feature -- Test routines assert ("Same Value at 1",compression_supported.at (1).is_equal (compression_variants.supported_variants.at (1))) assert ("Same count",compression_supported.count = compression_variants.supported_variants.count) assert ("Variant header is void",compression_variants.variant_header = Void) - assert ("Compression type is void",compression_variants.compression_type = Void) + assert ("Compression type is void",compression_variants.type = 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", conneg.encoding_default.is_equal (compression_variants.compression_type)) + assert ("Compression is defaul", conneg.encoding_default.is_equal (compression_variants.type)) assert ("Variant header", compression_variants.variant_header = 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_defautl ("gzip") + conneg.set_encoding_default("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", compression_variants.variant_header.is_equal ("Accept-Encoding")) - assert ("Encoding Type is gzip", compression_variants.compression_type.is_equal ("gzip")) + assert ("Encoding Type is gzip", compression_variants.type.is_equal ("gzip")) end @@ -141,14 +141,14 @@ feature -- Test routines assert ("Same Value at 1",languages_supported.at (1).is_equal (language_variants.supported_variants.at (1))) assert ("Same count",languages_supported.count = language_variants.supported_variants.count) assert ("Variant header is void",language_variants.variant_header = Void) - assert ("Language type is void",language_variants.language_type = Void) + assert ("Language type is void",language_variants.type = Void) -- 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 defaul", conneg.language_default.is_equal (language_variants.language_type)) + assert ("Language is defaul", conneg.language_default.is_equal (language_variants.type)) assert ("Variant header", language_variants.variant_header = Void) @@ -157,7 +157,7 @@ feature -- Test routines assert ("Expected Acceptable", language_variants.is_acceptable) assert ("Variants is dettached",language_variants.supported_variants = Void) assert ("Variant Header", language_variants.variant_header.is_equal ("Accept-Language")) - assert ("Language Type is fr", language_variants.language_type.is_equal ("fr")) + assert ("Language Type is fr", language_variants.type.is_equal ("fr")) end diff --git a/library/network/protocol/CONNEG/test/language_parser_test.e b/library/network/protocol/content_negotation/test/language_parser_test.e similarity index 87% rename from library/network/protocol/CONNEG/test/language_parser_test.e rename to library/network/protocol/content_negotation/test/language_parser_test.e index bac690bc..a7911f5d 100644 --- a/library/network/protocol/CONNEG/test/language_parser_test.e +++ b/library/network/protocol/content_negotation/test/language_parser_test.e @@ -25,10 +25,10 @@ feature -- Test routines test_parse_media_range do - assert ("Expected ('da', {'q':'1.0',})", parser.parse_media_range ("da").out.same_string ("('da', {'q':'1.0',})")); - assert ("Expected ('en', 'gb', {'q':'0.8',})", parser.parse_media_range ("en-gb;q=0.8").out.same_string ("('en', 'gb', {'q':'0.8',})")); - assert ("Expected ('en', {'q':'0.7',})", parser.parse_media_range ("en;q=0.7").out.same_string ("('en', {'q':'0.7',})")); - assert ("Expected ('en', '*', {'q':'1.0',})", parser.parse_media_range ("en-*").out.same_string ("('en', '*', {'q':'1.0',})")); + assert ("Expected ('da', {'q':'1.0',})", parser.parse_language_range ("da").out.same_string ("('da', {'q':'1.0',})")); + assert ("Expected ('en', 'gb', {'q':'0.8',})", parser.parse_language_range ("en-gb;q=0.8").out.same_string ("('en', 'gb', {'q':'0.8',})")); + assert ("Expected ('en', {'q':'0.7',})", parser.parse_language_range ("en;q=0.7").out.same_string ("('en', {'q':'0.7',})")); + assert ("Expected ('en', '*', {'q':'1.0',})", parser.parse_language_range ("en-*").out.same_string ("('en', '*', {'q':'1.0',})")); end diff --git a/library/network/protocol/CONNEG/test/mime_parser_test.e b/library/network/protocol/content_negotation/test/mime_parser_test.e similarity index 75% rename from library/network/protocol/CONNEG/test/mime_parser_test.e rename to library/network/protocol/content_negotation/test/mime_parser_test.e index ef6de97f..a63b8505 100644 --- a/library/network/protocol/CONNEG/test/mime_parser_test.e +++ b/library/network/protocol/content_negotation/test/mime_parser_test.e @@ -24,19 +24,45 @@ feature {NONE} -- Events create parser end +feature -- Helper + + format (a_mediatype: HTTP_MEDIA_TYPE): STRING + -- Representation of the current object + do + create Result.make_from_string ("(") + if attached a_mediatype.type as t then + Result.append_string ("'" + t + "',") + end + if attached a_mediatype.subtype as st then + Result.append_string (" '" + st + "',") + end + Result.append_string (" {") + if attached a_mediatype.parameters as l_params then + from + l_params.start + until + l_params.after + loop + Result.append ("'" + l_params.key_for_iteration + "':'" + l_params.item_for_iteration + "',"); + l_params.forth + end + end + Result.append ("})") + end + feature -- Test routines test_parse_media_range do - assert ("Expected ('application', 'xml', {'q':'1',})", parser.parse_media_range("application/xml;q=1").out.same_string("('application', 'xml', {'q':'1.0',})") ) + 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',})", parser.parse_media_range("application/xml").out.same_string("('application', 'xml', {'q':'1.0',})") ) - assert ("Expected ('application', 'xml', {'q':'1',})", parser.parse_media_range("application/xml;q=").out.same_string("('application', 'xml', {'q':'1.0',})") ) - assert ("Expected ('application', 'xml', {'q':'1',})", parser.parse_media_range("application/xml ; q=").out.same_string("('application', 'xml', {'q':'1.0',})") ) - assert ("Expected ('application', 'xml', {'q':'1','b':'other',})", parser.parse_media_range("application/xml ; q=1;b=other").out.same_string("('application', 'xml', {'q':'1.0','b':'other',})") ) - assert ("Expected ('application', 'xml', {'q':'1','b':'other',})", parser.parse_media_range("application/xml ; q=2;b=other").out.same_string("('application', 'xml', {'q':'1.0','b':'other',})") ) + 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',})") ) -- Accept header that includes * - assert ("Expected ('*', '*', {'q':'.2',})", parser.parse_media_range(" *; q=.2").out.same_string("('*', '*', {'q':'.2',})")) + assert ("Expected ('*', '*', {'q':'.2',})", format (parser.parse_media_range(" *; q=.2")).same_string("('*', '*', {'q':'.2',})")) end diff --git a/library/network/protocol/CONNEG/test/test-safe.ecf b/library/network/protocol/content_negotation/test/test-safe.ecf similarity index 93% rename from library/network/protocol/CONNEG/test/test-safe.ecf rename to library/network/protocol/content_negotation/test/test-safe.ecf index 9fb46bd4..18eb204d 100644 --- a/library/network/protocol/CONNEG/test/test-safe.ecf +++ b/library/network/protocol/content_negotation/test/test-safe.ecf @@ -12,6 +12,7 @@ + diff --git a/library/network/protocol/CONNEG/test/test.ecf b/library/network/protocol/content_negotation/test/test.ecf similarity index 93% rename from library/network/protocol/CONNEG/test/test.ecf rename to library/network/protocol/content_negotation/test/test.ecf index 88d3dec7..6da3deb1 100644 --- a/library/network/protocol/CONNEG/test/test.ecf +++ b/library/network/protocol/content_negotation/test/test.ecf @@ -12,6 +12,7 @@ + diff --git a/library/network/protocol/http/src/http_media_type.e b/library/network/protocol/http/src/http_media_type.e index 2addad59..fbe67cb2 100644 --- a/library/network/protocol/http/src/http_media_type.e +++ b/library/network/protocol/http/src/http_media_type.e @@ -100,13 +100,11 @@ feature {NONE} -- Initialization t.right_adjust type := t if t.same_string ("*") then - -- Flexible parser allowing "*" even if this is not really a valid media-type - -- let's interpret it as "*/*" - subtype := "*" + --| Accept *; should be */* else has_error := True - subtype := "*" end + subtype := "*" else subtype := t.substring (p + 1, t.count) type := t diff --git a/tools/bin/ecf_updater.exe b/tools/bin/ecf_updater.exe deleted file mode 100644 index e4e515cf..00000000 Binary files a/tools/bin/ecf_updater.exe and /dev/null differ