Merge branch 'master' into es17.01
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
</library>
|
||||
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/>
|
||||
<cluster name="src" location=".\src\">
|
||||
<cluster name="implementation" location="$|implementation" recursive="true" hidden="true"/>
|
||||
<cluster name="spec_null" location="$|spec\null\" recursive="true"/>
|
||||
<cluster name="spec_net" location="$|spec\net\">
|
||||
<condition>
|
||||
|
||||
@@ -196,73 +196,8 @@ feature -- Settings
|
||||
Result := session.is_insecure
|
||||
end
|
||||
|
||||
feature {NONE} -- Utilities
|
||||
|
||||
append_parameters_to_url (a_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_32]; a_url: STRING)
|
||||
-- Append parameters `a_parameters' to `a_url'
|
||||
require
|
||||
a_url_attached: a_url /= Void
|
||||
local
|
||||
l_first_param: BOOLEAN
|
||||
do
|
||||
if a_parameters.count > 0 then
|
||||
if a_url.index_of ('?', 1) > 0 then
|
||||
l_first_param := False
|
||||
elseif a_url.index_of ('&', 1) > 0 then
|
||||
l_first_param := False
|
||||
else
|
||||
l_first_param := True
|
||||
end
|
||||
|
||||
from
|
||||
a_parameters.start
|
||||
until
|
||||
a_parameters.after
|
||||
loop
|
||||
if l_first_param then
|
||||
a_url.append_character ('?')
|
||||
else
|
||||
a_url.append_character ('&')
|
||||
end
|
||||
a_url.append (urlencode (a_parameters.key_for_iteration))
|
||||
a_url.append_character ('=')
|
||||
a_url.append (urlencode (a_parameters.item_for_iteration))
|
||||
l_first_param := False
|
||||
a_parameters.forth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Utilities: encoding
|
||||
|
||||
url_encoder: URL_ENCODER
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
urlencode (s: READABLE_STRING_32): READABLE_STRING_8
|
||||
-- URL encode `s'
|
||||
do
|
||||
Result := url_encoder.encoded_string (s)
|
||||
end
|
||||
|
||||
urldecode (s: READABLE_STRING_8): READABLE_STRING_32
|
||||
-- URL decode `s'
|
||||
do
|
||||
Result := url_encoder.decoded_string (s)
|
||||
end
|
||||
|
||||
stripslashes (s: STRING): STRING
|
||||
do
|
||||
Result := s.string
|
||||
Result.replace_substring_all ("\%"", "%"")
|
||||
Result.replace_substring_all ("\'", "'")
|
||||
Result.replace_substring_all ("\/", "/")
|
||||
Result.replace_substring_all ("\\", "\")
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -142,16 +142,16 @@ feature -- Element change
|
||||
end
|
||||
end
|
||||
|
||||
add_query_parameter (k: READABLE_STRING_32; v: READABLE_STRING_32)
|
||||
add_query_parameter (k: READABLE_STRING_GENERAL; v: READABLE_STRING_GENERAL)
|
||||
-- Add a query parameter `k=v'.
|
||||
do
|
||||
query_parameters.force (v, k)
|
||||
query_parameters.force (v.to_string_32, k.to_string_32)
|
||||
end
|
||||
|
||||
add_form_parameter (k: READABLE_STRING_32; v: READABLE_STRING_32)
|
||||
add_form_parameter (k: READABLE_STRING_GENERAL; v: READABLE_STRING_GENERAL)
|
||||
-- Add a form parameter `k'= `v'.
|
||||
do
|
||||
form_parameters.force (v, k)
|
||||
form_parameters.force (v.to_string_32, k.to_string_32)
|
||||
end
|
||||
|
||||
set_credentials_required (b: BOOLEAN)
|
||||
@@ -236,18 +236,62 @@ feature -- Status setting
|
||||
end
|
||||
end
|
||||
|
||||
feature -- URL helpers
|
||||
|
||||
append_query_parameters_to_url (a_url: STRING)
|
||||
-- Append parameters `a_parameters' to `a_url'
|
||||
require
|
||||
a_url_attached: a_url /= Void
|
||||
local
|
||||
l_first_param: BOOLEAN
|
||||
do
|
||||
if
|
||||
attached query_parameters as l_query_parameters and then
|
||||
not l_query_parameters.is_empty
|
||||
then
|
||||
if a_url.index_of ('?', 1) > 0 then
|
||||
l_first_param := False
|
||||
elseif a_url.index_of ('&', 1) > 0 then
|
||||
l_first_param := False
|
||||
else
|
||||
l_first_param := True
|
||||
end
|
||||
|
||||
across
|
||||
query_parameters as ic
|
||||
loop
|
||||
if l_first_param then
|
||||
a_url.append_character ('?')
|
||||
else
|
||||
a_url.append_character ('&')
|
||||
end
|
||||
l_first_param := False
|
||||
uri_percent_encoder.append_query_name_encoded_string_to (ic.key, a_url)
|
||||
a_url.append_character ('=')
|
||||
uri_percent_encoder.append_query_value_encoded_string_to (ic.item, a_url)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Conversion helpers
|
||||
|
||||
query_parameters_to_url_encoded_string: STRING_8
|
||||
-- `query_parameters' as url-encoded string.
|
||||
do
|
||||
Result := parameters_to_url_encoded_string (query_parameters)
|
||||
Result := parameters_to_uri_percent_encoded_string (query_parameters)
|
||||
end
|
||||
|
||||
form_parameters_to_x_www_form_url_encoded_string: STRING_8
|
||||
-- `form_parameters' as x-www-form-urlencoded string.
|
||||
do
|
||||
Result := parameters_to_x_www_form_urlencoded_string (form_parameters)
|
||||
end
|
||||
|
||||
form_parameters_to_url_encoded_string: STRING_8
|
||||
-- `form_parameters' as url-encoded string.
|
||||
obsolete "Use form_parameters_to_x_www_form_url_encoded_string [2017-05-31]"
|
||||
do
|
||||
Result := parameters_to_url_encoded_string (form_parameters)
|
||||
Result := form_parameters_to_x_www_form_url_encoded_string
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
@@ -271,6 +315,52 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
end
|
||||
|
||||
parameters_to_uri_percent_encoded_string (ht: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_32]): STRING_8
|
||||
-- Build query urlencoded string using parameters from `ht'.
|
||||
do
|
||||
create Result.make (64)
|
||||
across
|
||||
ht as ic
|
||||
loop
|
||||
if not Result.is_empty then
|
||||
Result.append_character ('&')
|
||||
end
|
||||
uri_percent_encoder.append_query_name_encoded_string_to (ic.key, Result)
|
||||
Result.append_character ('=')
|
||||
uri_percent_encoder.append_query_value_encoded_string_to (ic.item, Result)
|
||||
end
|
||||
end
|
||||
|
||||
parameters_to_x_www_form_urlencoded_string (ht: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_32]): STRING_8
|
||||
-- Build x-www-form-urlencoded string using parameters from `ht'.
|
||||
do
|
||||
create Result.make (64)
|
||||
from
|
||||
ht.start
|
||||
until
|
||||
ht.after
|
||||
loop
|
||||
if not Result.is_empty then
|
||||
Result.append_character ('&')
|
||||
end
|
||||
Result.append (x_www_form_url_encoder.encoded_string (ht.key_for_iteration))
|
||||
Result.append_character ('=')
|
||||
Result.append (x_www_form_url_encoder.encoded_string (ht.item_for_iteration))
|
||||
ht.forth
|
||||
end
|
||||
end
|
||||
|
||||
x_www_form_url_encoder: X_WWW_FORM_URL_ENCODER
|
||||
-- Shared x-www-form-urlencoded encoder.
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
uri_percent_encoder: URI_PERCENT_ENCODER
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
url_encoder: URL_ENCODER
|
||||
-- Shared URL encoder.
|
||||
once
|
||||
@@ -278,7 +368,7 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -60,28 +60,10 @@ feature -- Access
|
||||
|
||||
url (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): STRING_8
|
||||
-- Url computed from Current and `ctx' data.
|
||||
local
|
||||
s: STRING_8
|
||||
url_encoder: URL_ENCODER
|
||||
do
|
||||
Result := base_url + a_path
|
||||
if ctx /= Void then
|
||||
create s.make_empty
|
||||
create url_encoder
|
||||
across
|
||||
ctx.query_parameters as q
|
||||
loop
|
||||
if not s.is_empty then
|
||||
s.append_character ('&')
|
||||
end
|
||||
s.append (url_encoder.encoded_string (q.key))
|
||||
s.append_character ('=')
|
||||
s.append (url_encoder.encoded_string (q.item))
|
||||
end
|
||||
if not s.is_empty then
|
||||
Result.append_character ('?')
|
||||
Result.append (s)
|
||||
end
|
||||
ctx.append_query_parameters_to_url (Result)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -420,7 +402,7 @@ feature -- Element change
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -0,0 +1,628 @@
|
||||
note
|
||||
description: "[
|
||||
Component to handle percent encoding
|
||||
|
||||
WARNING: THIS IS A COPY FROM $ISE_LIBRARY/library/text/uri library.
|
||||
In the future, http_client will use directly the `uri` library.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=Percent-encoding", "protocol=URI", "src=http://en.wikipedia.org/wiki/Percent-encoding"
|
||||
|
||||
class
|
||||
URI_PERCENT_ENCODER
|
||||
|
||||
feature -- Percent encoding
|
||||
|
||||
append_percent_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
|
||||
-- Append `s' as percent-encoded value to `a_result'
|
||||
local
|
||||
i,n: INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
n := s.count
|
||||
until
|
||||
i > n
|
||||
loop
|
||||
append_encoded_character_code_to (s.code (i), a_result)
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
append_query_name_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
|
||||
-- Append `s' as encoded for URI query name to `a_result'
|
||||
local
|
||||
i,n: INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
n := s.count
|
||||
until
|
||||
i > n
|
||||
loop
|
||||
append_query_name_encoded_character_code_to (s.code (i), a_result)
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
append_query_value_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
|
||||
-- Append `s' as encoded for URI query value to `a_result'.
|
||||
local
|
||||
i,n: INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
n := s.count
|
||||
until
|
||||
i > n
|
||||
loop
|
||||
append_query_value_encoded_character_code_to (s.code (i), a_result)
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
append_path_segment_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
|
||||
-- Append `a_string' as encoded for URI path segment to `a_result'
|
||||
local
|
||||
i,n: INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
n := s.count
|
||||
until
|
||||
i > n
|
||||
loop
|
||||
append_path_segment_encoded_character_code_to (s.code (i), a_result)
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
append_www_form_url_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
|
||||
-- Append `a_string' as www-form-urlencoded value to `a_result'.
|
||||
-- The main difference with `append_percent_encoded_string_to` is the encoding of space using '+'.
|
||||
local
|
||||
i,n: INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
n := s.count
|
||||
until
|
||||
i > n
|
||||
loop
|
||||
inspect s.code (i)
|
||||
when 32 then -- space: 32 ' '
|
||||
a_result.append_code (43) -- 43 '+'
|
||||
else
|
||||
append_encoded_character_code_to (s.code (i), a_result)
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- URI building helpers
|
||||
|
||||
append_encoded_character_code_to (c: NATURAL_32; a_result: STRING_GENERAL)
|
||||
-- Append character code `c' as query name encoded content into `a_result'.
|
||||
do
|
||||
if
|
||||
--| unreserved ALPHA / DIGIT
|
||||
(48 <= c and c <= 57) -- DIGIT: 0 .. 9
|
||||
or (65 <= c and c <= 90) -- ALPHA: A .. Z
|
||||
or (97 <= c and c <= 122) -- ALPHA: a .. z
|
||||
then
|
||||
a_result.append_code (c)
|
||||
else
|
||||
inspect c
|
||||
when
|
||||
45, 46, 95, 126 -- unreserved characters: -._~
|
||||
then
|
||||
a_result.append_code (c)
|
||||
when
|
||||
58, 64, -- reserved =+ gen-delims: : @
|
||||
33, 36, 38, 39, 40, 41, 42, -- reserved =+ sub-delims: ! $ & ' ( ) *
|
||||
43, 44, 59, 61, -- reserved = sub-delims: + , ; =
|
||||
37 -- percent encoding: %
|
||||
then
|
||||
append_percent_encoded_character_code_to (c, a_result)
|
||||
else
|
||||
append_percent_encoded_character_code_to (c, a_result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
append_query_name_encoded_character_code_to (c: NATURAL_32; a_result: STRING_GENERAL)
|
||||
-- Append character code `a_code' as query name encoded content into `a_result'.
|
||||
do
|
||||
inspect c
|
||||
when 61 then -- equal sign: =
|
||||
append_percent_encoded_character_code_to (c, a_result)
|
||||
else
|
||||
append_query_value_encoded_character_code_to (c, a_result)
|
||||
end
|
||||
end
|
||||
|
||||
append_query_value_encoded_character_code_to (c: NATURAL_32; a_result: STRING_GENERAL)
|
||||
-- Append character code `a_code' as query value encoded content into `a_result'.
|
||||
do
|
||||
inspect c
|
||||
when 32 then -- Space
|
||||
a_result.append_code (43) -- 43 '+'
|
||||
when
|
||||
39, -- '
|
||||
58, 64, -- reserved =+ gen-delims: : @
|
||||
33, 36, 40, 41, 42, -- reserved =+ sub-delims: ! $ ( ) *
|
||||
44, 59, 61 -- reserved = sub-delims: , ; =
|
||||
then
|
||||
a_result.append_code (c)
|
||||
when
|
||||
47, -- slash: /
|
||||
63 -- question mark ?
|
||||
then
|
||||
a_result.append_code (c)
|
||||
else
|
||||
append_encoded_character_code_to (c, a_result)
|
||||
end
|
||||
end
|
||||
|
||||
append_path_segment_encoded_character_code_to (c: NATURAL_32; a_result: STRING_GENERAL)
|
||||
-- Append character code `a_code' as query name encoded content into `a_result'.
|
||||
do
|
||||
append_encoded_character_code_to (c, a_result)
|
||||
end
|
||||
|
||||
feature -- Percent encoding: character
|
||||
|
||||
append_percent_encoded_character_code_to (a_code: NATURAL_32; a_result: STRING_GENERAL)
|
||||
-- Append character code `a_code' as percent-encoded content into `a_result'
|
||||
do
|
||||
if a_code > 0xFF then
|
||||
-- Unicode
|
||||
append_percent_encoded_unicode_character_code_to (a_code, a_result)
|
||||
elseif a_code > 0x7F then
|
||||
-- Extended ASCII
|
||||
-- This requires percent-encoding on UTF-8 converted character.
|
||||
append_percent_encoded_unicode_character_code_to (a_code, a_result)
|
||||
else
|
||||
-- ASCII
|
||||
append_percent_encoded_ascii_character_code_to (a_code, a_result)
|
||||
end
|
||||
ensure
|
||||
appended: a_result.count > old a_result.count
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation: character encoding
|
||||
|
||||
append_percent_encoded_ascii_character_code_to (a_code: NATURAL_32; a_result: STRING_GENERAL)
|
||||
-- Append extended ascii character code `a_code' as percent-encoded content into `a_result'
|
||||
-- Note: it does not UTF-8 convert this extended ASCII.
|
||||
require
|
||||
is_extended_ascii: a_code <= 0xFF
|
||||
local
|
||||
c: INTEGER
|
||||
do
|
||||
if a_code > 0xFF then
|
||||
-- Unicode
|
||||
append_percent_encoded_unicode_character_code_to (a_code, a_result)
|
||||
else
|
||||
-- Extended ASCII
|
||||
c := a_code.to_integer_32
|
||||
a_result.append_code (37) -- 37 '%%'
|
||||
a_result.append_code (hex_digit [c |>> 4])
|
||||
a_result.append_code (hex_digit [c & 0xF])
|
||||
end
|
||||
ensure
|
||||
appended: a_result.count > old a_result.count
|
||||
end
|
||||
|
||||
append_percent_encoded_unicode_character_code_to (a_code: NATURAL_32; a_result: STRING_GENERAL)
|
||||
-- Append Unicode character code `a_code' as UTF-8 and percent-encoded content into `a_result'
|
||||
-- Note: it does include UTF-8 conversion of extended ASCII and Unicode.
|
||||
do
|
||||
if a_code <= 0x7F then
|
||||
-- 0xxxxxxx
|
||||
append_percent_encoded_ascii_character_code_to (a_code, a_result)
|
||||
elseif a_code <= 0x7FF then
|
||||
-- 110xxxxx 10xxxxxx
|
||||
append_percent_encoded_ascii_character_code_to ((a_code |>> 6) | 0xC0, a_result)
|
||||
append_percent_encoded_ascii_character_code_to ((a_code & 0x3F) | 0x80, a_result)
|
||||
elseif a_code <= 0xFFFF then
|
||||
-- 1110xxxx 10xxxxxx 10xxxxxx
|
||||
append_percent_encoded_ascii_character_code_to ((a_code |>> 12) | 0xE0, a_result)
|
||||
append_percent_encoded_ascii_character_code_to (((a_code |>> 6) & 0x3F) | 0x80, a_result)
|
||||
append_percent_encoded_ascii_character_code_to ((a_code & 0x3F) | 0x80, a_result)
|
||||
else
|
||||
-- c <= 1FFFFF - there are no higher code points
|
||||
-- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
append_percent_encoded_ascii_character_code_to ((a_code |>> 18) | 0xF0, a_result)
|
||||
append_percent_encoded_ascii_character_code_to (((a_code |>> 12) & 0x3F) | 0x80, a_result)
|
||||
append_percent_encoded_ascii_character_code_to (((a_code |>> 6) & 0x3F) | 0x80, a_result)
|
||||
append_percent_encoded_ascii_character_code_to ((a_code & 0x3F) | 0x80, a_result)
|
||||
end
|
||||
ensure
|
||||
appended: a_result.count > old a_result.count
|
||||
end
|
||||
|
||||
feature -- Percent decoding
|
||||
|
||||
append_percent_decoded_string_to (v: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
|
||||
-- Append to `a_result' a string equivalent to the percent-encoded string `v'
|
||||
--| Note that is `a_result' is a STRING_8, any Unicode character will be kept as UTF-8
|
||||
local
|
||||
i,n: INTEGER
|
||||
c: NATURAL_32
|
||||
pr: CELL [INTEGER]
|
||||
a_result_is_string_32: BOOLEAN
|
||||
do
|
||||
a_result_is_string_32 := attached {STRING_32} a_result
|
||||
from
|
||||
i := 1
|
||||
create pr.put (i)
|
||||
n := v.count
|
||||
until
|
||||
i > n
|
||||
loop
|
||||
c := v.code (i)
|
||||
inspect c
|
||||
when 43 then -- 43 '+'
|
||||
-- Some implementation are replacing spaces with "+" instead of "%20"
|
||||
a_result.append_code (32) -- 32 ' '
|
||||
when 37 then -- 37 '%%'
|
||||
-- An escaped character ?
|
||||
if i = n then -- Error?
|
||||
a_result.append_code (c)
|
||||
else
|
||||
if a_result_is_string_32 then
|
||||
-- Convert UTF-8 to UTF-32
|
||||
pr.replace (i)
|
||||
c := next_percent_decoded_unicode_character_code (v, pr)
|
||||
a_result.append_code (c)
|
||||
i := pr.item
|
||||
else
|
||||
-- Keep UTF-8
|
||||
pr.replace (i)
|
||||
c := next_percent_decoded_character_code (v, pr)
|
||||
a_result.append_code (c)
|
||||
i := pr.item
|
||||
end
|
||||
end
|
||||
else
|
||||
if c <= 0x7F then
|
||||
a_result.append_code (c)
|
||||
else
|
||||
if a_result_is_string_32 then
|
||||
a_result.append_code (c)
|
||||
else
|
||||
-- Keep the percent encoded char for non string 32.
|
||||
append_percent_encoded_character_code_to (c, a_result)
|
||||
end
|
||||
end
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation: decoding
|
||||
|
||||
next_percent_decoded_character_code (v: READABLE_STRING_GENERAL; a_position: CELL [INTEGER]): NATURAL_32
|
||||
-- Character decoded from string `v' starting from index `a_position.item'
|
||||
-- note: it also updates `a_position.item' to indicate the new index position.
|
||||
require
|
||||
valid_start: a_position.item <= v.count
|
||||
is_percent_char: v.code (a_position.item) = 37 -- 37 '%%'
|
||||
local
|
||||
c: NATURAL_32
|
||||
i, n: INTEGER
|
||||
not_a_digit: BOOLEAN
|
||||
ascii_pos: NATURAL_32
|
||||
ival: NATURAL_32
|
||||
pos: INTEGER
|
||||
c_is_digit: BOOLEAN
|
||||
do
|
||||
--| pos is index in stream of escape character ('%')
|
||||
pos := a_position.item
|
||||
c := v.code (pos + 1)
|
||||
if c = 85 or c = 117 then -- 117 'u' 85 'U'
|
||||
-- NOTE: this is not a standard, but it can occur, so use this for decoding only
|
||||
-- An escaped Unicode (ucs2) value, from ECMA scripts
|
||||
-- has the form: %u<n> where <n> is the UCS value
|
||||
-- of the character (two byte integer, one to 4 chars
|
||||
-- after escape sequence).
|
||||
-- See: http://en.wikipedia.org/wiki/Percent-encoding#Non-standard_implementations
|
||||
-- UTF-8 result can be 1 to 4 characters.
|
||||
from
|
||||
i := pos + 2
|
||||
n := v.count
|
||||
until
|
||||
(i > n) or not_a_digit
|
||||
loop
|
||||
c := v.code (i)
|
||||
c_is_digit := (48 <= c and c <= 57) -- DIGIT: 0 .. 9
|
||||
if
|
||||
c_is_digit
|
||||
or (97 <= c and c <= 102) -- ALPHA: a..f
|
||||
or (65 <= c and c <= 70) -- ALPHA: A..F
|
||||
then
|
||||
ival := ival * 16
|
||||
if c_is_digit then
|
||||
ival := ival + (c - 48) -- 48 '0'
|
||||
else
|
||||
if c > 70 then -- a..f
|
||||
ival := ival + (c - 97) + 10 -- 97 'a'
|
||||
else -- A..F
|
||||
ival := ival + (c - 65) + 10 -- 65 'A'
|
||||
end
|
||||
end
|
||||
i := i + 1
|
||||
else
|
||||
not_a_digit := True
|
||||
i := i - 1
|
||||
end
|
||||
end
|
||||
a_position.replace (i)
|
||||
Result := ival
|
||||
else
|
||||
-- ASCII char?
|
||||
ascii_pos := hexadecimal_string_to_natural_32 (v.substring (pos + 1, pos + 2))
|
||||
Result := ascii_pos
|
||||
a_position.replace (pos + 2)
|
||||
end
|
||||
end
|
||||
|
||||
next_percent_decoded_unicode_character_code (v: READABLE_STRING_GENERAL; a_position: CELL [INTEGER]): NATURAL_32
|
||||
-- Next decoded character from `v' at position `a_position.item'
|
||||
-- note: it also updates `a_position' to indicate the new index position.
|
||||
require
|
||||
valid_start: a_position.item <= v.count
|
||||
is_percent_char: v.code (a_position.item) = 37 -- 37 '%%'
|
||||
local
|
||||
n, j: INTEGER
|
||||
c: NATURAL_32
|
||||
c1, c2, c3, c4: NATURAL_32
|
||||
pr: CELL [INTEGER]
|
||||
do
|
||||
create pr.put (a_position.item)
|
||||
c1 := next_percent_decoded_character_code (v, pr)
|
||||
|
||||
j := pr.item
|
||||
n := v.count
|
||||
|
||||
Result := c1
|
||||
a_position.replace (j)
|
||||
|
||||
if c1 <= 0x7F then
|
||||
-- 0xxxxxxx
|
||||
Result := c1
|
||||
elseif c1 <= 0xDF then
|
||||
-- 110xxxxx 10xxxxxx
|
||||
if j + 2 <= n then
|
||||
c := v.code (j + 1)
|
||||
if c = 37 then -- 37 '%%'
|
||||
pr.replace (j + 1)
|
||||
c2 := next_percent_decoded_character_code (v, pr)
|
||||
j := pr.item
|
||||
Result := (
|
||||
((c1 & 0x1F) |<< 6) |
|
||||
( c2 & 0x3F )
|
||||
)
|
||||
a_position.replace (j)
|
||||
else
|
||||
-- Do not try to decode
|
||||
end
|
||||
end
|
||||
elseif c1 <= 0xEF then
|
||||
-- 1110xxxx 10xxxxxx 10xxxxxx
|
||||
if j + 2 <= n then
|
||||
c := v.code (j + 1)
|
||||
if c = 37 then -- 37 '%%'
|
||||
pr.replace (j + 1)
|
||||
c2 := next_percent_decoded_character_code (v, pr)
|
||||
j := pr.item
|
||||
if j + 2 <= n then
|
||||
c := v.code (j + 1)
|
||||
if c = 37 then -- 37 '%%'
|
||||
pr.replace (j + 1)
|
||||
c3 := next_percent_decoded_character_code (v, pr)
|
||||
j := pr.item
|
||||
|
||||
Result := (
|
||||
((c1 & 0xF) |<< 12) |
|
||||
((c2 & 0x3F) |<< 6) |
|
||||
( c3 & 0x3F )
|
||||
)
|
||||
a_position.replace (j)
|
||||
else
|
||||
-- Do not try to decode
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Do not try to decode
|
||||
end
|
||||
end
|
||||
elseif c1 <= 0xF7 then
|
||||
-- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
|
||||
if j + 2 <= n then
|
||||
c := v.code (j + 1)
|
||||
if c = 37 then -- 37 '%%'
|
||||
pr.replace (j + 1)
|
||||
c2 := next_percent_decoded_character_code (v, pr)
|
||||
j := pr.item
|
||||
if j + 2 <= n then
|
||||
c := v.code (j + 1)
|
||||
if c = 37 then -- 37 '%%'
|
||||
pr.replace (j + 1)
|
||||
c3 := next_percent_decoded_character_code (v, pr)
|
||||
j := pr.item
|
||||
if j + 2 <= n then
|
||||
c := v.code (j + 1)
|
||||
if c = 37 then -- 37 '%%'
|
||||
pr.replace (j + 1)
|
||||
c4 := next_percent_decoded_character_code (v, pr)
|
||||
j := pr.item
|
||||
|
||||
a_position.replace (j)
|
||||
|
||||
Result := (
|
||||
((c1 & 0x7) |<< 18 ) |
|
||||
((c2 & 0x3F) |<< 12) |
|
||||
((c3 & 0x3F) |<< 6) |
|
||||
( c4 & 0x3F )
|
||||
)
|
||||
else
|
||||
-- Do not try to decode
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Do not try to decode
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Do not try to decode
|
||||
end
|
||||
end
|
||||
else
|
||||
Result := c1
|
||||
end
|
||||
end
|
||||
|
||||
feature -- RFC and characters
|
||||
|
||||
is_hexa_decimal_character (c: CHARACTER_32): BOOLEAN
|
||||
-- Is hexadecimal character ?
|
||||
do
|
||||
Result := ('a' <= c and c <= 'f') or ('A' <= c and c <= 'F') -- HEXA
|
||||
or ('0' <= c and c <= '9') -- DIGIT
|
||||
end
|
||||
|
||||
is_alpha_or_digit_character (c: CHARACTER_32): BOOLEAN
|
||||
-- Is ALPHA or DIGIT character ?
|
||||
do
|
||||
Result := ('a' <= c and c <= 'z') or ('A' <= c and c <= 'Z') -- ALPHA
|
||||
or ('0' <= c and c <= '9') -- DIGIT
|
||||
end
|
||||
|
||||
is_alpha_character (c: CHARACTER_32): BOOLEAN
|
||||
-- Is ALPHA character ?
|
||||
do
|
||||
Result := ('a' <= c and c <= 'z') or ('A' <= c and c <= 'Z')
|
||||
end
|
||||
|
||||
is_digit_character (c: CHARACTER_32): BOOLEAN
|
||||
-- Is DIGIT character ?
|
||||
do
|
||||
Result := ('0' <= c and c <= '9')
|
||||
end
|
||||
|
||||
is_unreserved_character (c: CHARACTER_32): BOOLEAN
|
||||
-- unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
do
|
||||
if
|
||||
('a' <= c and c <= 'z') -- ALPHA
|
||||
or ('A' <= c and c <= 'Z') -- ALPHA
|
||||
or ('0' <= c and c <= '9') -- DIGIT
|
||||
then
|
||||
Result := True
|
||||
else
|
||||
inspect c
|
||||
when '-', '_', '.', '~' then -- unreserved
|
||||
Result := True
|
||||
else
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
is_reserved_character (c: CHARACTER_32): BOOLEAN
|
||||
-- reserved = gen-delims / sub-delims
|
||||
do
|
||||
Result := is_gen_delims_character (c) or is_sub_delims_character (c)
|
||||
end
|
||||
|
||||
is_gen_delims_character (c: CHARACTER_32): BOOLEAN
|
||||
-- gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
|
||||
do
|
||||
inspect c
|
||||
when ':' , '/', '?' , '#' , '[' , ']' , '@' then
|
||||
Result := True
|
||||
else
|
||||
end
|
||||
end
|
||||
|
||||
is_sub_delims_character (c: CHARACTER_32): BOOLEAN
|
||||
-- sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
-- / "*" / "+" / "," / ";" / "="
|
||||
do
|
||||
inspect c
|
||||
when '!' , '$' , '&' , '%'' , '(' , ')' , '*' , '+' , ',' , ';' , '=' then -- sub-delims
|
||||
Result := True
|
||||
else
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
hex_digit: SPECIAL [NATURAL_32]
|
||||
-- Hexadecimal digits.
|
||||
once
|
||||
create Result.make_filled (0, 16)
|
||||
Result [0] := {NATURAL_32} 48 -- 48 '0'
|
||||
Result [1] := {NATURAL_32} 49 -- 49 '1'
|
||||
Result [2] := {NATURAL_32} 50 -- 50 '2'
|
||||
Result [3] := {NATURAL_32} 51 -- 51 '3'
|
||||
Result [4] := {NATURAL_32} 52 -- 52 '4'
|
||||
Result [5] := {NATURAL_32} 53 -- 53 '5'
|
||||
Result [6] := {NATURAL_32} 54 -- 54 '6'
|
||||
Result [7] := {NATURAL_32} 55 -- 55 '7'
|
||||
Result [8] := {NATURAL_32} 56 -- 56 '8'
|
||||
Result [9] := {NATURAL_32} 57 -- 57 '9'
|
||||
Result [10] := {NATURAL_32} 65 -- 65 'A'
|
||||
Result [11] := {NATURAL_32} 66 -- 66 'B'
|
||||
Result [12] := {NATURAL_32} 67 -- 67 'C'
|
||||
Result [13] := {NATURAL_32} 68 -- 68 'D'
|
||||
Result [14] := {NATURAL_32} 69 -- 69 'E'
|
||||
Result [15] := {NATURAL_32} 70 -- 70 'F'
|
||||
end
|
||||
|
||||
is_hexa_decimal (a_string: READABLE_STRING_GENERAL): BOOLEAN
|
||||
-- Is `a_string' a valid hexadecimal sequence?
|
||||
local
|
||||
l_convertor: like ctoi_convertor
|
||||
do
|
||||
l_convertor := ctoi_convertor
|
||||
l_convertor.parse_string_with_type (a_string, {NUMERIC_INFORMATION}.type_natural_32)
|
||||
Result := l_convertor.is_integral_integer
|
||||
end
|
||||
|
||||
hexadecimal_string_to_natural_32 (a_hex_string: READABLE_STRING_GENERAL): NATURAL_32
|
||||
-- Convert hexadecimal value `a_hex_string' to its corresponding NATURAL_32 value.
|
||||
require
|
||||
is_hexa: is_hexa_decimal (a_hex_string)
|
||||
local
|
||||
l_convertor: like ctoi_convertor
|
||||
do
|
||||
l_convertor := ctoi_convertor
|
||||
l_convertor.parse_string_with_type (a_hex_string, {NUMERIC_INFORMATION}.type_no_limitation)
|
||||
Result := l_convertor.parsed_natural_32
|
||||
end
|
||||
|
||||
ctoi_convertor: HEXADECIMAL_STRING_TO_INTEGER_CONVERTER
|
||||
-- Converter used to convert string to integer or natural.
|
||||
once
|
||||
create Result.make
|
||||
Result.set_leading_separators_acceptable (False)
|
||||
Result.set_trailing_separators_acceptable (False)
|
||||
ensure
|
||||
ctoi_convertor_not_void: Result /= Void
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -82,9 +82,6 @@ feature -- Execution
|
||||
|
||||
--| URL
|
||||
l_url := url
|
||||
if ctx /= Void then
|
||||
append_parameters_to_url (ctx.query_parameters, l_url)
|
||||
end
|
||||
|
||||
if session.is_header_sent_verbose then
|
||||
io.error.put_string ("> Sending:%N")
|
||||
@@ -171,7 +168,7 @@ feature -- Execution
|
||||
then
|
||||
if l_ct.starts_with ("application/x-www-form-urlencoded") then
|
||||
-- Content-Type is already application/x-www-form-urlencoded
|
||||
l_upload_data := ctx.form_parameters_to_url_encoded_string
|
||||
l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
|
||||
elseif l_ct.starts_with ("multipart/form-data") then
|
||||
l_use_curl_form := True
|
||||
else
|
||||
@@ -179,7 +176,7 @@ feature -- Execution
|
||||
l_use_curl_form := True
|
||||
end
|
||||
else
|
||||
l_upload_data := ctx.form_parameters_to_url_encoded_string
|
||||
l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
|
||||
end
|
||||
else
|
||||
l_use_curl_form := True
|
||||
@@ -199,6 +196,14 @@ feature -- Execution
|
||||
)
|
||||
l_form_data.forth
|
||||
end
|
||||
if l_upload_filename /= Void then
|
||||
curl.formadd_string_string (l_form, l_last,
|
||||
{CURL_FORM_CONSTANTS}.curlform_copyname, "file",
|
||||
{CURL_FORM_CONSTANTS}.curlform_file, l_upload_filename,
|
||||
{CURL_FORM_CONSTANTS}.curlform_end
|
||||
)
|
||||
l_upload_filename := Void
|
||||
end
|
||||
l_last.release_item
|
||||
curl_easy.setopt_form (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httppost, l_form)
|
||||
end
|
||||
|
||||
@@ -41,7 +41,7 @@ feature -- Custom
|
||||
local
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, a_method, Current, ctx)
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (url (a_path, ctx), a_method, Current, ctx)
|
||||
Result := req.response
|
||||
end
|
||||
|
||||
@@ -154,7 +154,7 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
end
|
||||
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, a_method, Current, ctx)
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (url (a_path, ctx), a_method, Current, ctx)
|
||||
Result := req.response
|
||||
|
||||
if f /= Void then
|
||||
@@ -176,7 +176,7 @@ feature {LIBCURL_HTTP_CLIENT_REQUEST} -- Curl implementation
|
||||
|
||||
|
||||
;note
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -156,7 +156,7 @@ feature -- Access
|
||||
end
|
||||
|
||||
create l_request_uri.make_from_string (l_uri.path)
|
||||
if attached l_uri.query as l_query then
|
||||
if attached l_uri.query as l_query and then not l_query.is_empty then
|
||||
l_request_uri.append_character ('?')
|
||||
l_request_uri.append (l_query)
|
||||
end
|
||||
@@ -198,7 +198,7 @@ feature -- Access
|
||||
attached headers.item ("Content-Type") as l_ct
|
||||
then
|
||||
if l_ct.starts_with ("application/x-www-form-urlencoded") then
|
||||
l_upload_data := ctx.form_parameters_to_url_encoded_string
|
||||
l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
|
||||
elseif l_ct.starts_with ("multipart/form-data") then
|
||||
-- create form using multipart/form-data encoding
|
||||
l_boundary := new_mime_boundary (l_form_data)
|
||||
@@ -208,12 +208,12 @@ feature -- Access
|
||||
-- not supported !
|
||||
-- Send as form-urlencoded
|
||||
headers.extend ("application/x-www-form-urlencoded", "Content-Type")
|
||||
l_upload_data := ctx.form_parameters_to_url_encoded_string
|
||||
l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
|
||||
end
|
||||
else
|
||||
-- Send as form-urlencoded
|
||||
headers.extend ("application/x-www-form-urlencoded", "Content-Type")
|
||||
l_upload_data := ctx.form_parameters_to_url_encoded_string
|
||||
l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
|
||||
end
|
||||
headers.extend (l_upload_data.count.out, "Content-Length")
|
||||
if l_is_chunked_transfer_encoding then
|
||||
@@ -246,7 +246,7 @@ feature -- Access
|
||||
elseif l_upload_filename /= Void then
|
||||
check ctx.has_upload_filename end
|
||||
create l_upload_file.make_with_name (l_upload_filename)
|
||||
if l_upload_file.exists and then l_upload_file.readable then
|
||||
if l_upload_file.exists and then l_upload_file.is_access_readable then
|
||||
if not l_is_chunked_transfer_encoding then
|
||||
headers.extend (l_upload_file.count.out, "Content-Length")
|
||||
end
|
||||
@@ -495,6 +495,7 @@ feature {NONE} -- Helpers
|
||||
across
|
||||
a_form_parameters as ic
|
||||
loop
|
||||
Result.append ("--")
|
||||
Result.append (a_mime_boundary)
|
||||
Result.append (http_end_of_header_line)
|
||||
Result.append ("Content-Disposition: form-data; name=")
|
||||
@@ -519,7 +520,7 @@ feature {NONE} -- Helpers
|
||||
else
|
||||
l_mime_type := "application/octet-stream"
|
||||
end
|
||||
|
||||
Result.append ("--")
|
||||
Result.append (a_mime_boundary)
|
||||
Result.append (http_end_of_header_line)
|
||||
Result.append ("Content-Disposition: form-data; name=%"")
|
||||
@@ -542,6 +543,7 @@ feature {NONE} -- Helpers
|
||||
end
|
||||
Result.append (http_end_of_header_line)
|
||||
end
|
||||
Result.append ("--")
|
||||
Result.append (a_mime_boundary)
|
||||
Result.append ("--") --| end
|
||||
end
|
||||
@@ -907,7 +909,7 @@ feature {NONE} -- Helpers
|
||||
create ran.set_seed (i) -- FIXME: use a real random seed.
|
||||
ran.start
|
||||
ran.forth
|
||||
n := (20 * ran.real_item).truncated_to_integer
|
||||
n := (10 * ran.real_item).truncated_to_integer
|
||||
create Result.make_filled ('-', 3 + n)
|
||||
s := "_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
from
|
||||
|
||||
@@ -67,7 +67,7 @@ feature -- Custom
|
||||
local
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
do
|
||||
create {NET_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, a_method, Current, ctx)
|
||||
create {NET_HTTP_CLIENT_REQUEST} req.make (url (a_path, ctx), a_method, Current, ctx)
|
||||
Result := req.response
|
||||
end
|
||||
|
||||
@@ -167,12 +167,12 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
end
|
||||
|
||||
create {NET_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, a_method, Current, ctx)
|
||||
create {NET_HTTP_CLIENT_REQUEST} req.make (url (a_path, ctx), a_method, Current, ctx)
|
||||
Result := req.response
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -25,7 +25,7 @@ feature -- Custom
|
||||
|
||||
custom (a_method: READABLE_STRING_8; a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
do
|
||||
create Result.make (base_url + a_path)
|
||||
create Result.make (url (a_path, ctx))
|
||||
end
|
||||
|
||||
custom_with_upload_data (a_method: READABLE_STRING_8; a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; data: READABLE_STRING_8): HTTP_CLIENT_RESPONSE
|
||||
@@ -98,7 +98,7 @@ feature -- Status report
|
||||
-- Is interface usable?
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -34,6 +34,11 @@ feature -- Tests
|
||||
test_post_with_form_data
|
||||
end
|
||||
|
||||
libcurl_test_post_with_uncommon_form_data
|
||||
do
|
||||
test_post_with_uncommon_form_data
|
||||
end
|
||||
|
||||
libcurl_test_post_with_file
|
||||
do
|
||||
test_post_with_file
|
||||
|
||||
@@ -34,6 +34,11 @@ feature -- Tests
|
||||
test_post_with_form_data
|
||||
end
|
||||
|
||||
net_test_post_with_uncommon_form_data
|
||||
do
|
||||
test_post_with_uncommon_form_data
|
||||
end
|
||||
|
||||
net_test_post_with_file
|
||||
do
|
||||
test_post_with_file
|
||||
@@ -69,4 +74,9 @@ feature -- Tests
|
||||
test_post_with_file_using_chunked_transfer_encoding
|
||||
end
|
||||
|
||||
net_test_get_with_query_parameters
|
||||
do
|
||||
test_get_with_query_parameters
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
note
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
@@ -21,7 +21,10 @@ feature -- Initialization
|
||||
on_prepare
|
||||
do
|
||||
Precursor
|
||||
global_requestbin_path := new_requestbin_path
|
||||
global_requestbin_path := "/s0jkhhs0"
|
||||
if global_requestbin_path = Void then
|
||||
global_requestbin_path := new_requestbin_path
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Factory
|
||||
@@ -49,6 +52,9 @@ feature -- Requestbin
|
||||
i := l_content.substring_index ("%"name%":", 1)
|
||||
if i > 0 then
|
||||
j := l_content.index_of (',', i + 1)
|
||||
if j = 0 then
|
||||
j := l_content.index_of ('}', i + 1)
|
||||
end
|
||||
if j > 0 then
|
||||
Result := l_content.substring (i + 7, j - 1)
|
||||
Result.adjust
|
||||
@@ -61,6 +67,7 @@ feature -- Requestbin
|
||||
if not Result.starts_with ("/") then
|
||||
Result.prepend_character ('/')
|
||||
end
|
||||
print ("new_requestbin_path => http://requestb.in" + Result + "?inspect%N")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -108,8 +115,55 @@ feature -- Factory
|
||||
-- check requestbin to ensure the form parameters are correctly received
|
||||
sess := new_session ("http://requestb.in")
|
||||
create l_ctx.make
|
||||
l_ctx.form_parameters.extend ("First Value", "First Key")
|
||||
l_ctx.form_parameters.extend ("Second Value", "Second Key")
|
||||
l_ctx.add_form_parameter ("First Key", "First Value")
|
||||
l_ctx.add_form_parameter ("Second Key", "Second Value")
|
||||
l_ctx.add_form_parameter ("unicode", {STRING_32} "Hello / 你好 !")
|
||||
l_ctx.add_form_parameter ({STRING_32} "Field 你好 !", "How are you?")
|
||||
create h.make_empty
|
||||
if
|
||||
attached sess.post (requestbin_path, l_ctx, "") as res and then
|
||||
attached res.headers as hds
|
||||
then
|
||||
across
|
||||
hds as c
|
||||
loop
|
||||
h.append (c.item.name + ": " + c.item.value + "%R%N")
|
||||
end
|
||||
end
|
||||
print (h)
|
||||
else
|
||||
assert ("Has requestbin path", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_post_with_uncommon_form_data
|
||||
local
|
||||
sess: HTTP_CLIENT_SESSION
|
||||
h: STRING_8
|
||||
l_ctx: HTTP_CLIENT_REQUEST_CONTEXT
|
||||
do
|
||||
if attached global_requestbin_path as requestbin_path then
|
||||
|
||||
-- POST REQUEST WITH FORM DATA
|
||||
-- check requestbin to ensure the form parameters are correctly received
|
||||
sess := new_session ("http://requestb.in")
|
||||
create l_ctx.make
|
||||
|
||||
l_ctx.add_form_parameter ("title", "Eiffel World!") -- space and !
|
||||
l_ctx.add_form_parameter ("path", "foo/bar") -- slash
|
||||
l_ctx.add_form_parameter ("unreserved", ":!@[]{}()*") -- ...
|
||||
l_ctx.add_form_parameter ("reserved", "+=?&_#_") -- ...
|
||||
l_ctx.add_form_parameter ("a=b", "a=b") -- equal sign
|
||||
l_ctx.add_form_parameter ("test", "!$&'()*") --
|
||||
l_ctx.add_form_parameter ("lst[a][b]", "[123][456]") -- brackets
|
||||
l_ctx.add_form_parameter ("pos{1,2}", "loc{a,b}") -- curly brackets
|
||||
l_ctx.add_form_parameter ("?foo", "?bar") -- question mark
|
||||
l_ctx.add_form_parameter ("?", "?") -- question mark
|
||||
l_ctx.add_form_parameter ("&bar", "&bar") -- ampersand
|
||||
l_ctx.add_form_parameter ("&", "&") -- ampersand
|
||||
|
||||
assert ("form data well generated", l_ctx.form_parameters_to_x_www_form_url_encoded_string.same_string ("title=Eiffel+World!&path=foo%%2Fbar&unreserved=%%3A!%%40%%5B%%5D%%7B%%7D()*&reserved=%%2B%%3D%%3F%%26_%%23_&a%%3Db=a%%3Db&test=!%%24%%26'()*&lst%%5Ba%%5D%%5Bb%%5D=%%5B123%%5D%%5B456%%5D&pos%%7B1%%2C2%%7D=loc%%7Ba%%2Cb%%7D&%%3Ffoo=%%3Fbar&%%3F=%%3F&%%26bar=%%26bar&%%26=%%26"))
|
||||
|
||||
create h.make_empty
|
||||
if
|
||||
attached sess.post (requestbin_path, l_ctx, "") as res and then
|
||||
@@ -143,7 +197,7 @@ feature -- Factory
|
||||
l_ctx.set_upload_filename ("test.txt")
|
||||
create h.make_empty
|
||||
if
|
||||
attached sess.post (requestbin_path, l_ctx, "") as res and then
|
||||
attached sess.post (requestbin_path, l_ctx, Void) as res and then
|
||||
attached res.headers as hds
|
||||
then
|
||||
across
|
||||
@@ -202,7 +256,7 @@ feature -- Factory
|
||||
-- set filename to a local file
|
||||
sess := new_session ("http://requestb.in")
|
||||
create l_ctx.make
|
||||
l_ctx.set_upload_data ("This is a test for http client.%N")
|
||||
l_ctx.set_upload_data ("name=This is a test for http client.%N")
|
||||
create h.make_empty
|
||||
if
|
||||
attached sess.put (requestbin_path, l_ctx, Void) as res and then
|
||||
@@ -232,10 +286,12 @@ feature -- Factory
|
||||
-- check requestbin to ensure the file and form parameters are correctly received
|
||||
-- set filename to a local file
|
||||
sess := new_session ("http://requestb.in")
|
||||
-- sess := new_session ("http://localhost:9090")
|
||||
create l_ctx.make
|
||||
l_ctx.set_upload_filename ("logo.jpg")
|
||||
l_ctx.form_parameters.extend ("First Value", "First Key")
|
||||
l_ctx.form_parameters.extend ("Second Value", "Second Key")
|
||||
-- l_ctx.set_upload_filename ("logo.jpg")
|
||||
l_ctx.set_upload_filename ("test.txt")
|
||||
l_ctx.add_form_parameter ("First", "Value")
|
||||
l_ctx.add_form_parameter ("Second", "and last value")
|
||||
create h.make_empty
|
||||
if
|
||||
attached sess.post (requestbin_path, l_ctx, Void) as res and then
|
||||
@@ -297,6 +353,7 @@ feature -- Factory
|
||||
sess := new_session ("http://google.com")
|
||||
create h.make_empty
|
||||
if attached sess.get ("/", Void) as res and then attached res.headers as hds then
|
||||
assert("was redirected", res.redirections_count > 0)
|
||||
across
|
||||
hds as c
|
||||
loop
|
||||
@@ -328,6 +385,53 @@ feature -- Factory
|
||||
end
|
||||
end
|
||||
|
||||
test_get_with_query_parameters
|
||||
local
|
||||
sess: HTTP_CLIENT_SESSION
|
||||
h: STRING_8
|
||||
l_ctx: HTTP_CLIENT_REQUEST_CONTEXT
|
||||
q: STRING
|
||||
do
|
||||
if attached global_requestbin_path as requestbin_path then
|
||||
|
||||
-- GET REQUEST WITH A FILE AND FORM DATA
|
||||
-- check requestbin to ensure the file and form parameters are correctly received
|
||||
-- set filename to a local file
|
||||
sess := new_session ("http://requestb.in")
|
||||
create l_ctx.make
|
||||
l_ctx.add_query_parameter ("?", "?first&arg")
|
||||
l_ctx.add_query_parameter ("title", "Eiffel World!")
|
||||
l_ctx.add_query_parameter ("path", "foo/bar")
|
||||
l_ctx.add_query_parameter ("reserved", "+=&?")
|
||||
l_ctx.add_query_parameter ("unreserved", ":!@'()*")
|
||||
l_ctx.add_query_parameter ("unsafe", "%"[]{}")
|
||||
l_ctx.add_query_parameter ("test", "!$&'()*")
|
||||
l_ctx.add_query_parameter ("a&b", "a&b")
|
||||
l_ctx.add_query_parameter ("lst[a][b]", "[abc][123]")
|
||||
l_ctx.add_query_parameter ("foo(a,b)", "bar(1,2)*pi")
|
||||
create q.make_empty
|
||||
l_ctx.append_query_parameters_to_url (q)
|
||||
assert("query", q.same_string ("??=?first%%26arg&title=Eiffel+World!&path=foo/bar&reserved=%%2B=%%26?&unreserved=:!@'()*&unsafe=%%22%%5B%%5D%%7B%%7D&test=!$%%26'()*&a%%26b=a%%26b&lst%%5Ba%%5D%%5Bb%%5D=%%5Babc%%5D%%5B123%%5D&foo(a,b)=bar(1,2)*pi"))
|
||||
|
||||
|
||||
create h.make_empty
|
||||
if
|
||||
attached sess.get (requestbin_path, l_ctx) as res and then
|
||||
attached res.headers as hds
|
||||
then
|
||||
across
|
||||
hds as c
|
||||
loop
|
||||
h.append (c.item.name + ": " + c.item.value + "%R%N")
|
||||
end
|
||||
end
|
||||
print (h)
|
||||
else
|
||||
assert ("Has requestbin path", False)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user