From 0ef88eadf5feeccdca5099fa35b90d603edc101b Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 22 Jul 2011 16:57:50 +0200 Subject: [PATCH] Improvement and revert back to support draft 04 (but using custom variable, allow the user to follow draft 05 spec) --- .../src/draft_05/uri_template_constants.e | 52 ++ .../protocol/uri_template/src/uri_template.e | 118 ++-- .../uri_template/src/uri_template_constants.e | 52 ++ .../src/uri_template_expression.e | 93 ++- .../src/uri_template_expression_variable.e | 228 ++++--- .../test_uri_template-draft_05.ecf | 28 + .../draft_50/test_uri_template_draft_05.e | 632 ++++++++++++++++++ .../uri_template/tests/test_uri_template.e | 178 ++--- .../uri_template/uri_template-safe.ecf | 18 +- .../protocol/uri_template/uri_template.ecf | 37 +- 10 files changed, 1128 insertions(+), 308 deletions(-) create mode 100644 library/protocol/uri_template/src/draft_05/uri_template_constants.e create mode 100644 library/protocol/uri_template/src/uri_template_constants.e create mode 100644 library/protocol/uri_template/test_uri_template-draft_05.ecf create mode 100644 library/protocol/uri_template/tests/draft_50/test_uri_template_draft_05.e diff --git a/library/protocol/uri_template/src/draft_05/uri_template_constants.e b/library/protocol/uri_template/src/draft_05/uri_template_constants.e new file mode 100644 index 00000000..6fc51bc2 --- /dev/null +++ b/library/protocol/uri_template/src/draft_05/uri_template_constants.e @@ -0,0 +1,52 @@ +note + description: "[ + Summary description for {URI_TEMPLATE_CONSTANTS}. + + see http://tools.ietf.org/html/draft-gregorio-uritemplate-05 + ]" + author: "" + date: "$Date$" + revision: "$Revision$" + +class + URI_TEMPLATE_CONSTANTS + +feature -- Operator + + Reserved_operator: CHARACTER = '+' + + Form_style_query_operator: CHARACTER = '?' + + Path_style_parameters_operator: CHARACTER = ';' + + Path_segment_operator: CHARACTER = '/' + + Label_operator: CHARACTER = '.' + +feature -- Separator + + Default_delimiter: CHARACTER = '|' --| Draft 05 + +feature -- Explode + + Explode_plus: CHARACTER = '+' + + Explode_star: CHARACTER = '*' + +feature -- Modified + + Modifier_substring: CHARACTER = ':' + + Modifier_remainder: CHARACTER = '^' + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/protocol/uri_template/src/uri_template.e b/library/protocol/uri_template/src/uri_template.e index 96e65268..a07428b3 100644 --- a/library/protocol/uri_template/src/uri_template.e +++ b/library/protocol/uri_template/src/uri_template.e @@ -2,7 +2,9 @@ note description: "[ Summary description for {URI_TEMPLATE}. - See http://tools.ietf.org/html/draft-gregorio-uritemplate-05 + See http://tools.ietf.org/html/draft-gregorio-uritemplate-04 + + note for draft 05, check {URI_TEMPLATE_CONSTANTS}.Default_delimiter ]" legal: "See notice at end of class." @@ -52,17 +54,18 @@ feature -- Access feature -- Structures variable_names: LIST [STRING] + -- All variable names do - analyze (Void) - if attached expansion_parts as l_x_parts then - create {ARRAYED_LIST [STRING]} Result.make (l_x_parts.count) + analyze + if attached expressions as l_expressions then + create {ARRAYED_LIST [STRING]} Result.make (l_expressions.count) from - l_x_parts.start + l_expressions.start until - l_x_parts.after + l_expressions.after loop - Result.append (l_x_parts.item.variable_names) - l_x_parts.forth + Result.append (l_expressions.item.variable_names) + l_expressions.forth end else create {ARRAYED_LIST [STRING]} Result.make (0) @@ -70,19 +73,20 @@ feature -- Structures end path_variable_names: LIST [STRING] + -- All variable names part of the path do - analyze (Void) - if attached expansion_parts as l_x_parts then - create {ARRAYED_LIST [STRING]} Result.make (l_x_parts.count) + analyze + if attached expressions as l_expressions then + create {ARRAYED_LIST [STRING]} Result.make (l_expressions.count) from - l_x_parts.start + l_expressions.start until - l_x_parts.after + l_expressions.after loop - if not l_x_parts.item.is_query then - Result.append (l_x_parts.item.variable_names) + if not l_expressions.item.is_query then + Result.append (l_expressions.item.variable_names) end - l_x_parts.forth + l_expressions.forth end else create {ARRAYED_LIST [STRING]} Result.make (0) @@ -90,19 +94,20 @@ feature -- Structures end query_variable_names: LIST [STRING] + -- All variable names part of the query (i.e after '?') do - analyze (Void) - if attached expansion_parts as l_x_parts then - create {ARRAYED_LIST [STRING]} Result.make (l_x_parts.count) + analyze + if attached expressions as l_expressions then + create {ARRAYED_LIST [STRING]} Result.make (l_expressions.count) from - l_x_parts.start + l_expressions.start until - l_x_parts.after + l_expressions.after loop - if l_x_parts.item.is_query then - Result.append (l_x_parts.item.variable_names) + if l_expressions.item.is_query then + Result.append (l_expressions.item.variable_names) end - l_x_parts.forth + l_expressions.forth end else create {ARRAYED_LIST [STRING]} Result.make (0) @@ -111,33 +116,33 @@ feature -- Structures feature -- Builder - string (a_ht: HASH_TABLE [detachable ANY, STRING]): STRING + expanded_string (a_ht: HASH_TABLE [detachable ANY, STRING]): STRING -- Expanded template using variable from `a_ht' local tpl: like template exp: URI_TEMPLATE_EXPRESSION p,q: INTEGER do - analyze (Void) + analyze tpl := template - if attached expansion_parts as l_x_parts then + if attached expressions as l_expressions then create Result.make (tpl.count) from - l_x_parts.start + l_expressions.start p := 1 until - l_x_parts.after + l_expressions.after loop - q := l_x_parts.item.position + q := l_expressions.item.position --| Added inter variable text Result.append (tpl.substring (p, q - 1)) --| Expand variables ... - exp := l_x_parts.item - exp.append_to_string (a_ht, Result) + exp := l_expressions.item + exp.append_expanded_to_string (a_ht, Result) - p := q + l_x_parts.item.expression.count + 2 + p := q + l_expressions.item.expression.count + 2 - l_x_parts.forth + l_expressions.forth end Result.append (tpl.substring (p, tpl.count)) else @@ -160,33 +165,37 @@ feature -- Match l_uri_count: INTEGER do --| Extract expansion parts "\\{([^\\}]*)\\}" - analyze (Void) - if attached expansion_parts as l_x_parts then - create l_path_vars.make (l_x_parts.count) - create l_query_vars.make (l_x_parts.count) + analyze + if attached expressions as l_expressions then + create l_path_vars.make (l_expressions.count) + create l_query_vars.make (l_expressions.count) l_vars := l_path_vars b := True l_uri_count := a_uri.count tpl := template - if l_x_parts.is_empty then + if l_expressions.is_empty then b := a_uri.substring (1, tpl.count).same_string (tpl) else from - l_x_parts.start + l_expressions.start p := 1 l_offset := 0 until - l_x_parts.after or not b + l_expressions.after or not b loop - exp := l_x_parts.item + exp := l_expressions.item vn := exp.expression q := exp.position --| Check text between vars + --| FIXME jfiat [2011/07/22] : check this ... + --| There should be at least one literal between two expression + --| {var}{foobar} is ambigous for matching ... + b := False if q > p then t := tpl.substring (p, q - 1) s := a_uri.substring (p + l_offset, q + l_offset - 1) b := s.same_string (t) - p := q + vn.count + 2 + p := exp.end_position end --| Check related variable if b and then not vn.is_empty then @@ -210,7 +219,7 @@ feature -- Match b := exp.is_query --| query are optional end end - l_x_parts.forth + l_expressions.forth end end if b then @@ -221,14 +230,14 @@ feature -- Match feature {NONE} -- Internal Access - expansion_parts: detachable LIST [URI_TEMPLATE_EXPRESSION] + expressions: detachable LIST [URI_TEMPLATE_EXPRESSION] -- Expansion parts feature {NONE} -- Implementation - analyze (a_handler: detachable URI_TEMPLATE_HANDLER) + analyze local - l_x_parts: like expansion_parts + l_expressions: like expressions c: CHARACTER i,p,n: INTEGER tpl: like template @@ -237,12 +246,12 @@ feature {NONE} -- Implementation x: STRING exp: URI_TEMPLATE_EXPRESSION do - l_x_parts := expansion_parts - if l_x_parts = Void then + l_expressions := expressions + if l_expressions = Void then tpl := template --| Extract expansion parts "\\{([^\\}]*)\\}" - create {ARRAYED_LIST [like expansion_parts.item]} l_x_parts.make (tpl.occurrences ('{')) + create {ARRAYED_LIST [like expressions.item]} l_expressions.make (tpl.occurrences ('{')) from i := 1 n := tpl.count @@ -254,7 +263,7 @@ feature {NONE} -- Implementation if in_x then if c = '}' then create exp.make (p, x.twin, in_query) - l_x_parts.force (exp) + l_expressions.force (exp) x.wipe_out in_x := False else @@ -276,7 +285,7 @@ feature {NONE} -- Implementation end i := i + 1 end - expansion_parts := l_x_parts + expressions := l_expressions end end @@ -355,11 +364,6 @@ feature {NONE} -- Implementation Result := a_uri.substring (a_index, p) end - url_encoder: URL_ENCODER - once - create Result - end - note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/protocol/uri_template/src/uri_template_constants.e b/library/protocol/uri_template/src/uri_template_constants.e new file mode 100644 index 00000000..eb66ad3e --- /dev/null +++ b/library/protocol/uri_template/src/uri_template_constants.e @@ -0,0 +1,52 @@ +note + description: "[ + Summary description for {URI_TEMPLATE_CONSTANTS}. + + see http://tools.ietf.org/html/draft-gregorio-uritemplate-04 + ]" + author: "" + date: "$Date$" + revision: "$Revision$" + +class + URI_TEMPLATE_CONSTANTS + +feature -- Operator + + Reserved_operator: CHARACTER = '+' + + Form_style_query_operator: CHARACTER = '?' + + Path_style_parameters_operator: CHARACTER = ';' + + Path_segment_operator: CHARACTER = '/' + + Label_operator: CHARACTER = '.' + +feature -- Separator + + Default_delimiter: CHARACTER = '=' --| Draft 0.4 , change to '|' for Draft 0.5 + +feature -- Explode + + Explode_plus: CHARACTER = '+' + + Explode_star: CHARACTER = '*' + +feature -- Modified + + Modifier_substring: CHARACTER = ':' + + Modifier_remainder: CHARACTER = '^' + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/protocol/uri_template/src/uri_template_expression.e b/library/protocol/uri_template/src/uri_template_expression.e index 298a53c5..5b65c638 100644 --- a/library/protocol/uri_template/src/uri_template_expression.e +++ b/library/protocol/uri_template/src/uri_template_expression.e @@ -8,8 +8,13 @@ class URI_TEMPLATE_EXPRESSION inherit + ANY + DEBUG_OUTPUT + URI_TEMPLATE_CONSTANTS + export {NONE} all end + create make @@ -42,22 +47,27 @@ feature -- Processing op_prefix := '%U' op_delimiter := ',' inspect exp[1] - when '+' then + when Reserved_operator then + --| '+' reserved := True operator := '+' - when '.' then + when Label_operator then + --| '.' operator := '.' op_prefix := '.' op_delimiter := '.' - when '/' then + when Path_segment_operator then + --| '/' operator := '/' op_prefix := '/' op_delimiter := '/' - when ';' then + when Path_style_parameters_operator then + --| ';' operator := ';' op_prefix := ';' op_delimiter := ';' - when '?' then + when Form_style_query_operator then + --| '?' operator := '?' op_prefix := '?' op_delimiter := '&' @@ -81,7 +91,7 @@ feature -- Processing loop s := lst.item vmodifier := Void - p := s.index_of ('|', 1) + p := s.index_of (Default_delimiter, 1) if p > 0 then vn := s.substring (1, p - 1) s := s.substring (p + 1, s.count) @@ -97,7 +107,7 @@ feature -- Processing i > n loop inspect vn[i] - when '*', '+', ':', '^' then + when Explode_plus, Explode_star, Modifier_substring, Modifier_remainder then vmodifier := vn.substring (i, n) vn := vn.substring (1, i - 1) i := n + 1 --| exit @@ -105,7 +115,7 @@ feature -- Processing i := i + 1 end end - vars.force (create {URI_TEMPLATE_EXPRESSION_VARIABLE}.make (operator, vn, s, vmodifier)) + vars.force (create {URI_TEMPLATE_EXPRESSION_VARIABLE}.make (Current, vn, s, vmodifier)) lst.forth end variables := vars @@ -117,32 +127,39 @@ feature -- Processing feature -- Access position: INTEGER + -- Character position on Current in the template + + end_position: INTEGER + do + Result := position + expression.count + 2 --| '{' + `expression' + '}' + end expression: STRING + -- Operator? + VariableName + modifier is_query: BOOLEAN + -- Is in the query part (i.e: after '?' ?) feature -- Status operator: CHARACTER - - has_operator: BOOLEAN - do - Result := operator /= '%U' - end + -- First character of `expression' if among reserved: BOOLEAN - - has_op_prefix: BOOLEAN - do - Result := op_prefix /= '%U' - end + -- Is reserved + -- i.e: do not url-encode the reserved character op_prefix: CHARACTER + -- When expanding list of table, first character to use + --| ex: '?' for {?var} op_delimiter: CHARACTER + -- When expanding list of table, delimiter character to use + --| ex: ',' for {?var} variables: detachable LIST [URI_TEMPLATE_EXPRESSION_VARIABLE] + -- List of variables declared in `expression' + --| ex: "foo", "bar" for {?foo,bar} variable_names: LIST [STRING] do @@ -168,46 +185,16 @@ feature -- Status report feature -- Report - append_to_string (a_ht: HASH_TABLE [detachable ANY, STRING]; a_buffer: STRING) + append_expanded_to_string (a_ht: HASH_TABLE [detachable ANY, STRING]; a_buffer: STRING) do analyze if attached variables as vars then append_custom_variables_to_string (a_ht, vars, op_prefix, op_delimiter, True, a_buffer) --- inspect operator --- when '?' then --- append_custom_variables_to_string (a_ht, vars, '?', '&', True, a_buffer) --- when ';' then --- append_custom_variables_to_string (a_ht, vars, ';', ';', False, a_buffer) --- when '.' then --- append_custom_variables_to_string (a_ht, vars, '.', ',', True, a_buffer) --- when '/' then --- append_custom_variables_to_string (a_ht, vars, '/', '/', True, a_buffer) --- else --- append_custom_variables_to_string (a_ht, vars, '%U', ',', False, a_buffer) --- end end end feature {NONE} -- Implementation - url_encoded_string (s: READABLE_STRING_GENERAL; a_encoded: BOOLEAN): STRING - do - if a_encoded then - Result := url_encoder.encoded_string (s.as_string_32) - else - Result := url_encoder.partial_encoded_string (s.as_string_32, << - ':', ',', - '+', '.', '/', ';', '?', - '|', '!', '@' - >>) - end - end - - url_encoder: URL_ENCODER - once - create Result - end - append_custom_variables_to_string (a_ht: HASH_TABLE [detachable ANY, STRING]; vars: like variables; prefix_char, delimiter_char: CHARACTER; a_include_name: BOOLEAN; a_buffer: STRING) -- If `first_char' is '%U' do not print any first character local @@ -228,8 +215,8 @@ feature {NONE} -- Implementation vdata := a_ht.item (vi.name) vstr := Void if vdata /= Void then - vstr := vi.string (vdata) - if vstr = Void and vi.has_explode_modifier then + vstr := vi.expanded_string (vdata) + if vstr = Void and vi.has_explode then --| Missing or list empty vstr := vi.default_value l_use_default := True @@ -250,9 +237,9 @@ feature {NONE} -- Implementation else a_buffer.append_character (delimiter_char) end - if l_use_default and (operator = '?') and not vi.has_explode_modifier_star then + if l_use_default and (operator = Form_style_query_operator) and not vi.has_explode_star then a_buffer.append (vi.name) - if vi.has_explode_modifier_plus then + if vi.has_explode_plus then a_buffer.append_character ('.') else a_buffer.append_character ('=') diff --git a/library/protocol/uri_template/src/uri_template_expression_variable.e b/library/protocol/uri_template/src/uri_template_expression_variable.e index 81cf11e6..eecff43b 100644 --- a/library/protocol/uri_template/src/uri_template_expression_variable.e +++ b/library/protocol/uri_template/src/uri_template_expression_variable.e @@ -7,133 +7,172 @@ note class URI_TEMPLATE_EXPRESSION_VARIABLE +inherit + ANY + + URI_TEMPLATE_CONSTANTS + export {NONE} all end + create make feature {NONE} -- Initialization - make (op: like operator; n: like name; d: like default_value; m: like modifier) + make (exp: like expression; n: like name; d: like default_value; em: detachable STRING) + -- Create based on expression `exp', variable name `n', default value `d' if any + -- and explode or modifier string `em' do - operator := op + expression := exp + operator := exp.operator name := n default_value := d - modifier := m - + if em /= Void and then em.count > 0 then + inspect em[1] + when Explode_star, Explode_plus then + explode := em[1] + when Modifier_substring, Modifier_remainder then + modifier := em + else + end + end op_prefix := '%U' op_separator := ',' - inspect op - when '+' then + inspect operator + when Reserved_operator then --| '+' reserved := True - when '?' then + when Form_style_query_operator then --| '?' op_prefix := '?' op_separator := '&' - when ';' then + when Path_style_parameters_operator then --| ';' op_prefix := ';' op_separator := ';' - when '/' then + when Path_segment_operator then --| '/' op_prefix := '/' op_separator := '/' - when '.' then + when Label_operator then --| '.' op_prefix := '.' op_separator := '.' else - end end feature -- Access + expression: URI_TEMPLATE_EXPRESSION + -- Parent expression + operator: CHARACTER + -- First character of related `expression' name: STRING + -- variable name default_value: detachable STRING + -- default value if any reserved: BOOLEAN + -- Is reserved? + -- i.e: do not url-encode the reserved character op_prefix: CHARACTER + -- When expanding list of table, first character to use + --| ex: '?' for {?var} op_separator: CHARACTER + -- When expanding list of table, delimiter character to use + --| ex: ',' for {?var} + + explode: CHARACTER + -- Explode character , '*' or '+' modifier: detachable STRING + -- Modifier expression, starting by ':' or '^' + --| ":3" , "-3", "^4", ... - has_modifier: BOOLEAN - do - Result := modifier /= Void - end - - modified (s: READABLE_STRING_GENERAL): READABLE_STRING_GENERAL + modified_string (s: READABLE_STRING_GENERAL): READABLE_STRING_GENERAL local t: STRING i,n: INTEGER do Result := s - if attached modifier as m and then m.count > 1 and then m[1] = ':' then + if attached modifier as m and then m.count > 1 then n := s.count t := m.substring (2, m.count) if t.is_integer then i := t.to_integer - if i > 0 then - if i < n then - Result := s.substring (1, i) + inspect m[1] + when Modifier_substring then + if i > 0 then + if i < n then + Result := s.substring (1, i) + end + elseif i < 0 then + Result := s.substring (n - i, n) end - elseif i < 0 then - Result := s.substring (n - i, n) + when Modifier_remainder then + if i > 0 then + if i < n then + Result := s.substring (i + 1, n) + end + elseif i < 0 then + Result := s.substring (1, n + i) --| n + i = n - (-i) + end + else + check Known_modified: False end + -- Unchanged end end end end - has_explode_modifier: BOOLEAN + has_explode: BOOLEAN do - Result := attached modifier as m and then m.count = 1 and then ( - m[1] = '+' or m[1] = '*' - ) + Result := explode = Explode_plus or explode = Explode_star end - has_explode_modifier_plus: BOOLEAN + has_explode_plus: BOOLEAN do - Result := attached modifier as m and then m.count = 1 and then - m[1] = '+' + Result := explode = Explode_plus end - has_explode_modifier_star: BOOLEAN + has_explode_star: BOOLEAN do - Result := attached modifier as m and then m.count = 1 and then - m[1] = '*' + Result := explode = Explode_star end feature -- Report - string (d: detachable ANY): detachable STRING + expanded_string (d: detachable ANY): detachable STRING local l_delimiter: CHARACTER v_enc: detachable STRING k_enc: STRING l_obj: detachable ANY i,n: INTEGER - modifier_is_plus: BOOLEAN - modifier_is_star: BOOLEAN - modifier_has_explode: BOOLEAN + explode_is_plus: BOOLEAN + explode_is_star: BOOLEAN + l_has_explode: BOOLEAN dft: detachable ANY has_list_op: BOOLEAN + op: like operator do - modifier_has_explode := has_explode_modifier - if modifier_has_explode then - modifier_is_plus := has_explode_modifier_plus - modifier_is_star := has_explode_modifier_star + l_has_explode := has_explode + if l_has_explode then + explode_is_plus := has_explode_plus + explode_is_star := has_explode_star end - has_list_op := operator /= '%U' and operator /= '+' + op := operator + has_list_op := op /= '%U' and op /= Reserved_operator dft := default_value create Result.make (20) if attached {READABLE_STRING_GENERAL} d as l_string then - v_enc := url_encoded_string (modified (l_string), not reserved) - if operator = '?' then + v_enc := url_encoded_string (modified_string (l_string), not reserved) + if op = Form_style_query_operator then Result.append (name) Result.append_character ('=') - elseif operator = ';' then + elseif op = Path_style_parameters_operator then Result.append (name) if not v_enc.is_empty then Result.append_character ('=') @@ -143,29 +182,29 @@ feature -- Report elseif attached {ARRAY [detachable ANY]} d as l_array then if l_array.is_empty then if dft /= Void then - inspect operator - when '?',';' then - if not modifier_has_explode then + inspect op + when Form_style_query_operator, Path_style_parameters_operator then + if not l_has_explode then Result.append (name) Result.append_character ('=') Result.append (dft.out) else - if modifier_is_plus then + if explode_is_plus then Result.append (name) Result.append_character ('.') end Result.append (dft.out) end - when '/' then - if modifier_is_plus then + when Path_segment_operator then + if explode_is_plus then Result.append (name) Result.append_character ('.') end Result.append (dft.out) - when '.' then + when Label_operator then else - if modifier_has_explode then - if modifier_is_plus then + if l_has_explode then + if explode_is_plus then Result.append (name) Result.append_character ('.') end @@ -176,17 +215,14 @@ feature -- Report -- nothing ... end else - if modifier_has_explode then + if l_has_explode then l_delimiter := op_separator else l_delimiter := ',' - inspect operator - when '?' then + inspect op + when Form_style_query_operator then Result.append (name) Result.append_character ('=') - when ';' then - when '/' then --- Result.append_character ('/') else end end @@ -203,10 +239,10 @@ feature -- Report else v_enc := "" end - if modifier_is_plus then + if explode_is_plus then if - (operator = '?' and modifier_is_plus) or - (operator = ';' and modifier_has_explode) + (op = Form_style_query_operator and explode_is_plus) or + (op = Path_style_parameters_operator and l_has_explode) then Result.append (name) Result.append_character ('=') @@ -214,7 +250,7 @@ feature -- Report Result.append (name) Result.append_character ('.') end - elseif modifier_is_star and operator = '?' then + elseif explode_is_star and op = Form_style_query_operator then Result.append (name) Result.append_character ('=') end @@ -230,47 +266,31 @@ feature -- Report Result := Void end elseif attached {HASH_TABLE [detachable ANY, STRING]} d as l_table then --- if operator = '?' and not modifier_has_explode and l_table.is_empty and dft = Void then --- elseif operator = '?' and not modifier_has_explode then --- Result.append (name) --- Result.append_character ('=') --- if l_table.is_empty and dft /= Void then --- Result.append (dft.out) --- end --- elseif l_table.is_empty and dft /= Void then --- if modifier_has_explode then --- if modifier_is_plus then --- Result.append (name) --- Result.append_character ('.') --- end --- Result.append (dft.out) --- end --- end if l_table.is_empty then if dft /= Void then - inspect operator - when '?',';' then - if not modifier_has_explode then + inspect op + when Form_style_query_operator, Path_style_parameters_operator then + if not l_has_explode then Result.append (name) Result.append_character ('=') Result.append (dft.out) else - if modifier_is_plus then + if explode_is_plus then Result.append (name) Result.append_character ('.') end Result.append (dft.out) end - when '/' then - if modifier_is_plus then + when Path_segment_operator then + if explode_is_plus then Result.append (name) Result.append_character ('.') end Result.append (dft.out) - when '.' then + when Label_operator then else - if modifier_has_explode then - if modifier_is_plus then + if l_has_explode then + if explode_is_plus then Result.append (name) Result.append_character ('.') end @@ -281,16 +301,14 @@ feature -- Report -- nothing ... end else - if modifier_has_explode then + if l_has_explode then l_delimiter := op_separator else l_delimiter := ',' - inspect operator - when '?' then + inspect op + when Form_style_query_operator then Result.append (name) Result.append_character ('=') - when ';' then - when '/' then else end end @@ -308,20 +326,12 @@ feature -- Report v_enc := "" end - if modifier_is_plus then + if explode_is_plus then Result.append (name) Result.append_character ('.') end if - modifier_has_explode and - ( - operator = '%U' or - operator = '+' or - operator = '?' or - operator = '.' or - operator = ';' or - operator = '/' - ) + l_has_explode then Result.append (k_enc) Result.append_character ('=') @@ -348,12 +358,12 @@ feature -- Report else v_enc := default_value end - if operator = '?' then + if op = Form_style_query_operator then Result.append (name) if v_enc /= Void then Result.append_character ('=') end - elseif operator = ';' then + elseif op = Path_style_parameters_operator then Result.append (name) if v_enc /= Void and then not v_enc.is_empty then Result.append_character ('=') @@ -374,7 +384,11 @@ feature {NONE} -- Implementation else Result := url_encoder.partial_encoded_string (s.as_string_32, << ':', ',', - '+', '.', '/', ';', '?', + Reserved_operator, + Label_operator, + Path_segment_operator, + Path_style_parameters_operator, + Form_style_query_operator, '|', '!', '@' >>) end diff --git a/library/protocol/uri_template/test_uri_template-draft_05.ecf b/library/protocol/uri_template/test_uri_template-draft_05.ecf new file mode 100644 index 00000000..0933b4af --- /dev/null +++ b/library/protocol/uri_template/test_uri_template-draft_05.ecf @@ -0,0 +1,28 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + /test_uri_template.e$ + + + + diff --git a/library/protocol/uri_template/tests/draft_50/test_uri_template_draft_05.e b/library/protocol/uri_template/tests/draft_50/test_uri_template_draft_05.e new file mode 100644 index 00000000..9d89ea5c --- /dev/null +++ b/library/protocol/uri_template/tests/draft_50/test_uri_template_draft_05.e @@ -0,0 +1,632 @@ +note + description: "[ + Eiffel tests that can be executed by testing tool. + ]" + author: "EiffelStudio test wizard" + date: "$Date$" + revision: "$Revision$" + testing: "type/manual" + +class + TEST_URI_TEMPLATE_DRAFT_05 + +inherit + EQA_TEST_SET + +feature -- Test routines + + test_uri_template_parser + note + testing: "uri-template-05" + do + uri_template_parse ("api/foo/{foo_id}/{?id,extra}", <<"foo_id">>, <<"id", "extra">>) + uri_template_parse ("weather/{state}/{city}?forecast={day}", <<"state", "city">>, <<"day">>) + end + + test_uri_template_matcher + note + testing: "uri-template-05" + local + tpl: URI_TEMPLATE + do + create tpl.make ("api/foo/{foo_id}/{?id,extra}") + uri_template_match (tpl, "api/foo/bar/", <<["foo_id", "bar"]>>, <<>>) + uri_template_match (tpl, "api/foo/bar/?id=123", <<["foo_id", "bar"]>>, <<["id", "123"]>>) + uri_template_match (tpl, "api/foo/bar/?id=123&extra=test", <<["foo_id", "bar"]>>, <<["id", "123"], ["extra", "test"]>>) + uri_template_match (tpl, "api/foo/bar/?id=123&extra=test&one=more", <<["foo_id", "bar"]>>, <<["id", "123"], ["extra", "test"]>>) + uri_template_mismatch (tpl, "") + uri_template_mismatch (tpl, "/") + uri_template_mismatch (tpl, "foo/bar/?id=123") + uri_template_mismatch (tpl, "/api/foo/bar/") + uri_template_mismatch (tpl, "api/foo/bar") + + create tpl.make ("weather/{state}/{city}?forecast={day}") + uri_template_match (tpl, "weather/California/Goleta?forecast=today", <<["state", "California"], ["city", "Goleta"]>>, <<["day", "today"]>>) + end + + uri_template_string_errors: detachable LIST [STRING] + + test_uri_template_string_builder + note + testing: "uri-template-05" + local + ht: HASH_TABLE [detachable ANY, STRING] + empty_keys: HASH_TABLE [STRING, STRING] + empty_list: ARRAY [STRING] + favs: HASH_TABLE [detachable ANY, STRING] + keys: HASH_TABLE [STRING, STRING] + colors: ARRAY [STRING] + names: ARRAY [STRING] + semi_dot: HASH_TABLE [STRING, STRING] + vals: ARRAY [STRING] + do + create ht.make (3) + ht.force ("FooBar", "foo_id") + ht.force ("That's right!", "extra") + ht.force ("123", "id") + ht.force ("California", "state") + ht.force ("Goleta", "city") + ht.force ("today", "day") + + ht.force ("value", "var") + ht.force ("Hello World!", "hello") + ht.force ("", "empty") + ht.force ("/foo/bar", "path") + ht.force ("1024", "x") + ht.force ("768", "y") + ht.force ("fred", "foo") + ht.force ("That's right!", "foo2") + ht.force ("http://example.com/home/", "base") + + names := <<"Fred", "Wilma", "Pebbles">> + ht.force (names, "name") + create favs.make (2) + favs.force ("red", "color") + favs.force ("high", "volume") + ht.force (favs, "favs") + + create empty_list.make_empty + ht.force (empty_list,"empty_list") + + create empty_keys.make (0) + ht.force (empty_keys,"empty_keys") + + vals := <<"val1", "val2", "val3">> + ht.force (vals, "list") + create keys.make (2) + keys.force ("val1", "key1") + keys.force ("val2", "key2") + ht.force (keys, "keys") + + colors := <<"red", "green", "blue">> + create semi_dot.make (3) + semi_dot.force (";", "semi") + semi_dot.force (".", "dot") + semi_dot.force (",", "comma") + + create {ARRAYED_LIST [STRING]} uri_template_string_errors.make (10) + + + --| Simple string expansion + uri_template_string (ht, "{var}", "value") + uri_template_string (ht, "{hello}", "Hello+World%%21") + uri_template_string (ht, "O{empty}X", "OX") + uri_template_string (ht, "O{undef}X", "OX") + + --| String expansion with defaults + uri_template_string (ht, "{var|default}", "value") + uri_template_string (ht, "O{empty|default}X", "OX") + uri_template_string (ht, "O{undef|default}X", "OdefaultX") + + --| Reserved expansion with defaults + uri_template_string (ht, "{+var}", "value") + uri_template_string (ht, "{+hello}", "Hello+World!") + uri_template_string (ht, "{+path}/here", "/foo/bar/here") + uri_template_string (ht, "here?ref={+path}", "here?ref=/foo/bar") + uri_template_string (ht, "up{+path}{x}/here", "up/foo/bar1024/here") + uri_template_string (ht, "up{+empty|/1}/here", "up/here") + uri_template_string (ht, "up{+undef|/1}/here", "up/1/here") + + --| String expansion with multiple variables + uri_template_string (ht, "{x,y}", "1024,768") + uri_template_string (ht, "{x,hello,y}", "1024,Hello+World%%21,768") + uri_template_string (ht, "?{x,empty}", "?1024,") + uri_template_string (ht, "?{x,undef}", "?1024") + uri_template_string (ht, "?{undef,y}", "?768") + uri_template_string (ht, "?{x,undef|0}", "?1024,0") + + --| Reserved expansion with multiple variables + uri_template_string (ht, "{+x,hello,y}", "1024,Hello+World!,768") + uri_template_string (ht, "{+path,x}/here", "/foo/bar,1024/here") + --| Label expansion, dot-prefixed + uri_template_string (ht, "X{.var}", "X.value") + uri_template_string (ht, "X{.empty}", "X.") + uri_template_string (ht, "X{.undef}", "X") + + --| Path segments, slash-prefixed + uri_template_string (ht, "{/var}", "/value") + uri_template_string (ht, "{/var,empty}", "/value/") + uri_template_string (ht, "{/var,undef}", "/value") + + --| Path-style parameters, semicolon-prefixed + uri_template_string (ht, "{;x,y}", ";x=1024;y=768") + uri_template_string (ht, "{;x,y,empty}", ";x=1024;y=768;empty") + uri_template_string (ht, "{;x,y,undef}", ";x=1024;y=768") + + --| Form-style query, ampersand-separated + uri_template_string (ht, "{?x,y}", "?x=1024&y=768") + uri_template_string (ht, "{?x,y,empty}", "?x=1024&y=768&empty=") + uri_template_string (ht, "{?x,y,undef}", "?x=1024&y=768") + + + ht.force (colors, "list") + ht.force (semi_dot, "keys") + --| String expansion with value modifiers + uri_template_string (ht, "{var:3}", "val") + uri_template_string (ht, "{var:30}", "value") + uri_template_string (ht, "{var^3}", "ue") + uri_template_string (ht, "{var^-3}", "va") + + uri_template_string (ht, "{list}", "red,green,blue") + uri_template_string (ht, "{list*}", "red,green,blue") + uri_template_string (ht, "{keys}", "semi,%%3B,dot,.,comma,%%2C") + uri_template_string (ht, "{keys*}", "semi=%%3B,dot=.,comma=%%2C") + --| Reserved expansion with value modifiers + uri_template_string (ht, "{+path:6}/here", "/foo/b/here") + uri_template_string (ht, "{+list}", "red,green,blue") + uri_template_string (ht, "{+list*}", "red,green,blue") + uri_template_string (ht, "{+keys}", "semi,;,dot,.,comma,,") + uri_template_string (ht, "{+keys*}", "semi=;,dot=.,comma=,") + --| Label expansion, dot-prefixed + uri_template_string (ht, "X{.var:3}", "X.val") + uri_template_string (ht, "X{.list}", "X.red,green,blue") + uri_template_string (ht, "X{.list*}", "X.red.green.blue") + uri_template_string (ht, "X{.keys}", "X.semi,%%3B,dot,.,comma,%%2C") + uri_template_string (ht, "X{.keys*}", "X.semi=%%3B.dot=..comma=%%2C") + + --| Path segments, slash-prefixed + uri_template_string (ht, "{/var:1,var}", "/v/value") + uri_template_string (ht, "{/list}", "/red,green,blue") + uri_template_string (ht, "{/list*}", "/red/green/blue") + uri_template_string (ht, "{/list*,path:4}", "/red/green/blue/%%2Ffoo") + uri_template_string (ht, "{/keys}", "/semi,%%3B,dot,.,comma,%%2C") + uri_template_string (ht, "{/keys*}", "/semi=%%3B/dot=./comma=%%2C") + + --| Path-style parameters, semicolon-prefixed + uri_template_string (ht, "{;hello:5}", ";hello=Hello") + uri_template_string (ht, "{;list}", ";red,green,blue") + uri_template_string (ht, "{;list*}", ";red;green;blue") + uri_template_string (ht, "{;keys}", ";semi,%%3B,dot,.,comma,%%2C") + uri_template_string (ht, "{;keys*}", ";semi=%%3B;dot=.;comma=%%2C") + + --| Form-style query, ampersand-separated + uri_template_string (ht, "{?var:3}", "?var=val") + uri_template_string (ht, "{?list}", "?list=red,green,blue") + uri_template_string (ht, "{?list*}", "?list=red&list=green&list=blue") + uri_template_string (ht, "{?keys}", "?keys=semi,%%3B,dot,.,comma,%%2C") + uri_template_string (ht, "{?keys*}", "?semi=%%3B&dot=.&comma=%%2C") + + assert ("all strings built", uri_template_string_errors = Void or (attached uri_template_string_errors as err and then err.is_empty)) + end + + + test_uri_template_string_builder_extra + note + testing: "uri-template-05" + local + ht: HASH_TABLE [detachable ANY, STRING] + empty_keys: HASH_TABLE [STRING, STRING] + empty_list: ARRAY [STRING] + favs: HASH_TABLE [detachable ANY, STRING] + keys: HASH_TABLE [STRING, STRING] + colors: ARRAY [STRING] + names: ARRAY [STRING] + semi_dot: HASH_TABLE [STRING, STRING] + vals: ARRAY [STRING] + do + create ht.make (3) + ht.force ("FooBar", "foo_id") + ht.force ("That's right!", "extra") + ht.force ("123", "id") + ht.force ("California", "state") + ht.force ("Goleta", "city") + ht.force ("today", "day") + + ht.force ("value", "var") + ht.force ("Hello World!", "hello") + ht.force ("", "empty") + ht.force ("/foo/bar", "path") + ht.force ("1024", "x") + ht.force ("768", "y") + ht.force ("fred", "foo") + ht.force ("That's right!", "foo2") + ht.force ("http://example.com/home/", "base") + + names := <<"Fred", "Wilma", "Pebbles">> + ht.force (names, "name") + create favs.make (2) + favs.force ("red", "color") + favs.force ("high", "volume") + ht.force (favs, "favs") + + create empty_list.make_empty + ht.force (empty_list,"empty_list") + + create empty_keys.make (0) + ht.force (empty_keys,"empty_keys") + + vals := <<"val1", "val2", "val3">> + ht.force (vals, "list") + create keys.make (2) + keys.force ("val1", "key1") + keys.force ("val2", "key2") + ht.force (keys, "keys") + + colors := <<"red", "green", "blue">> + create semi_dot.make (3) + semi_dot.force (";", "semi") + semi_dot.force (".", "dot") + semi_dot.force (",", "comma") + + create {ARRAYED_LIST [STRING]} uri_template_string_errors.make (10) + + --| Addition to the spec + uri_template_string (ht, "api/foo/{foo_id}/{?id,extra}", + "api/foo/FooBar/?id=123&extra=That%%27s+right%%21") + + uri_template_string (ht, "api/foo/{foo_id}/{?id,empty,undef,extra}", + "api/foo/FooBar/?id=123&empty=&extra=That%%27s+right%%21") + + uri_template_string (ht, "weather/{state}/{city}?forecast={day}", + "weather/California/Goleta?forecast=today") + + + uri_template_string (ht, "{var|default}", "value") + uri_template_string (ht, "{undef|default}", "default") + uri_template_string (ht, "{undef:3|default}", "default") + + uri_template_string (ht, "x{empty}y", "xy") + uri_template_string (ht, "x{empty|_}y", "xy") + uri_template_string (ht, "x{undef}y", "xy") + uri_template_string (ht, "x{undef|_}y", "x_y") + + uri_template_string (ht, "x{.name|none}", "x.Fred,Wilma,Pebbles") + uri_template_string (ht, "x{.name*|none}", "x.Fred.Wilma.Pebbles") + uri_template_string (ht, "x{.empty}", "x.") + uri_template_string (ht, "x{.empty|none}", "x.") + uri_template_string (ht, "x{.undef}", "x") + uri_template_string (ht, "x{.undef|none}", "x.none") + + uri_template_string (ht, "x{/name|none}", "x/Fred,Wilma,Pebbles") + uri_template_string (ht, "x{/name*|none}", "x/Fred/Wilma/Pebbles") + uri_template_string (ht, "x{/undef}", "x") + uri_template_string (ht, "x{/undef|none}", "x/none") + uri_template_string (ht, "x{/empty}", "x/") + uri_template_string (ht, "x{/empty|none}", "x/") + uri_template_string (ht, "x{/empty_keys}", "x") + uri_template_string (ht, "x{/empty_keys|none}", "x/none") + uri_template_string (ht, "x{/empty_keys*}", "x") + uri_template_string (ht, "x{/empty_keys*|none}", "x/none") + + uri_template_string (ht, "x{;name|none}", "x;name=Fred,Wilma,Pebbles") + uri_template_string (ht, "x{;favs|none}", "x;favs=color,red,volume,high") + uri_template_string (ht, "x{;favs*|none}", "x;color=red;volume=high") + uri_template_string (ht, "x{;empty}", "x;empty") + uri_template_string (ht, "x{;empty|none}", "x;empty") + + uri_template_string (ht, "x{;undef}", "x") + uri_template_string (ht, "x{;undef|none}", "x;none") + uri_template_string (ht, "x{;undef|foo=y}", "x;foo=y") + + uri_template_string (ht, "x{?var|none}", "x?var=value") + uri_template_string (ht, "x{?favs|none}", "x?favs=color,red,volume,high") + uri_template_string (ht, "x{?favs*|none}", "x?color=red&volume=high") + uri_template_string (ht, "x{?empty}", "x?empty=") + uri_template_string (ht, "x{?empty|foo=none}", "x?empty=") + uri_template_string (ht, "x{?undef}", "x") + uri_template_string (ht, "x{?undef|foo=none}", "x?foo=none") + uri_template_string (ht, "x{?empty_keys}", "x") + uri_template_string (ht, "x{?empty_keys|none}", "x?none") + uri_template_string (ht, "x{?empty_keys|y=z}", "x?y=z") + uri_template_string (ht, "x{?empty_keys*|y=z}", "x?y=z") + + + ------ + + uri_template_string (ht, "x{empty_list}y", "xy") + uri_template_string (ht, "x{empty_list|_}y", "xy") + uri_template_string (ht, "x{empty_list*}y", "xy") + uri_template_string (ht, "x{empty_list*|_}y", "x_y") + uri_template_string (ht, "x{empty_list+}y", "xy") + uri_template_string (ht, "x{empty_list+|_}y", "xempty_list._y") + + uri_template_string (ht, "x{empty_keys}y", "xy") + uri_template_string (ht, "x{empty_keys|_}y", "xy") + uri_template_string (ht, "x{empty_keys*}y", "xy") + uri_template_string (ht, "x{empty_keys*|_}y", "x_y") + uri_template_string (ht, "x{empty_keys+}y", "xy") + uri_template_string (ht, "x{empty_keys+|_}y", "xempty_keys._y") + + uri_template_string (ht, "x{?name|none}", "x?name=Fred,Wilma,Pebbles") + uri_template_string (ht, "x{?favs|none}", "x?favs=color,red,volume,high") + uri_template_string (ht, "x{?favs*|none}", "x?color=red&volume=high") + uri_template_string (ht, "x{?favs+|none}", "x?favs.color=red&favs.volume=high") + + uri_template_string (ht, "x{?undef}", "x") + uri_template_string (ht, "x{?undef|none}", "x?undef=none") + uri_template_string (ht, "x{?empty}", "x?empty=") + uri_template_string (ht, "x{?empty|none}", "x?empty=") + + uri_template_string (ht, "x{?empty_list}", "x") + uri_template_string (ht, "x{?empty_list|none}", "x?empty_list=none") + uri_template_string (ht, "x{?empty_list*}", "x") + uri_template_string (ht, "x{?empty_list*|none}", "x?none") + uri_template_string (ht, "x{?empty_list+}", "x") + uri_template_string (ht, "x{?empty_list+|none}", "x?empty_list.none") + + uri_template_string (ht, "x{?empty_keys}", "x") + uri_template_string (ht, "x{?empty_keys|none}", "x?empty_keys=none") + uri_template_string (ht, "x{?empty_keys*}", "x") + uri_template_string (ht, "x{?empty_keys*|none}", "x?none") + uri_template_string (ht, "x{?empty_keys+}", "x") + uri_template_string (ht, "x{?empty_keys+|none}", "x?empty_keys.none") + + uri_template_string (ht, "x{;name|none}", "x;name=Fred,Wilma,Pebbles") + uri_template_string (ht, "x{;favs|none}", "x;favs=color,red,volume,high") + uri_template_string (ht, "x{;favs*|none}", "x;color=red;volume=high") + uri_template_string (ht, "x{;favs+|none}", "x;favs.color=red;favs.volume=high") + uri_template_string (ht, "x{;undef}", "x") + uri_template_string (ht, "x{;undef|none}", "x;undef=none") + uri_template_string (ht, "x{;undef|none}", "x;none") + uri_template_string (ht, "x{;empty}", "x;empty") + uri_template_string (ht, "x{;empty|none}", "x;empty") + + uri_template_string (ht, "x{;empty_list}", "x") + uri_template_string (ht, "x{;empty_list|none}", "x;empty_list=none") + uri_template_string (ht, "x{;empty_list*}", "x") + uri_template_string (ht, "x{;empty_list*|none}", "x;none") + uri_template_string (ht, "x{;empty_list+}", "x") + uri_template_string (ht, "x{;empty_list+|none}", "x;empty_list.none") + + uri_template_string (ht, "x{;empty_keys}", "x") + uri_template_string (ht, "x{;empty_keys|none}", "x;empty_keys=none") + uri_template_string (ht, "x{;empty_keys*}", "x") + uri_template_string (ht, "x{;empty_keys*|none}", "x;none") + uri_template_string (ht, "x{;empty_keys+}", "x") + uri_template_string (ht, "x{;empty_keys+|none}", "x;empty_keys.none") + + uri_template_string (ht, "x{/name|none}", "x/Fred,Wilma,Pebbles") + uri_template_string (ht, "x{/name*|none}", "x/Fred/Wilma/Pebbles") + uri_template_string (ht, "x{/name+|none}", "x/name.Fred/name.Wilma/name.Pebbles") + uri_template_string (ht, "x{/favs|none}", "x/color,red,volume,high") + uri_template_string (ht, "x{/favs*|none}", "x/color/red/volume/high") + uri_template_string (ht, "x{/favs+|none}", "x/favs.color/red/favs.volume/high") + + uri_template_string (ht, "x{/undef}", "x") + uri_template_string (ht, "x{/undef|none}", "x/none") + uri_template_string (ht, "x{/empty}", "x/") + uri_template_string (ht, "x{/empty|none}", "x/") + + uri_template_string (ht, "x{/empty_list}", "x") + uri_template_string (ht, "x{/empty_list|none}", "x/none") + uri_template_string (ht, "x{/empty_list*}", "x") + uri_template_string (ht, "x{/empty_list*|none}", "x/none") + uri_template_string (ht, "x{/empty_list+}", "x") + uri_template_string (ht, "x{/empty_list+|none}", "x/empty_list.none") + + uri_template_string (ht, "x{/empty_keys}", "x") + uri_template_string (ht, "x{/empty_keys|none}", "x/none") + uri_template_string (ht, "x{/empty_keys*}", "x") + uri_template_string (ht, "x{/empty_keys*|none}", "x/none") + uri_template_string (ht, "x{/empty_keys+}", "x") + uri_template_string (ht, "x{/empty_keys+|none}", "x/empty_keys.none") + + --| Simple expansion with comma-separated values + uri_template_string (ht, "{var}", "value") + uri_template_string (ht, "{hello}", "Hello+World%%21") + uri_template_string (ht, "{path}/here", "%%2Ffoo%%2Fbar/here") + uri_template_string (ht, "{x,y}", "1024,768") + uri_template_string (ht, "{var|default}", "value") + uri_template_string (ht, "{undef|default}", "default") + uri_template_string (ht, "{list}", "val1,val2,val3") + uri_template_string (ht, "{list*}", "val1,val2,val3") + uri_template_string (ht, "{list+}", "list.val1,list.val2,list.val3") + uri_template_string (ht, "{keys}", "key1,val1,key2,val2") + uri_template_string (ht, "{keys*}", "key1,val1,key2,val2") + uri_template_string (ht, "{keys+}", "keys.key1,val1,keys.key2,val2") + + --| Reserved expansion with comma-separated values + uri_template_string (ht, "{+var}", "value") + uri_template_string (ht, "{+hello}", "Hello+World!") + uri_template_string (ht, "{+path}/here", "/foo/bar/here") + uri_template_string (ht, "{+path,x}/here", "/foo/bar,1024/here") + uri_template_string (ht, "{+path}{x}/here", "/foo/bar1024/here") + uri_template_string (ht, "{+empty}/here", "/here") + uri_template_string (ht, "{+undef}/here", "/here") + uri_template_string (ht, "{+list}", "val1,val2,val3") + uri_template_string (ht, "{+list*}", "val1,val2,val3") + uri_template_string (ht, "{+list+}", "list.val1,list.val2,list.val3") + uri_template_string (ht, "{+keys}", "key1,val1,key2,val2") + uri_template_string (ht, "{+keys*}", "key1,val1,key2,val2") + uri_template_string (ht, "{+keys+}", "keys.key1,val1,keys.key2,val2") + + --| Path-style parameters, semicolon-prefixed + uri_template_string (ht, "{;x,y}", ";x=1024;y=768") + uri_template_string (ht, "{;x,y,empty}", ";x=1024;y=768;empty") + uri_template_string (ht, "{;x,y,undef}", ";x=1024;y=768") + uri_template_string (ht, "{;list}", ";list=val1,val2,val3") -- DIFF + uri_template_string (ht, "{;list*}", ";val1;val2;val3") + uri_template_string (ht, "{;list+}", ";list=val1;list=val2;list=val3") + uri_template_string (ht, "{;keys}", ";key1,val1,key2,val2") + uri_template_string (ht, "{;keys*}", ";key1=val1;key2=val2") + uri_template_string (ht, "{;keys+}", ";keys.key1=val1;keys.key2=val2") + + --| Form-style parameters, ampersand-separated + uri_template_string (ht, "{?x,y}", "?x=1024&y=768") + uri_template_string (ht, "{?x,y,empty}", "?x=1024&y=768&empty=") + uri_template_string (ht, "{?x,y,undef}", "?x=1024&y=768") + uri_template_string (ht, "{?list}", "?list=val1,val2,val3") + uri_template_string (ht, "{?list*}", "?val1&val2&val3") + uri_template_string (ht, "{?list+}", "?list=val1&list=val2&list=val3") + uri_template_string (ht, "{?keys}", "?keys=key1,val1,key2,val2") + uri_template_string (ht, "{?keys*}", "?key1=val1&key2=val2") + uri_template_string (ht, "{?keys+}", "?keys.key1=val1&keys.key2=val2") + + --| Hierarchical path segments, slash-separated + uri_template_string (ht, "{/var}", "/value") + uri_template_string (ht, "{/var,empty}", "/value/") + uri_template_string (ht, "{/var,undef}", "/value") + uri_template_string (ht, "{/list}", "/val1,val2,val3") + uri_template_string (ht, "{/list*}", "/val1/val2/val3") + uri_template_string (ht, "{/list*,x}", "/val1/val2/val3/1024") + uri_template_string (ht, "{/list+}", "/list.val1/list.val2/list.val3") + uri_template_string (ht, "{/keys}", "/key1,val1,key2,val2") + uri_template_string (ht, "{/keys*}", "/key1/val1/key2/val2") + uri_template_string (ht, "{/keys+}", "/keys.key1/val1/keys.key2/val2") + + --| Label expansion, dot-prefixed + uri_template_string (ht, "X{.var}", "X.value") + uri_template_string (ht, "X{.empty}", "X.") + uri_template_string (ht, "X{.undef}", "X") + uri_template_string (ht, "X{.list}", "X.val1,val2,val3") + uri_template_string (ht, "X{.list*}", "X.val1.val2.val3") + uri_template_string (ht, "X{.list*,x}", "X.val1.val2.val3.1024") + uri_template_string (ht, "X{.list+}", "X.list.val1.list.val2.list.val3") + uri_template_string (ht, "X{.keys}", "X.key1,val1,key2,val2") + uri_template_string (ht, "X{.keys*}", "X.key1.val1.key2.val2") + uri_template_string (ht, "X{.keys+}", "X.keys.key1.val1.keys.key2.val2") + + --| Simple Expansion + uri_template_string (ht, "{foo}", "fred") + uri_template_string (ht, "{foo,foo}", "fred,fred") + uri_template_string (ht, "{bar,foo}", "fred") + uri_template_string (ht, "{bar|wilma}", "wilma") + + --| Reserved Expansion + uri_template_string (ht, "{foo2}", "That%%27s+right%%21") + uri_template_string (ht, "{+foo2}", "That%%27s+right!") + uri_template_string (ht, "{base}index", "http%%3A%%2F%%2Fexample.com%%2Fhome%%2Findex") + uri_template_string (ht, "{+base}index", "http://example.com/home/index") + + assert ("all strings built", uri_template_string_errors = Void or (attached uri_template_string_errors as err and then err.is_empty)) + end + + uri_template_string (a_ht: HASH_TABLE [detachable ANY, STRING]; a_expression: STRING; a_expected: STRING) + local + tpl: URI_TEMPLATE + s: STRING + m: STRING + do + create tpl.make (a_expression) + s := tpl.expanded_string (a_ht) + if not s.same_string (a_expected) then + m := "Expected string for %"" + a_expression + "%" expected=%""+ a_expected +"%" but got %"" + s + "%"%N" + if attached uri_template_string_errors as err then + print (m) + err.force (m) + else + assert (m, False) + end + end + end + + uri_template_parse (s: STRING_8; path_vars: ARRAY [STRING]; query_vars: ARRAY [STRING]) + local + u: URI_TEMPLATE + matched: BOOLEAN + i: INTEGER + do + create u.make (s) + if attached u.path_variable_names as vars then + matched := vars.count = path_vars.count + from + i := path_vars.lower + vars.start + until + not matched or i > path_vars.upper + loop + matched := vars.item.same_string (path_vars[i]) + vars.forth + i := i + 1 + end + else + matched := path_vars.is_empty + end + assert ("path variables matched", matched) + + if attached u.query_variable_names as vars then + matched := vars.count = query_vars.count + from + i := query_vars.lower + vars.start + until + not matched or i > query_vars.upper + loop + matched := vars.item.same_string (query_vars[i]) + vars.forth + i := i + 1 + end + else + matched := query_vars.is_empty + end + assert ("query variables matched", matched) + end + + uri_template_mismatch (a_uri_template: URI_TEMPLATE; a_uri: STRING) + local + l_match: detachable URI_TEMPLATE_MATCH_RESULT + do + l_match := a_uri_template.match (a_uri) + assert ("uri %"" + a_uri + "%" does not match template %"" + a_uri_template.template + "%"", l_match = Void) + end + + uri_template_match (a_uri_template: URI_TEMPLATE; a_uri: STRING; path_res: ARRAY [TUPLE [name: STRING; value: STRING]]; query_res: ARRAY [TUPLE [name: STRING; value: STRING]]) + local + b: BOOLEAN + i: INTEGER + l_match: detachable URI_TEMPLATE_MATCH_RESULT + do + l_match := a_uri_template.match (a_uri) + if l_match /= Void then + if attached l_match.path_variables as path_ht then + b := path_ht.count = path_res.count + from + i := path_res.lower + until + not b or i > path_res.upper + loop + b := attached path_ht.item (path_res[i].name) as s and then s.same_string (path_res[i].value) + i := i + 1 + end + assert ("uri matched path variables", b) + end + if attached l_match.query_variables as query_ht then + b := query_ht.count >= query_res.count + from + i := query_res.lower + until + not b or i > query_res.upper + loop + b := attached query_ht.item (query_res[i].name) as s and then s.same_string (query_res[i].value) + i := i + 1 + end + assert ("uri matched query variables", b) + end + else + assert ("uri matched", False) + end + end + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end + + diff --git a/library/protocol/uri_template/tests/test_uri_template.e b/library/protocol/uri_template/tests/test_uri_template.e index 65989a99..7297b30a 100644 --- a/library/protocol/uri_template/tests/test_uri_template.e +++ b/library/protocol/uri_template/tests/test_uri_template.e @@ -114,9 +114,9 @@ feature -- Test routines uri_template_string (ht, "O{undef}X", "OX") --| String expansion with defaults - uri_template_string (ht, "{var|default}", "value") - uri_template_string (ht, "O{empty|default}X", "OX") - uri_template_string (ht, "O{undef|default}X", "OdefaultX") + uri_template_string (ht, "{var=default}", "value") + uri_template_string (ht, "O{empty=default}X", "OX") + uri_template_string (ht, "O{undef=default}X", "OdefaultX") --| Reserved expansion with defaults uri_template_string (ht, "{+var}", "value") @@ -124,8 +124,8 @@ feature -- Test routines uri_template_string (ht, "{+path}/here", "/foo/bar/here") uri_template_string (ht, "here?ref={+path}", "here?ref=/foo/bar") uri_template_string (ht, "up{+path}{x}/here", "up/foo/bar1024/here") - uri_template_string (ht, "up{+empty|/1}/here", "up/here") - uri_template_string (ht, "up{+undef|/1}/here", "up/1/here") + uri_template_string (ht, "up{+empty=/1}/here", "up/here") + uri_template_string (ht, "up{+undef=/1}/here", "up/1/here") --| String expansion with multiple variables uri_template_string (ht, "{x,y}", "1024,768") @@ -133,7 +133,7 @@ feature -- Test routines uri_template_string (ht, "?{x,empty}", "?1024,") uri_template_string (ht, "?{x,undef}", "?1024") uri_template_string (ht, "?{undef,y}", "?768") - uri_template_string (ht, "?{x,undef|0}", "?1024,0") + uri_template_string (ht, "?{x,undef=0}", "?1024,0") --| Reserved expansion with multiple variables uri_template_string (ht, "{+x,hello,y}", "1024,Hello+World!,768") @@ -164,6 +164,9 @@ feature -- Test routines --| String expansion with value modifiers uri_template_string (ht, "{var:3}", "val") uri_template_string (ht, "{var:30}", "value") + uri_template_string (ht, "{var^3}", "ue") + uri_template_string (ht, "{var^-3}", "va") + uri_template_string (ht, "{list}", "red,green,blue") uri_template_string (ht, "{list*}", "red,green,blue") uri_template_string (ht, "{keys}", "semi,%%3B,dot,.,comma,%%2C") @@ -203,7 +206,6 @@ feature -- Test routines uri_template_string (ht, "{?keys}", "?keys=semi,%%3B,dot,.,comma,%%2C") uri_template_string (ht, "{?keys*}", "?semi=%%3B&dot=.&comma=%%2C") - assert ("all strings built", uri_template_string_errors = Void or (attached uri_template_string_errors as err and then err.is_empty)) end @@ -279,153 +281,153 @@ feature -- Test routines "weather/California/Goleta?forecast=today") - uri_template_string (ht, "{var|default}", "value") - uri_template_string (ht, "{undef|default}", "default") - uri_template_string (ht, "{undef:3|default}", "default") + uri_template_string (ht, "{var=default}", "value") + uri_template_string (ht, "{undef=default}", "default") + uri_template_string (ht, "{undef:3=default}", "default") uri_template_string (ht, "x{empty}y", "xy") - uri_template_string (ht, "x{empty|_}y", "xy") + uri_template_string (ht, "x{empty=_}y", "xy") uri_template_string (ht, "x{undef}y", "xy") - uri_template_string (ht, "x{undef|_}y", "x_y") + uri_template_string (ht, "x{undef=_}y", "x_y") - uri_template_string (ht, "x{.name|none}", "x.Fred,Wilma,Pebbles") - uri_template_string (ht, "x{.name*|none}", "x.Fred.Wilma.Pebbles") + uri_template_string (ht, "x{.name=none}", "x.Fred,Wilma,Pebbles") + uri_template_string (ht, "x{.name*=none}", "x.Fred.Wilma.Pebbles") uri_template_string (ht, "x{.empty}", "x.") - uri_template_string (ht, "x{.empty|none}", "x.") + uri_template_string (ht, "x{.empty=none}", "x.") uri_template_string (ht, "x{.undef}", "x") - uri_template_string (ht, "x{.undef|none}", "x.none") + uri_template_string (ht, "x{.undef=none}", "x.none") - uri_template_string (ht, "x{/name|none}", "x/Fred,Wilma,Pebbles") - uri_template_string (ht, "x{/name*|none}", "x/Fred/Wilma/Pebbles") + uri_template_string (ht, "x{/name=none}", "x/Fred,Wilma,Pebbles") + uri_template_string (ht, "x{/name*=none}", "x/Fred/Wilma/Pebbles") uri_template_string (ht, "x{/undef}", "x") - uri_template_string (ht, "x{/undef|none}", "x/none") + uri_template_string (ht, "x{/undef=none}", "x/none") uri_template_string (ht, "x{/empty}", "x/") - uri_template_string (ht, "x{/empty|none}", "x/") + uri_template_string (ht, "x{/empty=none}", "x/") uri_template_string (ht, "x{/empty_keys}", "x") - uri_template_string (ht, "x{/empty_keys|none}", "x/none") + uri_template_string (ht, "x{/empty_keys=none}", "x/none") uri_template_string (ht, "x{/empty_keys*}", "x") - uri_template_string (ht, "x{/empty_keys*|none}", "x/none") + uri_template_string (ht, "x{/empty_keys*=none}", "x/none") - uri_template_string (ht, "x{;name|none}", "x;name=Fred,Wilma,Pebbles") - uri_template_string (ht, "x{;favs|none}", "x;favs=color,red,volume,high") - uri_template_string (ht, "x{;favs*|none}", "x;color=red;volume=high") + uri_template_string (ht, "x{;name=none}", "x;name=Fred,Wilma,Pebbles") + uri_template_string (ht, "x{;favs=none}", "x;favs=color,red,volume,high") + uri_template_string (ht, "x{;favs*=none}", "x;color=red;volume=high") uri_template_string (ht, "x{;empty}", "x;empty") - uri_template_string (ht, "x{;empty|none}", "x;empty") + uri_template_string (ht, "x{;empty=none}", "x;empty") uri_template_string (ht, "x{;undef}", "x") - uri_template_string (ht, "x{;undef|none}", "x;none") - uri_template_string (ht, "x{;undef|foo=y}", "x;foo=y") + uri_template_string (ht, "x{;undef=none}", "x;none") + uri_template_string (ht, "x{;undef=foo=y}", "x;foo=y") - uri_template_string (ht, "x{?var|none}", "x?var=value") - uri_template_string (ht, "x{?favs|none}", "x?favs=color,red,volume,high") - uri_template_string (ht, "x{?favs*|none}", "x?color=red&volume=high") + uri_template_string (ht, "x{?var=none}", "x?var=value") + uri_template_string (ht, "x{?favs=none}", "x?favs=color,red,volume,high") + uri_template_string (ht, "x{?favs*=none}", "x?color=red&volume=high") uri_template_string (ht, "x{?empty}", "x?empty=") - uri_template_string (ht, "x{?empty|foo=none}", "x?empty=") + uri_template_string (ht, "x{?empty=foo=none}", "x?empty=") uri_template_string (ht, "x{?undef}", "x") - uri_template_string (ht, "x{?undef|foo=none}", "x?foo=none") + uri_template_string (ht, "x{?undef=foo=none}", "x?foo=none") uri_template_string (ht, "x{?empty_keys}", "x") - uri_template_string (ht, "x{?empty_keys|none}", "x?none") - uri_template_string (ht, "x{?empty_keys|y=z}", "x?y=z") - uri_template_string (ht, "x{?empty_keys*|y=z}", "x?y=z") + uri_template_string (ht, "x{?empty_keys=none}", "x?none") + uri_template_string (ht, "x{?empty_keys=y=z}", "x?y=z") + uri_template_string (ht, "x{?empty_keys*=y=z}", "x?y=z") ------ uri_template_string (ht, "x{empty_list}y", "xy") - uri_template_string (ht, "x{empty_list|_}y", "xy") + uri_template_string (ht, "x{empty_list=_}y", "xy") uri_template_string (ht, "x{empty_list*}y", "xy") - uri_template_string (ht, "x{empty_list*|_}y", "x_y") + uri_template_string (ht, "x{empty_list*=_}y", "x_y") uri_template_string (ht, "x{empty_list+}y", "xy") - uri_template_string (ht, "x{empty_list+|_}y", "xempty_list._y") + uri_template_string (ht, "x{empty_list+=_}y", "xempty_list._y") uri_template_string (ht, "x{empty_keys}y", "xy") - uri_template_string (ht, "x{empty_keys|_}y", "xy") + uri_template_string (ht, "x{empty_keys=_}y", "xy") uri_template_string (ht, "x{empty_keys*}y", "xy") - uri_template_string (ht, "x{empty_keys*|_}y", "x_y") + uri_template_string (ht, "x{empty_keys*=_}y", "x_y") uri_template_string (ht, "x{empty_keys+}y", "xy") - uri_template_string (ht, "x{empty_keys+|_}y", "xempty_keys._y") + uri_template_string (ht, "x{empty_keys+=_}y", "xempty_keys._y") - uri_template_string (ht, "x{?name|none}", "x?name=Fred,Wilma,Pebbles") - uri_template_string (ht, "x{?favs|none}", "x?favs=color,red,volume,high") - uri_template_string (ht, "x{?favs*|none}", "x?color=red&volume=high") - uri_template_string (ht, "x{?favs+|none}", "x?favs.color=red&favs.volume=high") + uri_template_string (ht, "x{?name=none}", "x?name=Fred,Wilma,Pebbles") + uri_template_string (ht, "x{?favs=none}", "x?favs=color,red,volume,high") + uri_template_string (ht, "x{?favs*=none}", "x?color=red&volume=high") + uri_template_string (ht, "x{?favs+=none}", "x?favs.color=red&favs.volume=high") uri_template_string (ht, "x{?undef}", "x") - uri_template_string (ht, "x{?undef|none}", "x?undef=none") + uri_template_string (ht, "x{?undef=none}", "x?undef=none") uri_template_string (ht, "x{?empty}", "x?empty=") - uri_template_string (ht, "x{?empty|none}", "x?empty=") + uri_template_string (ht, "x{?empty=none}", "x?empty=") uri_template_string (ht, "x{?empty_list}", "x") - uri_template_string (ht, "x{?empty_list|none}", "x?empty_list=none") + uri_template_string (ht, "x{?empty_list=none}", "x?empty_list=none") uri_template_string (ht, "x{?empty_list*}", "x") - uri_template_string (ht, "x{?empty_list*|none}", "x?none") + uri_template_string (ht, "x{?empty_list*=none}", "x?none") uri_template_string (ht, "x{?empty_list+}", "x") - uri_template_string (ht, "x{?empty_list+|none}", "x?empty_list.none") + uri_template_string (ht, "x{?empty_list+=none}", "x?empty_list.none") uri_template_string (ht, "x{?empty_keys}", "x") - uri_template_string (ht, "x{?empty_keys|none}", "x?empty_keys=none") + uri_template_string (ht, "x{?empty_keys=none}", "x?empty_keys=none") uri_template_string (ht, "x{?empty_keys*}", "x") - uri_template_string (ht, "x{?empty_keys*|none}", "x?none") + uri_template_string (ht, "x{?empty_keys*=none}", "x?none") uri_template_string (ht, "x{?empty_keys+}", "x") - uri_template_string (ht, "x{?empty_keys+|none}", "x?empty_keys.none") + uri_template_string (ht, "x{?empty_keys+=none}", "x?empty_keys.none") - uri_template_string (ht, "x{;name|none}", "x;name=Fred,Wilma,Pebbles") - uri_template_string (ht, "x{;favs|none}", "x;favs=color,red,volume,high") - uri_template_string (ht, "x{;favs*|none}", "x;color=red;volume=high") - uri_template_string (ht, "x{;favs+|none}", "x;favs.color=red;favs.volume=high") + uri_template_string (ht, "x{;name=none}", "x;name=Fred,Wilma,Pebbles") + uri_template_string (ht, "x{;favs=none}", "x;favs=color,red,volume,high") + uri_template_string (ht, "x{;favs*=none}", "x;color=red;volume=high") + uri_template_string (ht, "x{;favs+=none}", "x;favs.color=red;favs.volume=high") uri_template_string (ht, "x{;undef}", "x") - uri_template_string (ht, "x{;undef|none}", "x;undef=none") - uri_template_string (ht, "x{;undef|none}", "x;none") + uri_template_string (ht, "x{;undef=none}", "x;undef=none") + uri_template_string (ht, "x{;undef=none}", "x;none") uri_template_string (ht, "x{;empty}", "x;empty") - uri_template_string (ht, "x{;empty|none}", "x;empty") + uri_template_string (ht, "x{;empty=none}", "x;empty") uri_template_string (ht, "x{;empty_list}", "x") - uri_template_string (ht, "x{;empty_list|none}", "x;empty_list=none") + uri_template_string (ht, "x{;empty_list=none}", "x;empty_list=none") uri_template_string (ht, "x{;empty_list*}", "x") - uri_template_string (ht, "x{;empty_list*|none}", "x;none") + uri_template_string (ht, "x{;empty_list*=none}", "x;none") uri_template_string (ht, "x{;empty_list+}", "x") - uri_template_string (ht, "x{;empty_list+|none}", "x;empty_list.none") + uri_template_string (ht, "x{;empty_list+=none}", "x;empty_list.none") uri_template_string (ht, "x{;empty_keys}", "x") - uri_template_string (ht, "x{;empty_keys|none}", "x;empty_keys=none") + uri_template_string (ht, "x{;empty_keys=none}", "x;empty_keys=none") uri_template_string (ht, "x{;empty_keys*}", "x") - uri_template_string (ht, "x{;empty_keys*|none}", "x;none") + uri_template_string (ht, "x{;empty_keys*=none}", "x;none") uri_template_string (ht, "x{;empty_keys+}", "x") - uri_template_string (ht, "x{;empty_keys+|none}", "x;empty_keys.none") + uri_template_string (ht, "x{;empty_keys+=none}", "x;empty_keys.none") - uri_template_string (ht, "x{/name|none}", "x/Fred,Wilma,Pebbles") - uri_template_string (ht, "x{/name*|none}", "x/Fred/Wilma/Pebbles") - uri_template_string (ht, "x{/name+|none}", "x/name.Fred/name.Wilma/name.Pebbles") - uri_template_string (ht, "x{/favs|none}", "x/color,red,volume,high") - uri_template_string (ht, "x{/favs*|none}", "x/color/red/volume/high") - uri_template_string (ht, "x{/favs+|none}", "x/favs.color/red/favs.volume/high") + uri_template_string (ht, "x{/name=none}", "x/Fred,Wilma,Pebbles") + uri_template_string (ht, "x{/name*=none}", "x/Fred/Wilma/Pebbles") + uri_template_string (ht, "x{/name+=none}", "x/name.Fred/name.Wilma/name.Pebbles") + uri_template_string (ht, "x{/favs=none}", "x/color,red,volume,high") + uri_template_string (ht, "x{/favs*=none}", "x/color/red/volume/high") + uri_template_string (ht, "x{/favs+=none}", "x/favs.color/red/favs.volume/high") uri_template_string (ht, "x{/undef}", "x") - uri_template_string (ht, "x{/undef|none}", "x/none") + uri_template_string (ht, "x{/undef=none}", "x/none") uri_template_string (ht, "x{/empty}", "x/") - uri_template_string (ht, "x{/empty|none}", "x/") + uri_template_string (ht, "x{/empty=none}", "x/") uri_template_string (ht, "x{/empty_list}", "x") - uri_template_string (ht, "x{/empty_list|none}", "x/none") + uri_template_string (ht, "x{/empty_list=none}", "x/none") uri_template_string (ht, "x{/empty_list*}", "x") - uri_template_string (ht, "x{/empty_list*|none}", "x/none") + uri_template_string (ht, "x{/empty_list*=none}", "x/none") uri_template_string (ht, "x{/empty_list+}", "x") - uri_template_string (ht, "x{/empty_list+|none}", "x/empty_list.none") + uri_template_string (ht, "x{/empty_list+=none}", "x/empty_list.none") uri_template_string (ht, "x{/empty_keys}", "x") - uri_template_string (ht, "x{/empty_keys|none}", "x/none") + uri_template_string (ht, "x{/empty_keys=none}", "x/none") uri_template_string (ht, "x{/empty_keys*}", "x") - uri_template_string (ht, "x{/empty_keys*|none}", "x/none") + uri_template_string (ht, "x{/empty_keys*=none}", "x/none") uri_template_string (ht, "x{/empty_keys+}", "x") - uri_template_string (ht, "x{/empty_keys+|none}", "x/empty_keys.none") + uri_template_string (ht, "x{/empty_keys+=none}", "x/empty_keys.none") --| Simple expansion with comma-separated values uri_template_string (ht, "{var}", "value") uri_template_string (ht, "{hello}", "Hello+World%%21") uri_template_string (ht, "{path}/here", "%%2Ffoo%%2Fbar/here") uri_template_string (ht, "{x,y}", "1024,768") - uri_template_string (ht, "{var|default}", "value") - uri_template_string (ht, "{undef|default}", "default") + uri_template_string (ht, "{var=default}", "value") + uri_template_string (ht, "{undef=default}", "default") uri_template_string (ht, "{list}", "val1,val2,val3") uri_template_string (ht, "{list*}", "val1,val2,val3") uri_template_string (ht, "{list+}", "list.val1,list.val2,list.val3") @@ -498,7 +500,7 @@ feature -- Test routines uri_template_string (ht, "{foo}", "fred") uri_template_string (ht, "{foo,foo}", "fred,fred") uri_template_string (ht, "{bar,foo}", "fred") - uri_template_string (ht, "{bar|wilma}", "wilma") + uri_template_string (ht, "{bar=wilma}", "wilma") --| Reserved Expansion uri_template_string (ht, "{foo2}", "That%%27s+right%%21") @@ -516,7 +518,7 @@ feature -- Test routines m: STRING do create tpl.make (a_expression) - s := tpl.string (a_ht) + s := tpl.expanded_string (a_ht) if not s.same_string (a_expected) then m := "Expected string for %"" + a_expression + "%" expected=%""+ a_expected +"%" but got %"" + s + "%"%N" if attached uri_template_string_errors as err then @@ -596,7 +598,7 @@ feature -- Test routines b := attached path_ht.item (path_res[i].name) as s and then s.same_string (path_res[i].value) i := i + 1 end - assert ("uri matched path variables", b) + assert ("uri %"" + a_uri + "%" matched path variables", b) end if attached l_match.query_variables as query_ht then b := query_ht.count >= query_res.count @@ -608,10 +610,10 @@ feature -- Test routines b := attached query_ht.item (query_res[i].name) as s and then s.same_string (query_res[i].value) i := i + 1 end - assert ("uri matched query variables", b) + assert ("uri %"" + a_uri + "%" matched query variables", b) end else - assert ("uri matched", False) + assert ("uri %"" + a_uri + "%" matched", False) end end diff --git a/library/protocol/uri_template/uri_template-safe.ecf b/library/protocol/uri_template/uri_template-safe.ecf index ed5b9178..dda82aa1 100644 --- a/library/protocol/uri_template/uri_template-safe.ecf +++ b/library/protocol/uri_template/uri_template-safe.ecf @@ -13,7 +13,22 @@ - + + + /draft_05$ + + + /uri_template_constants.e + + + + + + + + + + @@ -26,6 +41,7 @@ + diff --git a/library/protocol/uri_template/uri_template.ecf b/library/protocol/uri_template/uri_template.ecf index 8d31c66c..5a6c0f76 100644 --- a/library/protocol/uri_template/uri_template.ecf +++ b/library/protocol/uri_template/uri_template.ecf @@ -7,12 +7,45 @@ /EIFGENs$ /.svn$ + + - + + + /draft_05$ + + + /uri_template_constants.e + + + + + + + + + + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + -