Web form:

- Improvement about web form manipulation (remove a field, set a text value to input fields by name, ...)
 - Improved web form html generation, especially for select and type checkbox
 - Updated the date input field interface with a new set_date_value .

File response:
 - "application/force-download" is not a standard MIME content type, so use "application_octet_stream" instead as default.

Standalone connector:
 - Added expected creation procedure for the service launcher.
 - Added new "secure_port" configuration variable, for SSL standalone service.
   This way, if `is_secure` is True, the server will use `secure_port` (overrides `port` value).

Date:
 - Improved support for RFC 3339 (a profile of ISO 8601)

Removed obsolete and warnings:
 - removed usage of FILE_NAME
 - updated code to avoid implicit conversion from STRING_32 to STRING_8
 - avoid uneed conversion to STRING_8 (when possible)
This commit is contained in:
2020-10-02 15:02:06 +02:00
parent 75380a27fe
commit 30a5e087ae
80 changed files with 444 additions and 260 deletions

View File

@@ -1,6 +1,4 @@
note
description: "Summary description for {HTTP_CLIENT_CONSTANTS}."
author: ""
date: "$Date$"
revision: "$Revision$"
@@ -10,23 +8,19 @@ class
feature -- Auth type
auth_type_id (a_auth_type_string: READABLE_STRING_8): INTEGER
local
s: STRING_8
do
create s.make_from_string (a_auth_type_string)
s.to_lower
if s.same_string_general ("basic") then
if a_auth_type_string.is_case_insensitive_equal ("basic") then
Result := Auth_type_basic
elseif s.same_string_general ("digest") then
elseif a_auth_type_string.is_case_insensitive_equal ("digest") then
Result := Auth_type_digest
elseif s.same_string_general ("any") then
elseif a_auth_type_string.is_case_insensitive_equal ("any") then
Result := Auth_type_any
elseif s.same_string_general ("anysafe") then
elseif a_auth_type_string.is_case_insensitive_equal ("anysafe") then
Result := Auth_type_anysafe
elseif s.same_string_general ("none") then
elseif a_auth_type_string.is_case_insensitive_equal ("none") then
Result := Auth_type_none
end
end
end
Auth_type_none: INTEGER = 0
Auth_type_basic: INTEGER = 1
@@ -35,7 +29,7 @@ feature -- Auth type
Auth_type_anysafe: INTEGER = 4
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -108,7 +108,7 @@ feature {HTTP_CLIENT_SESSION} -- Execution
feature -- Authentication
auth_type: STRING
auth_type: READABLE_STRING_8
-- Set the authentication type for the request.
-- Types: "basic", "digest", "any"
do

View File

@@ -18,7 +18,7 @@ feature {NONE} -- Initialization
do
--| Default values
status := 200
url := a_url
create url.make_from_string (a_url)
create {STRING_8} raw_header.make_empty
end
@@ -46,7 +46,7 @@ feature {HTTP_CLIENT_REQUEST} -- Status setting
feature -- Access
url: STRING_8
url: IMMUTABLE_STRING_8
-- URL associated with Current response
status: INTEGER assign set_status
@@ -163,7 +163,7 @@ feature -- Access
end
c := h.index_of (':', l_start)
if c > 0 then
k := h.substring (l_start, c - 1)
k := h.substring (l_start, c - 1).to_string_8
k.right_adjust
c := c + 1
from until c <= n and not h[c].is_space loop
@@ -290,7 +290,7 @@ feature -- Change
l_has_location: BOOLEAN
l_content_length: INTEGER
s: READABLE_STRING_8
l_status_line,h: detachable STRING_8
l_status_line,h: detachable READABLE_STRING_8
do
from
i := 1
@@ -363,6 +363,7 @@ feature -- Change
-- Set http header `raw_header' to `h'
local
i: INTEGER
rs: READABLE_STRING_8
s: STRING_8
do
raw_header := h
@@ -372,8 +373,9 @@ feature -- Change
--| Set status line, right away.
i := h.index_of ('%N', 1)
if i > 0 then
s := h.substring (1, i - 1)
if s.starts_with ("HTTP/") then
rs := h.substring (1, i - 1)
if rs.starts_with ("HTTP/") then
s := rs.to_string_8
s.right_adjust
set_status_line (s)
end
@@ -405,7 +407,7 @@ feature {NONE} -- Implementation
-- Internal cached value for the headers
;note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -63,10 +63,11 @@ feature -- Access
do
if is_absolute_url (a_path) then
-- Is Absolute url
Result := a_path
Result := a_path.to_string_8
else
Result := base_url + a_path
end
create Result.make_from_string (base_url)
Result.append (a_path)
end
if ctx /= Void then
ctx.append_query_parameters_to_url (Result)
end
@@ -287,7 +288,7 @@ feature -- Access
feature -- Authentication
auth_type: STRING
auth_type: READABLE_STRING_8
-- Set the authentication type for the request.
-- Types: "basic", "digest", "any"

View File

@@ -31,7 +31,7 @@ feature -- Status report
is_available: BOOLEAN
-- Is interface usable?
do
Result := curl.is_dynamic_library_exists
Result := curl.is_api_available
end
feature -- Custom
@@ -139,12 +139,17 @@ feature {NONE} -- Implementation
l_data := ctx.upload_data
if l_data /= Void and a_method.is_case_insensitive_equal_general ("PUT") then
--| Quick and dirty hack using real file, for PUT uploaded data
--| FIXME [2012-05-23]: better use libcurl for that purpose
--| FIXME [2012-05-23]: find better solution with libcurl for that need
if ctx.has_upload_filename then
check put_conflict_file_and_data: False end
end
create f.make_open_write (create {FILE_NAME}.make_temporary_name)
if attached {EXECUTION_ENVIRONMENT}.temporary_directory_path as tmp then
create f.make_open_temporary_with_prefix (tmp.extended ("tmp-libcurl-").name)
else
create f.make_open_temporary_with_prefix ("tmp-libcurl-")
end
f.put_string (l_data)
f.close
check ctx /= Void then
@@ -176,7 +181,7 @@ feature {LIBCURL_HTTP_CLIENT_REQUEST} -- Curl implementation
;note
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -125,7 +125,7 @@ feature -- Access
if attached l_uri.host as h then
l_host := h
else
create l_url.make (url)
create l_url.make (url.to_string_8)
l_host := l_url.host
end
@@ -887,7 +887,7 @@ feature {NONE} -- Helpers
invariant
note
copyright: "2011-2018, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -112,7 +112,6 @@ feature -- Test routines
-- New test routine
local
sess: like new_session
h: STRING_8
config: HTTP_CLIENT_SECURE_CONFIG
do
--| Set secure configuration
@@ -160,7 +159,6 @@ feature -- Test routines
test_abs_url
local
sess: like new_session
h: STRING_8
l_url: STRING
do
sess := new_session ("https://www.eiffel.org")

View File

@@ -61,7 +61,7 @@ feature -- Requestbin
j := l_content.index_of ('}', i + 1)
end
if j > 0 then
Result := l_content.substring (i + 7, j - 1)
Result := l_content.substring (i + 7, j - 1).to_string_8
Result.adjust
if Result.starts_with ("%"") then
Result.remove_head (1)

View File

@@ -168,7 +168,7 @@ feature {NONE} -- Implementation
l_target_type: READABLE_STRING_8
l_range: HTTP_ACCEPT_LANGUAGE
l_param_matches: INTEGER
l_element: detachable READABLE_STRING_8
l_element: detachable READABLE_STRING_GENERAL
l_fitness: INTEGER
do
l_best_fitness := -1

View File

@@ -190,7 +190,7 @@ feature {NONE} -- Implementation
target: HTTP_MEDIA_TYPE
range: HTTP_MEDIA_TYPE
param_matches: INTEGER
element: detachable READABLE_STRING_8
element: detachable READABLE_STRING_GENERAL
l_fitness: INTEGER
do
best_fitness := -1

View File

@@ -172,7 +172,7 @@ feature -- Element change
feature -- Parameters: Access
parameter (a_key: READABLE_STRING_8): detachable READABLE_STRING_8
parameter (a_key: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
-- Parameter associated with `a_key', if present
-- otherwise default value of type `STRING'
do
@@ -186,7 +186,7 @@ feature -- Parameters: Access
feature -- Parameters: Status report
has_parameter (a_key: READABLE_STRING_8): BOOLEAN
has_parameter (a_key: READABLE_STRING_GENERAL): BOOLEAN
-- Is there an parameter in the parameters table with key `a_key'?
do
if attached parameters as l_params then
@@ -196,7 +196,7 @@ feature -- Parameters: Status report
feature -- Parameters: Change
put_parameter (a_value: READABLE_STRING_8; a_key: READABLE_STRING_8)
put_parameter (a_value: READABLE_STRING_8; a_key: READABLE_STRING_GENERAL)
-- Insert `a_value' with `a_key' if there is no other item
-- associated with the same key. If present, replace
-- the old value with `a_value'

View File

@@ -35,7 +35,7 @@ feature -- Helpers
across
l_parameters as ic
loop
Result.append ("'" + ic.key + "':'" + ic.item + "',");
Result.append ("'" + {UTF_CONVERTER}.utf_32_string_to_utf_8_string_8 (ic.key) + "':'" + ic.item + "',");
end
end
Result.append ("})")

View File

@@ -38,7 +38,7 @@ feature -- Helpers
across
l_params as ic
loop
Result.append ("'" + ic.key + "':'"+ ic.item + "',");
Result.append ("'" + {UTF_CONVERTER}.utf_32_string_to_utf_8_string_8 (ic.key) + "':'"+ ic.item + "',");
end
end
Result.append ("})")

View File

@@ -41,7 +41,7 @@ feature -- Helper
across
l_params as ic
loop
Result.append ("'" + ic.key + "':'" + ic.item + "',");
Result.append ("'" + {UTF_CONVERTER}.utf_32_string_to_utf_8_string_8 (ic.key) + "':'" + ic.item + "',");
end
end
Result.append ("})")

View File

@@ -47,21 +47,21 @@ feature {NONE} -- Initialization
feature -- Access
name: STRING_8
name: READABLE_STRING_8
-- name of the cookie.
value: STRING_8
value: READABLE_STRING_8
-- value of the cookie.
expiration: detachable STRING_8
expiration: detachable READABLE_STRING_8
-- Value of the Expires attribute.
path: detachable STRING_8
path: detachable READABLE_STRING_8
-- Value of the Path attribute.
-- Path to which the cookie applies.
--| The path "/", specify a cookie that apply to all URLs in your site.
domain: detachable STRING_8
domain: detachable READABLE_STRING_8
-- Value of the Domain attribute.
-- Domain to which the cookies apply.

View File

@@ -42,6 +42,7 @@ create
make_now_utc,
make_from_timestamp,
make_from_string,
make_from_rfc3339_string,
make_from_date_time
feature {NONE} -- Initialization
@@ -65,6 +66,18 @@ feature {NONE} -- Initialization
date_time := dt
elseif attached ansi_c_string_to_date_time (s) as dt then
date_time := dt
elseif attached rfc3339_string_to_date_time (s) as dt then
date_time := dt
else
has_error := True
date_time := epoch
end
end
make_from_rfc3339_string (s: READABLE_STRING_GENERAL)
do
if attached rfc3339_string_to_date_time (s) as dt then
date_time := dt
else
has_error := True
date_time := epoch
@@ -153,10 +166,13 @@ feature -- Conversion to string
append_date_time_to_rfc850_string (date_time, Result)
end
iso8601_string,
rfc3339_string: STRING
-- String representation following RFC 3339.
-- format: [yyyy-mm-ddThh:mi:ssZ]
-- https://www.rfc-editor.org/rfc/rfc3339.txt
-- note: RFC 3339 is a profile of ISO 8601.
-- https://en.wikipedia.org/wiki/ISO_8601
do
create Result.make (25)
append_date_time_to_rfc3339_string (date_time, Result)
@@ -241,6 +257,7 @@ feature -- Conversion into string
s.append (" GMT") -- SPace + GMT
end
append_date_time_to_iso8601_string,
append_date_time_to_rfc3339_string (dt: DATE_TIME; s: STRING_GENERAL)
-- Append `dt' as [yyyy-mm-ddThh:mi:ssZ] format to `s'.
do
@@ -316,7 +333,7 @@ feature -- Helper routines.
create fd.make (2, 2)
fd.show_trailing_zeros
fd.show_zero
r64 := t.fine_second
r64 := t.second + t.fractional_second * 0.01
f := fd.formatted (r64)
if f.ends_with_general (".00") then
append_2_digits_integer_to (t.second, s) -- ss
@@ -670,7 +687,7 @@ feature {NONE} -- Implementation
end
ansi_c_string_to_date_time (s: READABLE_STRING_GENERAL): detachable DATE_TIME
-- String representation of `dt' using the RFC 1123
-- ANSI C date from `s` string representation using the RFC 1123
-- asctime-date = wkday SP date3 SP time SP 4DIGIT
-- date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
-- ; month day (e.g., Jun 2)
@@ -919,10 +936,114 @@ feature {NONE} -- Implementation
end
end
rfc3339_string_to_date_time (s: READABLE_STRING_GENERAL): detachable DATE_TIME
--| 1985-04-12T23:20:50.52Z
--| 1996-12-19T16:39:57-08:00 = 1996-12-20T00:39:57Z
--|
note
EIS: "name=RFC3339", "protocol=URI", "src=https://tools.ietf.org/html/rfc3339"
local
y,mo,d,h,mi,sec, frac_sec: INTEGER
l_off_h, l_off_mi: INTEGER
tmp: READABLE_STRING_GENERAL
i, j, k, pos: INTEGER
err: BOOLEAN
do
if s /= Void then
pos := s.index_of ('T', 1)
if pos > 0 then
i := 1
j := s.index_of ('-', i)
if j > i and j < pos then
y := s.substring (i, j - 1).to_integer
i := j + 1
j := s.index_of ('-', i)
if j > i and j < pos then
mo := s.substring (i, j - 1).to_integer
d := s.substring (j + 1, pos - 1).to_integer
else
err := True
end
else
err := True
end
i := pos + 1
j := s.index_of (':', i)
if j > i then
h := s.substring (i, j - 1).to_integer
i := j + 1
j := s.index_of (':', i)
if j > i then
mi := s.substring (i, j - 1).to_integer
from
k := j + 1
until
k > s.count
or s[k].is_alpha
or s[k] = '+'
or s[k] = '-'
loop
k := k + 1
end
tmp := s.substring (j + 1, k - 1)
j := tmp.index_of ('.', 1)
if j > 0 then
sec := tmp.head (j - 1).to_integer
frac_sec := tmp.substring (j + 1, tmp.count).to_integer
else
sec := tmp.to_integer
end
if k <= s.count then
if s[k] = '+' then
tmp := s.substring (k + 1, s.count)
j := tmp.index_of (':', 1)
if j > 0 then
l_off_h := - tmp.head (j - 1).to_integer
l_off_mi := - tmp.substring (j + 1, tmp.count).to_integer
else
l_off_h := - tmp.to_integer
end
elseif s[k] = '-' then
tmp := s.substring (k + 1, s.count)
j := tmp.index_of (':', 1)
if j > 0 then
l_off_h := + tmp.head (j - 1).to_integer
l_off_mi := + tmp.substring (j + 1, tmp.count).to_integer
else
l_off_h := + tmp.to_integer
end
elseif s[k] = 'Z' then
-- Done
else
end
end
else
err := True
end
else
err := True
end
if not err then
create Result.make (y, mo, d, h, mi, sec)
if frac_sec /= 0 then
Result.set_fractionals (frac_sec)
Result.time.set_fractionals (frac_sec)
end
if l_off_h /= 0 then
Result.hour_add (l_off_h)
end
if l_off_mi /= 0 then
Result.minute_add (l_off_mi)
end
end
end
end
end
invariant
note
copyright: "2011-2019, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -40,9 +40,9 @@ feature -- Query
format_id (a_id: READABLE_STRING_GENERAL): INTEGER
local
s: STRING
s: READABLE_STRING_GENERAL
do
s := a_id.as_string_8.as_lower
s := a_id.as_lower
if s.same_string (json_name) then
Result := json
elseif s.same_string (xml_name) then
@@ -74,7 +74,7 @@ feature -- Query
end
note
copyright: "2011-2011, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -175,7 +175,7 @@ feature -- Header: adding
across
lines as c
loop
line := c.item
line := c.item.to_string_8
if not line.is_empty then
if line [line.count] = '%R' then
line.remove_tail (1)
@@ -223,7 +223,7 @@ feature -- Header: merging
across
lines as c
loop
line := c.item
line := c.item.to_string_8
if not line.is_empty then
if line [line.count] = '%R' then
line.remove_tail (1)
@@ -416,7 +416,7 @@ feature {NONE} -- Implementation: Header queries
end
note
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -106,7 +106,7 @@ feature -- Access
loop
l_line := ic.item
if has_same_header_name (l_line, a_header_name) then
res := l_line.substring (n + 2, l_line.count)
res := l_line.substring (n + 2, l_line.count).to_string_8
res.left_adjust
res.right_adjust
Result := res
@@ -271,25 +271,25 @@ feature -- Content related header
put_content_type_with_charset (a_content_type: READABLE_STRING_8; a_charset: READABLE_STRING_8)
-- Put content type `a_content_type' with `a_charset' as "charset" parameter.
do
put_content_type_with_parameters (a_content_type, <<["charset", a_charset]>>)
put_content_type_with_parameters (a_content_type, {ARRAY [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]} <<["charset", a_charset]>>)
end
add_content_type_with_charset (a_content_type: READABLE_STRING_8; a_charset: READABLE_STRING_8)
-- Same as `put_content_type_with_charset', but allow multiple definition of "Content-Type".
do
add_content_type_with_parameters (a_content_type, <<["charset", a_charset]>>)
add_content_type_with_parameters (a_content_type, {ARRAY [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]} <<["charset", a_charset]>>)
end
put_content_type_with_name (a_content_type: READABLE_STRING_8; a_name: READABLE_STRING_8)
-- Put content type `a_content_type' with `a_name' as "name" parameter.
do
put_content_type_with_parameters (a_content_type, <<["name", a_name]>>)
put_content_type_with_parameters (a_content_type, {ARRAY [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]} <<["name", a_name]>>)
end
add_content_type_with_name (a_content_type: READABLE_STRING_8; a_name: READABLE_STRING_8)
-- same as `put_content_type_with_name', but allow multiple definition of "Content-Type"
do
add_content_type_with_parameters (a_content_type, <<["name", a_name]>>)
add_content_type_with_parameters (a_content_type, {ARRAY [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]} <<["name", a_name]>>)
end
put_content_length (a_length: INTEGER)

View File

@@ -77,10 +77,10 @@ feature {NONE} -- Initialization
-- Look for semi colon as parameter separation
p := s.index_of (';', i)
if p > 0 then
t := s.substring (i, p - 1)
t := s.substring (i, p - 1).to_string_8
create parameters.make_from_substring (s, p + 1, s.count)
else
t := s.substring (i, n)
t := s.substring (i, n).to_string_8
end
-- Remove eventual trailing space
t.right_adjust
@@ -124,7 +124,7 @@ feature -- Access
subtype: READABLE_STRING_8
-- Sub type
has_parameter (a_name: READABLE_STRING_8): BOOLEAN
has_parameter (a_name: READABLE_STRING_GENERAL): BOOLEAN
-- Has Current a parameter?
do
if attached parameters as plst then
@@ -132,7 +132,7 @@ feature -- Access
end
end
parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
-- Value for eventual parameter named `a_name'.
do
if attached parameters as plst then
@@ -159,7 +159,7 @@ feature -- Conversion
loop
res.append_character (';')
res.append_character (' ')
res.append (p.key)
res.append ({UTF_CONVERTER}.utf_32_string_to_utf_8_string_8 (p.key))
res.append_character ('=')
res.append_character ('%"')
res.append (p.item)
@@ -272,13 +272,19 @@ feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
if type /= Void and subtype /= Void then
Result := type + "/" + subtype
if attached type as l_type and attached subtype as l_subtype then
create Result.make_from_string (l_type)
Result.append_character ('/')
Result.append (l_subtype)
if attached parameters as plst then
across
plst as p
loop
Result.append ("; " + p.key + "=" + "%"" + p.item + "%"")
Result.append ("; ")
Result.append ({UTF_CONVERTER}.utf_32_string_to_utf_8_string_8 (p.key))
Result.append ("=%"")
Result.append (p.item)
Result.append_character ('%"')
end
end
else
@@ -290,7 +296,7 @@ invariant
type_and_subtype_not_empty: not has_error implies not type.is_empty and not subtype.is_empty
note
copyright: "2011-2013, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -20,6 +20,8 @@ feature -- Content type : application
-- atom application content-type header
application_force_download: STRING = "application/force-download"
-- Warning: this is not a standard MIME content type.
-- Prefer application_octet_stream as default.
application_javascript: STRING = "application/javascript"
-- JavaScript application content-type header

View File

@@ -9,7 +9,7 @@ class
HTTP_PARAMETER_TABLE
inherit
HASH_TABLE [READABLE_STRING_8, STRING_8]
STRING_TABLE [READABLE_STRING_8]
redefine
empty_duplicate
end
@@ -58,7 +58,8 @@ feature {NONE} -- Implementation
-- and put in `out_end_index' the index after found parameter.
local
n: INTEGER
pn,pv: STRING_8
pn: READABLE_STRING_8
pv: STRING_8
i: INTEGER
p, q: INTEGER
err: BOOLEAN
@@ -86,7 +87,7 @@ feature {NONE} -- Implementation
if s[p+1] = '%"' then
q := s.index_of ('%"', p + 2)
if q > 0 then
pv := s.substring (p + 2, q - 1)
pv := s.substring (p + 2, q - 1).to_string_8
from
i := q + 1
until
@@ -108,7 +109,7 @@ feature {NONE} -- Implementation
if q = 0 then
q := n + 1
end
pv := s.substring (p + 1, q - 1)
pv := s.substring (p + 1, q - 1).to_string_8
out_end_index.replace (q + 1)
end
pv.right_adjust
@@ -138,7 +139,7 @@ feature {NONE} -- Duplication
end
note
copyright: "2011-2013, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -74,4 +74,29 @@ feature -- Test routines
end
test_http_date_rfc3339
local
s: STRING
d: HTTP_DATE
dt: DATE_TIME
do
create dt.make_now_utc
create dt.make (1985, 04, 12, 23, 20, 50)
dt.set_fractionals (52)
dt.time.set_fractionals (52)
create d.make_from_date_time (dt)
s := "1985-04-12T23:20:50.52Z"
assert ("RFC 3339 to string", d.rfc3339_string.same_string (s))
create d.make_from_rfc3339_string (s)
assert ("RFC 3339 from string", not d.has_error and then d.date_time.is_equal (dt))
create d.make_from_rfc3339_string ("1996-12-19T16:39:57-08:00")
assert ("-8hours", d.rfc3339_string.same_string ("1996-12-20T00:39:57Z"))
create d.make_from_rfc3339_string ("1937-01-01T12:00:27.87+00:20")
assert ("-8hours", d.rfc3339_string.same_string ("1937-01-01T11:40:27.87Z"))
end
end

View File

@@ -14,6 +14,7 @@
<concurrency support="none" use="none"/>
</capability>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<library name="http" location="..\http.ecf" readonly="false">
<option>
<assertions precondition="true" postcondition="true" check="true"/>