Merge branch 'jvelilla-ewf_cookie'
This commit is contained in:
351
library/network/protocol/http/src/http_cookie.e
Normal file
351
library/network/protocol/http/src/http_cookie.e
Normal file
@@ -0,0 +1,351 @@
|
||||
note
|
||||
description: "[
|
||||
This class represents the value of a HTTP cookie, transferred in a request.
|
||||
The class has features to build an HTTP cookie.
|
||||
|
||||
Following a newer RFC standard for Cookies http://tools.ietf.org/html/rfc6265
|
||||
|
||||
Domain
|
||||
* WARNING: Some existing user agents treat an absent Domain attribute as if the Domain attribute were present and contained the current host name.
|
||||
* For example, if example.com returns a Set-Cookie header without a Domain attribute, these user agents will erroneously send the cookie to www.example.com as well.
|
||||
|
||||
Max-Age, Expires
|
||||
* If a cookie has both the Max-Age and the Expires attribute, the Max-Age attribute has precedence and controls the expiration date of the cookie.
|
||||
* If a cookie has neither the Max-Age nor the Expires attribute, the user agent will retain the cookie until "the current session is over" (as defined by the user agent).
|
||||
* You will need to call the feature
|
||||
|
||||
HttpOnly, Secure
|
||||
* Note that the HttpOnly attribute is independent of the Secure attribute: a cookie can have both the HttpOnly and the Secure attribute.
|
||||
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=HTTP Cookie specification", "src=http://tools.ietf.org/html/rfc6265", "protocol=uri"
|
||||
class
|
||||
HTTP_COOKIE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8)
|
||||
-- Create an object instance of cookie with name `a_name' and value `a_value'.
|
||||
require
|
||||
a_name_not_blank: a_name /= Void and then not a_name.is_whitespace
|
||||
a_name_has_valid_characters: a_name /= Void and then has_valid_characters (a_name)
|
||||
a_value_has_valid_characters: a_value /= Void and then has_valid_characters (a_value)
|
||||
do
|
||||
set_name (a_name)
|
||||
set_value(a_value)
|
||||
set_max_age (-1)
|
||||
ensure
|
||||
name_set: name = a_name
|
||||
value_set: value = a_value
|
||||
max_age_set: max_age < 0
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING_8
|
||||
-- name of the cookie.
|
||||
|
||||
value: STRING_8
|
||||
-- value of the cookie.
|
||||
|
||||
expiration: detachable STRING_8
|
||||
-- Value of the Expires attribute.
|
||||
|
||||
path: detachable 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
|
||||
-- Value of the Domain attribute.
|
||||
-- Domain to which the cookies apply.
|
||||
|
||||
secure: BOOLEAN
|
||||
-- Value of the Secure attribute.
|
||||
-- By default False.
|
||||
--| Indicate if the cookie should only be sent over secured(encrypted connections, for example SSL).
|
||||
|
||||
http_only: BOOLEAN
|
||||
-- Value of the http_only attribute.
|
||||
-- By default false.
|
||||
--| Limits the scope of the cookie to HTTP requests.
|
||||
|
||||
max_age: INTEGER
|
||||
-- Value of the Max-Age attribute.
|
||||
--| How much time in seconds should elapsed before the cookie expires.
|
||||
--| By default max_age < 0 indicate a cookie will last only for the current user-agent (Browser, etc) session.
|
||||
--| A value of 0 instructs the user-agent to delete the cookie.
|
||||
|
||||
has_valid_characters (a_name: READABLE_STRING_8):BOOLEAN
|
||||
-- Has `a_name' valid characters for cookies?
|
||||
local
|
||||
l_iterator: STRING_ITERATION_CURSOR
|
||||
l_found: BOOLEAN
|
||||
do
|
||||
create l_iterator.make (a_name)
|
||||
Result := True
|
||||
across
|
||||
l_iterator as ic
|
||||
until
|
||||
l_found
|
||||
loop
|
||||
if not is_valid_character (ic.item.natural_32_code) then
|
||||
Result := False
|
||||
l_found := True
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
include_max_age: BOOLEAN
|
||||
-- Does the Set-Cookie header include Max-Age attribute?
|
||||
--|By default will include both.
|
||||
|
||||
include_expires: BOOLEAN
|
||||
-- Does the Set-Cookie header include Expires attribute?
|
||||
--|By default will include both.
|
||||
|
||||
|
||||
is_valid_rfc1123_date (a_string: READABLE_STRING_8): BOOLEAN
|
||||
-- Is the date represented by `a_string' a valid rfc1123 date?
|
||||
local
|
||||
d: HTTP_DATE
|
||||
do
|
||||
create d.make_from_string (a_string)
|
||||
Result := not d.has_error and then d.rfc1123_string.same_string (a_string)
|
||||
end
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
set_name (a_name: READABLE_STRING_8)
|
||||
-- Set `name' with `a_name'.
|
||||
require
|
||||
a_name_not_blank: a_name /= Void and then not a_name.is_whitespace
|
||||
a_name_has_valid_characters: a_name /= Void and then has_valid_characters (a_name)
|
||||
do
|
||||
name := a_name
|
||||
ensure
|
||||
name_set: name = a_name
|
||||
end
|
||||
|
||||
set_value (a_value: READABLE_STRING_8)
|
||||
-- Set `value' with `a_value'.
|
||||
require
|
||||
a_value_has_valid_characters: a_value /= Void and then has_valid_characters (a_value)
|
||||
do
|
||||
value := a_value
|
||||
ensure
|
||||
value_set: value = a_value
|
||||
end
|
||||
|
||||
set_expiration (a_date: READABLE_STRING_8)
|
||||
-- Set `expiration' with `a_date'
|
||||
require
|
||||
rfc1133_date: a_date /= Void and then is_valid_rfc1123_date (a_date)
|
||||
do
|
||||
expiration := a_date
|
||||
ensure
|
||||
expiration_set: attached expiration as l_expiration and then l_expiration.same_string (a_date)
|
||||
end
|
||||
|
||||
set_expiration_date (a_date: DATE_TIME)
|
||||
-- Set `expiration' with `a_date'
|
||||
do
|
||||
set_expiration (date_to_rfc1123_http_date_format (a_date))
|
||||
ensure
|
||||
expiration_set: attached expiration as l_expiration and then l_expiration.same_string (date_to_rfc1123_http_date_format (a_date))
|
||||
end
|
||||
|
||||
set_path (a_path: READABLE_STRING_8)
|
||||
-- Set `path' with `a_path'
|
||||
do
|
||||
path := a_path
|
||||
ensure
|
||||
path_set: path = a_path
|
||||
end
|
||||
|
||||
set_domain (a_domain: READABLE_STRING_8)
|
||||
-- Set `domain' with `a_domain'
|
||||
-- Note: you should avoid using "localhost" as `domain' for local cookies
|
||||
-- since they are not always handled by browser (for instance Chrome)
|
||||
require
|
||||
domain_without_port_info: a_domain /= Void implies not a_domain.has (':')
|
||||
do
|
||||
domain := a_domain
|
||||
ensure
|
||||
domain_set: domain = a_domain
|
||||
end
|
||||
|
||||
set_secure (a_secure: BOOLEAN)
|
||||
-- Set `secure' with `a_secure'
|
||||
do
|
||||
secure := a_secure
|
||||
ensure
|
||||
secure_set: secure = a_secure
|
||||
end
|
||||
|
||||
set_http_only (a_http_only: BOOLEAN)
|
||||
-- Set `http_only' with `a_http_only'
|
||||
do
|
||||
http_only := a_http_only
|
||||
ensure
|
||||
http_only_set: http_only = a_http_only
|
||||
end
|
||||
|
||||
set_max_age (a_max_age: INTEGER)
|
||||
-- Set `max_age' with `a_max_age'
|
||||
do
|
||||
max_age := a_max_age
|
||||
ensure
|
||||
max_age_set: max_age = a_max_age
|
||||
end
|
||||
|
||||
|
||||
mark_max_age
|
||||
-- Set `include_max_age' to True.
|
||||
-- Set `include_expires' to False.
|
||||
-- Set-Cookie will include only Max-Age attribute and not Expires.
|
||||
do
|
||||
include_max_age := True
|
||||
include_expires := False
|
||||
ensure
|
||||
max_age_true: include_max_age
|
||||
expire_false: not include_expires
|
||||
end
|
||||
|
||||
mark_expires
|
||||
-- Set `include_expires' to True.
|
||||
-- Set `include_max_age' to False
|
||||
-- Set-Cookie will include only Expires attribute and not Max_Age.
|
||||
do
|
||||
include_expires := True
|
||||
include_max_age := False
|
||||
ensure
|
||||
expires_true: include_expires
|
||||
max_age_false: not include_max_age
|
||||
end
|
||||
|
||||
set_default_expires_max_age
|
||||
-- Set `include_expires' to False.
|
||||
-- Set `include_max_age' to False
|
||||
-- Set-Cookie will include both Max-Age, Expires attributes.
|
||||
do
|
||||
include_expires := False
|
||||
include_max_age := False
|
||||
ensure
|
||||
expires_false: not include_expires
|
||||
max_age_false: not include_max_age
|
||||
end
|
||||
|
||||
feature {NONE} -- Date Utils
|
||||
|
||||
date_to_rfc1123_http_date_format (dt: DATE_TIME): STRING_8
|
||||
-- String representation of `dt' using the RFC 1123
|
||||
local
|
||||
d: HTTP_DATE
|
||||
do
|
||||
create d.make_from_date_time (dt)
|
||||
Result := d.string
|
||||
end
|
||||
|
||||
feature -- Output
|
||||
|
||||
header_line: STRING
|
||||
-- String representation of Set-Cookie header line of Current.
|
||||
local
|
||||
s: STRING
|
||||
do
|
||||
s := {HTTP_HEADER_NAMES}.header_set_cookie + colon_space + name + "=" + value
|
||||
if
|
||||
attached domain as l_domain and then not l_domain.same_string ("localhost")
|
||||
then
|
||||
s.append ("; Domain=")
|
||||
s.append (l_domain)
|
||||
end
|
||||
if attached path as l_path then
|
||||
s.append ("; Path=")
|
||||
s.append (l_path)
|
||||
end
|
||||
-- Expire
|
||||
if include_expires then
|
||||
if attached expiration as l_expires then
|
||||
s.append ("; Expires=")
|
||||
s.append (l_expires)
|
||||
end
|
||||
-- Max-Age
|
||||
elseif include_max_age then
|
||||
s.append ("; Max-Age=")
|
||||
s.append_integer (max_age)
|
||||
else
|
||||
-- Default
|
||||
check
|
||||
-- By default the attributes include_expires and include_max_age are False.
|
||||
-- Meaning that Expires and Max-Age headers are included in the response.
|
||||
default: (not include_expires) and (not include_max_age)
|
||||
end
|
||||
if attached expiration as l_expires then
|
||||
s.append ("; Expires=")
|
||||
s.append (l_expires)
|
||||
end
|
||||
|
||||
s.append ("; Max-Age=")
|
||||
s.append_integer (max_age)
|
||||
end
|
||||
|
||||
if secure then
|
||||
s.append ("; Secure")
|
||||
end
|
||||
if http_only then
|
||||
s.append ("; HttpOnly")
|
||||
end
|
||||
Result := s
|
||||
end
|
||||
|
||||
feature {NONE} -- Constants
|
||||
|
||||
|
||||
colon_space: IMMUTABLE_STRING_8
|
||||
once
|
||||
create Result.make_from_string (": ")
|
||||
end
|
||||
|
||||
|
||||
is_valid_character (c: NATURAL_32): BOOLEAN
|
||||
-- RFC6265 that specifies that the following is valid for characters in cookies.
|
||||
-- The following character ranges are valid:http://tools.ietf.org/html/rfc6265#section-4.1.1
|
||||
-- %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
|
||||
-- 0x21: !
|
||||
-- 0x23-2B: #$%&'()*+
|
||||
-- 0x2D-3A: -./0123456789:
|
||||
-- 0x3C-5B: <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[
|
||||
-- 0x5D-7E: ]^_`abcdefghijklmnopqrstuvwxyz{|}~
|
||||
note
|
||||
EIS: "name=valid-characters", "src=http://tools.ietf.org/html/rfc6265#section-4.1.1", "protocol=uri"
|
||||
do
|
||||
Result := True
|
||||
inspect c
|
||||
when 0x21 then
|
||||
when 0x23 .. 0x2B then
|
||||
when 0x2D .. 0x3A then
|
||||
when 0x3C .. 0x5B then
|
||||
when 0x5D .. 0x7E then
|
||||
else
|
||||
Result := False
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Jocelyn Fiat, 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
|
||||
155
library/network/protocol/http/tests/http_cookie_test_set.e
Normal file
155
library/network/protocol/http/tests/http_cookie_test_set.e
Normal file
@@ -0,0 +1,155 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing: "type/manual"
|
||||
|
||||
class
|
||||
HTTP_COOKIE_TEST_SET
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_cookie_expected_header
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Max-Age=-1"))
|
||||
end
|
||||
|
||||
test_cookie_value_with_illegal_characters
|
||||
-- values (cookie name and value)
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
assert ("Not valid space", not l_cookie.has_valid_characters ("Use! 12"))
|
||||
assert ("Not valid comma", not l_cookie.has_valid_characters ("Use!,12"))
|
||||
assert ("Not valid semicolon", not l_cookie.has_valid_characters ("Use!;12"))
|
||||
assert ("Not valid backslash", not l_cookie.has_valid_characters ("Use!\12"))
|
||||
assert ("Not valid Dquote", not l_cookie.has_valid_characters ("Use!%"12"))
|
||||
end
|
||||
|
||||
test_cookie_empty_value
|
||||
-- values (cookie name and value)
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "")
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=; Max-Age=-1"))
|
||||
end
|
||||
|
||||
test_cookie_full_attributes
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
l_cookie.set_expiration ("Sat, 18 Apr 2015 21:22:05 GMT")
|
||||
l_cookie.set_path ("/")
|
||||
l_cookie.set_secure (True)
|
||||
l_cookie.set_http_only (True)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
||||
end
|
||||
|
||||
test_cookie_include_expires
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
l_cookie.set_expiration ("Sat, 18 Apr 2015 21:22:05 GMT")
|
||||
l_cookie.set_path ("/")
|
||||
l_cookie.set_secure (True)
|
||||
l_cookie.set_http_only (True)
|
||||
l_cookie.mark_expires
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Secure; HttpOnly"))
|
||||
end
|
||||
|
||||
test_cookie_full_include_max_age
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
l_cookie.set_expiration ("Sat, 18 Apr 2015 21:22:05 GMT")
|
||||
l_cookie.set_path ("/")
|
||||
l_cookie.set_secure (True)
|
||||
l_cookie.set_http_only (True)
|
||||
l_cookie.mark_max_age
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Max-Age=-1; Secure; HttpOnly"))
|
||||
end
|
||||
|
||||
test_cookie_defaults_and_http_only
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_http_only (True)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Max-Age=-1; HttpOnly"))
|
||||
end
|
||||
|
||||
test_cookie_defaults_and_secure
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_secure (True)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Max-Age=-1; Secure"))
|
||||
end
|
||||
|
||||
|
||||
test_cookie_default_and_domain
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Max-Age=-1"))
|
||||
end
|
||||
|
||||
|
||||
test_cookie_default_and_path
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_path ("/")
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Path=/; Max-Age=-1"))
|
||||
end
|
||||
|
||||
test_cookie_default_and_custom_max_age
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_max_age (120)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Max-Age=120"))
|
||||
end
|
||||
|
||||
test_cookie_date_rfc1123_valid
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
assert ("Valid RFC1123", l_cookie.is_valid_rfc1123_date ("Thu, 19 Mar 2015 16:14:03 GMT"))
|
||||
end
|
||||
|
||||
test_cookie_date_rfc1123_invalid
|
||||
local
|
||||
l_cookie: HTTP_COOKIE
|
||||
do
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
assert ("Invalid RFC1123", not l_cookie.is_valid_rfc1123_date ("Thuesday, 19 Mar 2015 16:14:03 GMT"))
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
25
library/server/wsf/src/support/wsf_cookie.e
Normal file
25
library/server/wsf/src/support/wsf_cookie.e
Normal file
@@ -0,0 +1,25 @@
|
||||
note
|
||||
description: "This class represents the value of a HTTP cookie, transferred in a request."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_COOKIE
|
||||
|
||||
inherit
|
||||
|
||||
HTTP_COOKIE
|
||||
|
||||
create
|
||||
make
|
||||
note
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, 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
|
||||
@@ -316,6 +316,30 @@ feature -- Header output operation: helpers
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Header add cookie
|
||||
|
||||
add_cookie (a_cookie: WSF_COOKIE)
|
||||
-- Add a Set-Cookie header field to the response, iff there is not exist
|
||||
-- a Set-Cookie header field with the same cookie-name.
|
||||
--| Servers SHOULD NOT include more than one Set-Cookie header field in
|
||||
--| the same response with the same cookie-name.
|
||||
local
|
||||
l_same_cookie_name: BOOLEAN
|
||||
l_nv: STRING
|
||||
do
|
||||
across
|
||||
internal_header.headers as ic
|
||||
until l_same_cookie_name
|
||||
loop
|
||||
if ic.item.starts_with ("Set-Cookie:") then
|
||||
l_same_cookie_name := has_cookie_name (ic.item, a_cookie.name)
|
||||
end
|
||||
end
|
||||
if not l_same_cookie_name then
|
||||
internal_header.add_header (a_cookie.header_line)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Output report
|
||||
|
||||
transfered_content_length: NATURAL_64
|
||||
@@ -519,8 +543,31 @@ feature -- Error reporting
|
||||
wgi_response.put_error (a_message)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implemenation
|
||||
|
||||
has_cookie_name (a_cookie_line, a_cookie_name: READABLE_STRING_32 ): BOOLEAN
|
||||
-- Has the cookie line `a_cookie_line', the cookie name `a_cookie_name'?
|
||||
local
|
||||
i,j: INTEGER
|
||||
do
|
||||
Result := False
|
||||
i := a_cookie_line.index_of ('=', 1)
|
||||
j := a_cookie_line.index_of (':', 1)
|
||||
|
||||
if i > j and j > 0 then
|
||||
i := i - 1
|
||||
j := j + 1
|
||||
from until not a_cookie_line[j].is_space loop
|
||||
j := j + 1
|
||||
end
|
||||
if a_cookie_name.same_characters (a_cookie_line, j, i, 1) then
|
||||
Result := True
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
147
library/server/wsf/tests/src/test_wsf_response_test_suite.e
Normal file
147
library/server/wsf/tests/src/test_wsf_response_test_suite.e
Normal file
@@ -0,0 +1,147 @@
|
||||
note
|
||||
description: "Summary description for {TEST_WSF_RESPONSE_TEST_SUITE}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
TEST_WSF_RESPONSE_TEST_SUITE
|
||||
|
||||
inherit
|
||||
WSF_TO_WGI_SERVICE
|
||||
rename
|
||||
default_create as df_wgi,
|
||||
execute as execute_wgi
|
||||
end
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare
|
||||
select
|
||||
default_create
|
||||
end
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
do
|
||||
make_from_service (create {WSF_SERVICE_NULL})
|
||||
end
|
||||
|
||||
feature -- Test Cases
|
||||
|
||||
test_add_single_cookie
|
||||
local
|
||||
w_res: WSF_RESPONSE
|
||||
l_cookie: WSF_COOKIE
|
||||
l_header: WSF_HEADER
|
||||
l_res: WGI_RESPONSE_NULL
|
||||
do
|
||||
create {WGI_RESPONSE_NULL} l_res.make
|
||||
create w_res.make_from_wgi (l_res)
|
||||
|
||||
create l_header.make
|
||||
l_header.put_content_type_text_html
|
||||
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
l_cookie.set_expiration ("Sat, 18 Apr 2015 21:22:05 GMT")
|
||||
l_cookie.set_path ("/")
|
||||
l_cookie.set_secure (True)
|
||||
l_cookie.set_http_only (True)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
||||
|
||||
w_res.put_header_text (l_header.string)
|
||||
w_res.add_cookie (l_cookie)
|
||||
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
w_res.put_string ("Test")
|
||||
assert ("Expected", l_res.output.same_string("200 %R%NContent-Type: text/html%R%NSet-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly%R%N%R%NTest") )
|
||||
end
|
||||
|
||||
|
||||
test_add_multiple_cookiewith_similar_cookie_name
|
||||
local
|
||||
w_res: WSF_RESPONSE
|
||||
l_cookie: WSF_COOKIE
|
||||
l_header: WSF_HEADER
|
||||
l_res: WGI_RESPONSE_NULL
|
||||
do
|
||||
create {WGI_RESPONSE_NULL} l_res.make
|
||||
create w_res.make_from_wgi (l_res)
|
||||
|
||||
create l_header.make
|
||||
l_header.put_content_type_text_html
|
||||
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
l_cookie.set_expiration ("Sat, 18 Apr 2015 21:22:05 GMT")
|
||||
l_cookie.set_path ("/")
|
||||
l_cookie.set_secure (True)
|
||||
l_cookie.set_http_only (True)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
||||
w_res.put_header_text (l_header.string)
|
||||
w_res.add_cookie (l_cookie)
|
||||
|
||||
|
||||
create l_cookie.make ("user_id", "newUser")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
l_cookie.set_expiration ("Sat, 18 Apr 2015 21:22:05 GMT")
|
||||
l_cookie.set_path ("/")
|
||||
l_cookie.set_secure (True)
|
||||
l_cookie.set_http_only (True)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=newUser; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
||||
|
||||
w_res.add_cookie (l_cookie) -- Ignored
|
||||
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
w_res.put_string ("Test")
|
||||
assert ("Expected", l_res.output.same_string("200 %R%NContent-Type: text/html%R%NSet-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly%R%N%R%NTest") )
|
||||
end
|
||||
|
||||
|
||||
test_add_multiple_cookie_with_similar_cookie_name_2
|
||||
local
|
||||
w_res: WSF_RESPONSE
|
||||
l_cookie: WSF_COOKIE
|
||||
l_header: WSF_HEADER
|
||||
l_res: WGI_RESPONSE_NULL
|
||||
do
|
||||
create {WGI_RESPONSE_NULL} l_res.make
|
||||
create w_res.make_from_wgi (l_res)
|
||||
|
||||
create l_header.make
|
||||
l_header.put_content_type_text_html
|
||||
w_res.put_header_text (l_header.string)
|
||||
|
||||
create l_cookie.make ("user_id", "u12345")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
l_cookie.set_expiration ("Sat, 18 Apr 2015 21:22:05 GMT")
|
||||
l_cookie.set_path ("/")
|
||||
l_cookie.set_secure (True)
|
||||
l_cookie.set_http_only (True)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
||||
|
||||
|
||||
w_res.add_cookie (l_cookie)
|
||||
create l_cookie.make ("user_id", "newUser")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
l_cookie.set_expiration ("Sat, 18 Apr 2015 21:22:05 GMT")
|
||||
l_cookie.set_path ("/")
|
||||
l_cookie.set_secure (True)
|
||||
l_cookie.set_http_only (True)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: user_id=newUser; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
||||
|
||||
w_res.add_cookie (l_cookie) -- Ignored
|
||||
|
||||
|
||||
create l_cookie.make ("ewf_sessionid", "test")
|
||||
l_cookie.set_domain ("www.example.com")
|
||||
l_cookie.set_expiration ("Sat, 18 Apr 2015 21:22:05 GMT")
|
||||
l_cookie.set_path ("/")
|
||||
l_cookie.set_secure (True)
|
||||
l_cookie.set_http_only (True)
|
||||
assert("Expected", l_cookie.header_line.same_string ("Set-Cookie: ewf_sessionid=test; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly"))
|
||||
|
||||
w_res.add_cookie (l_cookie)
|
||||
w_res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||
w_res.put_string ("Test")
|
||||
assert ("Expected", l_res.output.same_string("200 %R%NContent-Type: text/html%R%NSet-Cookie: user_id=u12345; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly%R%NSet-Cookie: ewf_sessionid=test; Domain=www.example.com; Path=/; Expires=Sat, 18 Apr 2015 21:22:05 GMT; Max-Age=-1; Secure; HttpOnly%R%N%R%NTest") )
|
||||
end
|
||||
end
|
||||
136
library/server/wsf/tests/src/wgi_response_null.e
Normal file
136
library/server/wsf/tests/src/wgi_response_null.e
Normal file
@@ -0,0 +1,136 @@
|
||||
note
|
||||
description: "[
|
||||
Mock implementation of the WGI_RESPONSE interface.
|
||||
|
||||
Used for testing the ewf core and also web applications.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WGI_RESPONSE_NULL
|
||||
|
||||
inherit
|
||||
|
||||
WGI_RESPONSE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create output.make_empty
|
||||
create error.make_empty
|
||||
end
|
||||
|
||||
feature {WGI_CONNECTOR, WGI_SERVICE} -- Commit
|
||||
|
||||
commit
|
||||
-- Commit the current response
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
status_committed: BOOLEAN
|
||||
-- Status code set and committed?
|
||||
|
||||
header_committed: BOOLEAN
|
||||
-- Header committed?
|
||||
|
||||
message_committed: BOOLEAN
|
||||
-- Message committed?
|
||||
|
||||
message_writable: BOOLEAN
|
||||
-- Can message be written?
|
||||
do
|
||||
Result := status_is_set and header_committed
|
||||
end
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
status_is_set: BOOLEAN
|
||||
-- Is status set?
|
||||
do
|
||||
Result := status_code > 0
|
||||
end
|
||||
|
||||
set_status_code (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
|
||||
-- Set response status code
|
||||
-- Should be done before sending any data back to the client
|
||||
do
|
||||
status_code := a_code
|
||||
status_reason_phrase := a_reason_phrase
|
||||
if attached a_reason_phrase as l_rp then
|
||||
output.prepend (l_rp)
|
||||
end
|
||||
output.prepend (" ")
|
||||
output.prepend (a_code.out)
|
||||
output.append ("%R%N")
|
||||
status_committed := True
|
||||
end
|
||||
|
||||
status_code: INTEGER
|
||||
-- Response status
|
||||
|
||||
status_reason_phrase: detachable READABLE_STRING_8
|
||||
-- Custom status reason phrase for the Response (optional)
|
||||
|
||||
feature -- Header output operation
|
||||
|
||||
put_header_text (a_text: READABLE_STRING_8)
|
||||
do
|
||||
output.append (a_text)
|
||||
output.append ("%R%N")
|
||||
header_committed := True
|
||||
end
|
||||
|
||||
feature -- Output operation
|
||||
|
||||
put_character (c: CHARACTER_8)
|
||||
-- Send the character `c'
|
||||
do
|
||||
output.append_character (c)
|
||||
end
|
||||
|
||||
put_string (s: READABLE_STRING_8)
|
||||
-- Send the string `s'
|
||||
do
|
||||
output.append (s)
|
||||
end
|
||||
|
||||
put_substring (s: READABLE_STRING_8; start_index, end_index: INTEGER)
|
||||
-- Send the substring `start_index:end_index]'
|
||||
--| Could be optimized according to the target output
|
||||
do
|
||||
output.append_substring (s, start_index, end_index)
|
||||
end
|
||||
|
||||
flush
|
||||
do
|
||||
output.wipe_out
|
||||
end
|
||||
|
||||
feature -- Error reporting
|
||||
|
||||
put_error (a_message: READABLE_STRING_8)
|
||||
-- Report error described by `a_message'
|
||||
-- This might be used by the underlying connector
|
||||
do
|
||||
if attached error as err then
|
||||
err.append (a_message)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Implementation: Access
|
||||
|
||||
output: STRING
|
||||
-- Server output channel
|
||||
|
||||
error: detachable STRING
|
||||
-- Server output channel
|
||||
|
||||
|
||||
end
|
||||
26
library/server/wsf/tests/src/wsf_service_null.e
Normal file
26
library/server/wsf/tests/src/wsf_service_null.e
Normal file
@@ -0,0 +1,26 @@
|
||||
note
|
||||
description: "[
|
||||
Mock implementation of the WGI_SERVICE interface.
|
||||
|
||||
Used for testing the ewf core and also web applications
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WSF_SERVICE_NULL
|
||||
|
||||
inherit
|
||||
|
||||
WSF_SERVICE
|
||||
|
||||
|
||||
feature -- Execute
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the request
|
||||
-- See `req.input' for input stream
|
||||
-- `req.meta_variables' for the CGI meta variable
|
||||
-- and `res' for output buffer
|
||||
do
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user