diff --git a/CHANGELOGS.txt b/CHANGELOGS.txt
index 4ea6deca..da54ebf3 100644
--- a/CHANGELOGS.txt
+++ b/CHANGELOGS.txt
@@ -1,9 +1,28 @@
History for Eiffel-Web-Framework
+[2011-09-23] Jocelyn
+ * library "ewsgi":
+ - NEW simple autotest cases using Nino web server
+ -fixed issue with RAW_POST_DATA being added in form_data_parameters
+ instead of meta_variables ...
+ - Implemented WGI_VALUE for parameter's type (query_parameter,
+ form_data_parameter, item ...)
+ * Nino connector: added feature to shutdown the server from the WGI application
+ * NEW library "http_client": a new library to perform simple http requests
+ such as get, head, post, put, ... (currently implemented with Eiffel cURL)
+ * NEW library "http_authorization": added simple library to support
+ HTTP_AUTHORIZATION. For now only "Basic" auth type is supported ..
+
+[2011-09-22] Javier
+ * NEW Example: added partial Restbuck example
+
+[2011-09-21] Jocelyn
+ * Nino connector: fixed an issue with missing value for Content-Type and Content-Length
+
[2011-09-13] Jocelyn
* library "router": now using a generic design to allow customization of
request handler context class.
- * library "server/request/rest": first attempt to provide a library to
+ * NEW library "server/request/rest": first attempt to provide a library to
help building RESTful application (the interfaces are likely to change
soon) EXPERIMENTAL
diff --git a/doc/wiki b/doc/wiki
index a2a1f892..820bd7bd 160000
--- a/doc/wiki
+++ b/doc/wiki
@@ -1 +1 @@
-Subproject commit a2a1f89299a9fd1ff3078052e4c7917c329d27ed
+Subproject commit 820bd7bd6fab591691ff5c0560452c2783c8549e
diff --git a/examples/hello_routed_world/src/hello_routed_world.e b/examples/hello_routed_world/src/hello_routed_world.e
index 966366ea..f668235c 100644
--- a/examples/hello_routed_world/src/hello_routed_world.e
+++ b/examples/hello_routed_world/src/hello_routed_world.e
@@ -30,6 +30,8 @@ feature {NONE} -- Initialization
create_router
do
+-- (create {EXCEPTIONS}).raise ("ouch")
+ check False end
create router.make (5)
end
@@ -75,10 +77,10 @@ feature -- Execution
n: INTEGER
i: INTEGER
do
- create h.make
l_url := req.script_url ("/home")
n := 3
- h.put_refresh (l_url, 5, 200)
+ create h.make
+ h.put_refresh (l_url, 5)
res.set_status_code (200)
res.write_headers_string (h.string)
from
diff --git a/examples/restbucks/src/restbucks_server.e b/examples/restbucks/src/restbucks_server.e
index 34bf2392..cfca360a 100644
--- a/examples/restbucks/src/restbucks_server.e
+++ b/examples/restbucks/src/restbucks_server.e
@@ -55,7 +55,7 @@ feature -- Execution
create h.make
l_url := req.script_url ("/home")
n := 3
- h.put_refresh (l_url, 5, 200)
+ h.put_refresh (l_url, 5)
res.set_status_code (200)
res.write_headers_string (h.string)
from
diff --git a/ext/server/nino b/ext/server/nino
index 58767bb1..9fef2d71 160000
--- a/ext/server/nino
+++ b/ext/server/nino
@@ -1 +1 @@
-Subproject commit 58767bb1c13e660ba446c3d83493b458105976e1
+Subproject commit 9fef2d71f053c32c9e4c55984d53ebefe7a02c15
diff --git a/library/client/http_client/README.md b/library/client/http_client/README.md
new file mode 100644
index 00000000..c070db51
--- /dev/null
+++ b/library/client/http_client/README.md
@@ -0,0 +1 @@
+Simple HTTP client implemented using Eiffel cURL library
diff --git a/library/client/http_client/http_client.ecf b/library/client/http_client/http_client.ecf
index 0240a509..5aeb4acd 100644
--- a/library/client/http_client/http_client.ecf
+++ b/library/client/http_client/http_client.ecf
@@ -7,7 +7,7 @@
/EIFGENs$/.svn$
-
diff --git a/library/client/http_client/src/http_client_response.e b/library/client/http_client/src/http_client_response.e
index c7f46d28..5fc2cd7e 100644
--- a/library/client/http_client/src/http_client_response.e
+++ b/library/client/http_client/src/http_client_response.e
@@ -21,6 +21,17 @@ feature {NONE} -- Initialization
feature -- Status
+ error_occurred: BOOLEAN
+ -- Error occurred during request
+
+feature {HTTP_CLIENT_REQUEST} -- Status setting
+
+ set_error_occurred (b: BOOLEAN)
+ -- Set `error_occurred' to `b'
+ do
+ error_occurred := b
+ end
+
feature -- Access
status: INTEGER assign set_status
diff --git a/library/client/http_client/src/http_client_session.e b/library/client/http_client/src/http_client_session.e
index 5bb77b74..37cf2e17 100644
--- a/library/client/http_client/src/http_client_session.e
+++ b/library/client/http_client/src/http_client_session.e
@@ -108,6 +108,11 @@ feature -- Change
timeout := n
end
+ set_connect_timeout (n: like connect_timeout)
+ do
+ connect_timeout := n
+ end
+
set_user_agent (v: READABLE_STRING_8)
do
add_header ("User-Agent", v)
diff --git a/library/client/http_client/src/spec/libcurl/libcurl_http_client_request.e b/library/client/http_client/src/spec/libcurl/libcurl_http_client_request.e
index a6ec2f1a..5efa63c6 100644
--- a/library/client/http_client/src/spec/libcurl/libcurl_http_client_request.e
+++ b/library/client/http_client/src/spec/libcurl/libcurl_http_client_request.e
@@ -15,7 +15,6 @@ inherit
session
end
-
create
make
@@ -174,19 +173,20 @@ feature -- Execution
create Result.make
l_result := curl_easy.perform (curl_handle)
- create a_data.put (Void)
- l_result := curl_easy.getinfo (curl_handle, {CURL_INFO_CONSTANTS}.curlinfo_response_code, a_data)
- if l_result = 0 and then attached {INTEGER} a_data.item as l_http_status then
- Result.status := l_http_status
+ if l_result = {CURL_CODES}.curle_ok then
+ create a_data.put (Void)
+ l_result := curl_easy.getinfo (curl_handle, {CURL_INFO_CONSTANTS}.curlinfo_response_code, a_data)
+ if l_result = 0 and then attached {INTEGER} a_data.item as l_http_status then
+ Result.status := l_http_status
+ else
+ Result.status := 0
+ end
+ Result.body := l_curl_string.string
else
- Result.status := 0
+ Result.set_error_occurred (True)
end
--- last_api_call := l_url
curl_easy.cleanup (curl_handle)
-
-
- Result.body := l_curl_string.string
end
end
diff --git a/library/server/authentication/http_authorization/src/http_authorization.e b/library/server/authentication/http_authorization/src/http_authorization.e
index f35ea83b..f8f61c0f 100644
--- a/library/server/authentication/http_authorization/src/http_authorization.e
+++ b/library/server/authentication/http_authorization/src/http_authorization.e
@@ -7,42 +7,87 @@ note
class
HTTP_AUTHORIZATION
+inherit
+ REFACTORING_HELPER
+
create
- make
+ make,
+ make_basic_auth,
+ make_custom_auth
feature {NONE} -- Initialization
make (a_http_authorization: detachable READABLE_STRING_GENERAL)
-- Initialize `Current'.
local
- p: INTEGER
- s: STRING_8
+ i: INTEGER
+ t, s: STRING_8
+ u,p: READABLE_STRING_8
do
if attached a_http_authorization as l_auth then
s := l_auth.as_string_8
if not s.is_empty then
- p := 1
- if s[p] = ' ' then
- p := p + 1
+ i := 1
+ if s[i] = ' ' then
+ i := i + 1
end
- p := s.index_of (' ', p)
- if p > 0 then
- s := (create {BASE64}).decoded_string (s.substring (p + 1, s.count))
- p := s.index_of (':', 1) --| Let's assume ':' is forbidden in login ...
- if p > 0 then
- login := s.substring (1, p - 1).as_string_32
- password := s.substring (p + 1, s.count).as_string_32
+ i := s.index_of (' ', i)
+ if i > 0 then
+ t := s.substring (1, i - 1).as_lower
+ t.right_adjust; t.left_adjust
+ type := t
+ if t.same_string ("basic") then
+ s := (create {BASE64}).decoded_string (s.substring (i + 1, s.count))
+ i := s.index_of (':', 1) --| Let's assume ':' is forbidden in login ...
+ if i > 0 then
+ u := s.substring (1, i - 1).as_string_32
+ p := s.substring (i + 1, s.count).as_string_32
+ login := u
+ password := p
+ check
+ (create {HTTP_AUTHORIZATION}.make_custom_auth (u, p, t)).http_authorization ~ http_authorization
+ end
+ end
+ elseif t.same_string ("digest") then
+ to_implement ("HTTP Authorization %"digest%", not yet implemented")
+ else
+ to_implement ("HTTP Authorization %""+ t +"%", not yet implemented")
end
end
end
end
end
+ make_basic_auth (u: READABLE_STRING_32; p: READABLE_STRING_32)
+ do
+ make_custom_auth (u, p, "basic")
+ end
+
+ make_custom_auth (u: READABLE_STRING_32; p: READABLE_STRING_32; a_type: READABLE_STRING_8)
+ local
+ t: STRING_8
+ do
+ login := u
+ password := p
+ create t.make_from_string (a_type.as_lower)
+ t.left_adjust; t.right_adjust
+ type := t
+ if t.same_string ("basic") then
+ http_authorization := "Basic " + (create {BASE64}).encoded_string (u + ":" + p)
+ else
+ to_implement ("HTTP Authorization %""+ t +"%", not yet implemented")
+ end
+ end
+
feature -- Access
+ type: detachable READABLE_STRING_8
+
login: detachable READABLE_STRING_32
password: detachable READABLE_STRING_32
+ http_authorization: detachable READABLE_STRING_32
+
end
diff --git a/library/server/ewsgi/default/nino/nino_application.e b/library/server/ewsgi/default/nino/nino_application.e
index 1d18f11f..51d85966 100644
--- a/library/server/ewsgi/default/nino/nino_application.e
+++ b/library/server/ewsgi/default/nino/nino_application.e
@@ -53,6 +53,12 @@ feature -- Server
connector.launch
end
+ shutdown
+ -- Shutdown the server
+ do
+ connector.server.shutdown_server
+ end
+
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
diff --git a/library/server/ewsgi/specification/request/value/wgi_multiple_string_value.e b/library/server/ewsgi/specification/request/value/wgi_multiple_string_value.e
index 9654cbb5..4285f965 100644
--- a/library/server/ewsgi/specification/request/value/wgi_multiple_string_value.e
+++ b/library/server/ewsgi/specification/request/value/wgi_multiple_string_value.e
@@ -14,6 +14,7 @@ inherit
create
make_with_value,
+ make_with_array,
make_with_string
feature {NONE} -- Initialization
@@ -25,6 +26,26 @@ feature {NONE} -- Initialization
add_value (a_value)
end
+ make_with_array (arr: ARRAY [WGI_VALUE])
+ require
+ arr_not_empty: not arr.is_empty
+ all_same_name: across arr as c all c.item.name.same_string (arr[arr.lower].name) end
+ local
+ i,up: INTEGER
+ do
+ up := arr.upper
+ i := arr.lower
+ make_with_value (arr[i])
+ from
+ i := i + 1
+ until
+ i > up
+ loop
+ add_value (arr[i])
+ i := i + 1
+ end
+ end
+
make_with_string (a_name: like name; a_string: READABLE_STRING_32)
do
make_with_value (create {WGI_STRING_VALUE}.make (a_name, a_string))
@@ -75,7 +96,7 @@ feature -- Helper
across
string_values as c
loop
- if Result.count = 1 then
+ if Result.count > 1 then
Result.append_character (',')
end
Result.append_string (c.item)
diff --git a/library/server/ewsgi/specification/request/wgi_request.e b/library/server/ewsgi/specification/request/wgi_request.e
index 2250427c..6e160199 100644
--- a/library/server/ewsgi/specification/request/wgi_request.e
+++ b/library/server/ewsgi/specification/request/wgi_request.e
@@ -106,7 +106,7 @@ feature -- Access: CGI meta variables
end
end
- meta_variables: ITERATION_CURSOR [WGI_VALUE]
+ meta_variables: ITERABLE [WGI_VALUE]
-- These variables are specific to requests made with HTTP.
-- Interpretation of these variables may depend on the value of
-- SERVER_PROTOCOL.
@@ -587,7 +587,7 @@ feature -- Extra CGI environment variables
feature -- Query string Parameters
- query_parameters: ITERATION_CURSOR [WGI_VALUE]
+ query_parameters: ITERABLE [WGI_VALUE]
-- Variables extracted from QUERY_STRING
deferred
end
@@ -601,7 +601,7 @@ feature -- Query string Parameters
feature -- Form fields and related
- form_data_parameters: ITERATION_CURSOR [WGI_VALUE]
+ form_data_parameters: ITERABLE [WGI_VALUE]
-- Variables sent by POST request
deferred
end
@@ -626,7 +626,7 @@ feature -- Form fields and related
feature -- Cookies
- cookies: ITERATION_CURSOR [WGI_VALUE]
+ cookies: ITERABLE [WGI_VALUE]
-- Expanded cookies variable
deferred
end
@@ -638,7 +638,7 @@ feature -- Cookies
deferred
end
-feature -- Access: global variable
+feature -- Access: all variables
parameters: like items
obsolete "use items"
@@ -652,7 +652,7 @@ feature -- Access: global variable
Result := item (a_name)
end
- items: ITERATION_CURSOR [WGI_VALUE]
+ items: ITERABLE [WGI_VALUE]
-- Table containing all the various variables
-- Warning: this is computed each time, if you change the content of other containers
-- this won't update this Result's content, unless you query it again
diff --git a/library/server/ewsgi/specification/response/wgi_response_buffer.e b/library/server/ewsgi/specification/response/wgi_response_buffer.e
index 7cf4e9fa..ccdb0a30 100644
--- a/library/server/ewsgi/specification/response/wgi_response_buffer.e
+++ b/library/server/ewsgi/specification/response/wgi_response_buffer.e
@@ -37,7 +37,7 @@ feature -- Status report
feature {WGI_RESPONSE_BUFFER} -- Core output operation
- write (s: STRING)
+ write (s: READABLE_STRING_8)
-- Send the string `s'
-- this can be used for header and body
deferred
@@ -69,7 +69,7 @@ feature -- Status setting
feature -- Header output operation
- write_headers_string (a_headers: STRING)
+ write_headers_string (a_headers: READABLE_STRING_8)
require
status_set: status_is_set
header_not_committed: not header_committed
@@ -80,7 +80,7 @@ feature -- Header output operation
message_writable: message_writable
end
- write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: STRING; value: STRING]])
+ write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]])
-- Send headers with status `a_status', and headers from `a_headers'
require
status_not_set: not status_is_set
@@ -94,21 +94,21 @@ feature -- Header output operation
feature -- Output operation
- write_string (s: STRING)
+ write_string (s: READABLE_STRING_8)
-- Send the string `s'
require
message_writable: message_writable
deferred
end
- write_substring (s: STRING; a_begin_index, a_end_index: INTEGER)
+ write_substring (s: READABLE_STRING_8; a_begin_index, a_end_index: INTEGER)
-- Send the substring `s[a_begin_index:a_end_index]'
require
message_writable: message_writable
deferred
end
- write_file_content (fn: STRING)
+ write_file_content (fn: READABLE_STRING_8)
-- Send the content of file `fn'
require
message_writable: message_writable
diff --git a/library/server/ewsgi/src/application/wgi_application.e b/library/server/ewsgi/src/application/wgi_application.e
index 4c5a8d22..19386f69 100644
--- a/library/server/ewsgi/src/application/wgi_application.e
+++ b/library/server/ewsgi/src/application/wgi_application.e
@@ -16,14 +16,13 @@ feature -- Execution
execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
-- Execute the request
-- See `req.input' for input stream
- -- `req.environment' for the Gateway environment
+ -- `req.meta_variables' for the CGI meta variable
-- and `res' for output buffer
require
res_status_unset: not res.status_is_set
deferred
ensure
res_status_set: res.status_is_set
--- res_committed: res.message_committed
end
feature -- Process request
diff --git a/library/server/ewsgi/src/request/wgi_request_from_table.e b/library/server/ewsgi/src/request/wgi_request_from_table.e
index ec6fdb0d..913e6321 100644
--- a/library/server/ewsgi/src/request/wgi_request_from_table.e
+++ b/library/server/ewsgi/src/request/wgi_request_from_table.e
@@ -174,9 +174,9 @@ feature {NONE} -- Access: CGI meta parameters
feature -- Access: CGI meta parameters
- meta_variables: ITERATION_CURSOR [WGI_VALUE]
+ meta_variables: ITERABLE [WGI_VALUE]
do
- Result := meta_variables_table.new_cursor
+ Result := meta_variables_table
end
meta_variable (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
@@ -429,9 +429,9 @@ feature {NONE} -- Query parameters
feature -- Query parameters
- query_parameters: ITERATION_CURSOR [WGI_VALUE]
+ query_parameters: ITERABLE [WGI_VALUE]
do
- Result := query_parameters_table.new_cursor
+ Result := query_parameters_table
end
query_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
@@ -448,6 +448,7 @@ feature {NONE} -- Query parameters: implementation
n, p, i, j: INTEGER
s: STRING
l_name,l_value: STRING_32
+ v: WGI_VALUE
do
if a_content = Void then
create Result.make (0)
@@ -479,7 +480,17 @@ feature {NONE} -- Query parameters: implementation
l_name := url_encoder.decoded_string (l_name)
l_value := url_encoder.decoded_string (l_value)
end
- Result.force (new_string_value (l_name, l_value), l_name)
+ v := new_string_value (l_name, l_value)
+ if Result.has_key (l_name) and then attached Result.found_item as l_existing_value then
+ if attached {WGI_MULTIPLE_STRING_VALUE} l_existing_value as l_multi then
+ l_multi.add_value (v)
+ else
+ Result.force (create {WGI_MULTIPLE_STRING_VALUE}.make_with_array (<>), l_name)
+ check replaced: Result.found and then Result.found_item ~ l_existing_value end
+ end
+ else
+ Result.force (v, l_name)
+ end
end
end
end
@@ -515,7 +526,7 @@ feature {NONE} -- Form fields and related
vars := urlencoded_parameters (s, True)
end
if raw_post_data_recorded then
- vars.force (new_string_value ("RAW_POST_DATA", s), "RAW_POST_DATA")
+ set_meta_string_variable ("RAW_POST_DATA", s)
end
else
create vars.make (0)
@@ -527,9 +538,9 @@ feature {NONE} -- Form fields and related
feature -- Form fields and related
- form_data_parameters: ITERATION_CURSOR [WGI_VALUE]
+ form_data_parameters: ITERABLE [WGI_VALUE]
do
- Result := form_data_parameters_table.new_cursor
+ Result := form_data_parameters_table
end
form_data_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
@@ -595,9 +606,9 @@ feature {NONE} -- Cookies
feature -- Cookies
- cookies: ITERATION_CURSOR [WGI_VALUE]
+ cookies: ITERABLE [WGI_VALUE]
do
- Result := cookies_table.new_cursor
+ Result := cookies_table
end
cookie (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
@@ -612,57 +623,40 @@ feature {NONE} -- Access: global variable
-- Table containing all the various variables
-- Warning: this is computed each time, if you change the content of other containers
-- this won't update this Result's content, unless you query it again
- local
- vars: ITERATION_CURSOR [WGI_VALUE]
do
create Result.make (100)
- vars := meta_variables
- from
--- vars.start
- until
- vars.after
+ across
+ meta_variables as vars
loop
Result.force (vars.item, vars.item.name)
- vars.forth
end
- vars := query_parameters
- from
--- vars.start
- until
- vars.after
+ across
+ query_parameters as vars
loop
Result.force (vars.item, vars.item.name)
- vars.forth
end
- vars := form_data_parameters
- from
--- vars.start
- until
- vars.after
+ across
+ form_data_parameters as vars
loop
Result.force (vars.item, vars.item.name)
- vars.forth
end
- vars := cookies
- from
--- vars.start
- until
- vars.after
+ across
+ cookies as vars
loop
Result.force (vars.item, vars.item.name)
- vars.forth
end
+
end
feature -- Access: global variable
- items: ITERATION_CURSOR [WGI_VALUE]
+ items: ITERABLE [WGI_VALUE]
do
- Result := items_table.new_cursor
+ Result := items_table
end
item (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
diff --git a/library/server/ewsgi/src/response/wgi_response_stream_buffer.e b/library/server/ewsgi/src/response/wgi_response_stream_buffer.e
index b8dcd245..416b6fdd 100644
--- a/library/server/ewsgi/src/response/wgi_response_stream_buffer.e
+++ b/library/server/ewsgi/src/response/wgi_response_stream_buffer.e
@@ -48,7 +48,7 @@ feature -- Status report
feature {NONE} -- Core output operation
- write (s: STRING)
+ write (s: READABLE_STRING_8)
-- Send the content of `s'
-- this can be used for header and body
do
@@ -76,13 +76,13 @@ feature -- Status setting
feature -- Header output operation
- write_headers_string (a_headers: STRING)
+ write_headers_string (a_headers: READABLE_STRING_8)
do
write (a_headers)
header_committed := True
end
- write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: STRING; value: STRING]])
+ write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]])
-- Send headers with status `a_status', and headers from `a_headers'
local
h: EWF_HEADER
@@ -107,20 +107,20 @@ feature -- Header output operation
feature -- Output operation
- write_string (s: STRING)
+ write_string (s: READABLE_STRING_8)
-- Send the string `s'
do
write (s)
end
- write_substring (s: STRING; start_index, end_index: INTEGER)
+ write_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.put_substring (s, start_index, end_index)
end
- write_file_content (fn: STRING)
+ write_file_content (fn: READABLE_STRING_8)
-- Send the content of file `fn'
do
output.put_file_content (fn)
diff --git a/library/server/ewsgi/src/support/ewf_header.e b/library/server/ewsgi/src/support/ewf_header.e
index 7bacd217..6eacd3bb 100644
--- a/library/server/ewsgi/src/support/ewf_header.e
+++ b/library/server/ewsgi/src/support/ewf_header.e
@@ -28,7 +28,7 @@ feature {NONE} -- Initialization
make
-- Initialize current
do
- create {ARRAYED_LIST [STRING]} headers.make (3)
+ create {ARRAYED_LIST [READABLE_STRING_8]} headers.make (3)
end
feature -- Recycle
@@ -40,7 +40,7 @@ feature -- Recycle
feature -- Access
- headers: LIST [STRING]
+ headers: LIST [READABLE_STRING_8]
-- Header's lines
string: STRING
@@ -67,24 +67,24 @@ feature -- Access
feature -- Header change: general
- add_header (h: STRING)
+ add_header (h: READABLE_STRING_8)
do
headers.force (h)
end
- put_header (h: STRING)
+ put_header (h: READABLE_STRING_8)
-- Add header `h' or replace existing header of same header name
do
force_header_by_name (header_name (h), h)
end
- add_header_key_value (k,v: STRING)
+ add_header_key_value (k,v: READABLE_STRING_8)
-- Add header `k:v', or replace existing header of same header name/key
do
add_header (k + colon_space + v)
end
- put_header_key_value (k,v: STRING)
+ put_header_key_value (k,v: READABLE_STRING_8)
-- Add header `k:v', or replace existing header of same header name/key
do
put_header (k + colon_space + v)
@@ -104,23 +104,23 @@ feature -- Content related header
put_header_key_value ("Status", s)
end
- put_content_type (t: STRING)
+ put_content_type (t: READABLE_STRING_8)
do
put_header_key_value (name_content_type, t)
end
- add_content_type (t: STRING)
+ add_content_type (t: READABLE_STRING_8)
-- same as `put_content_type', but allow multiple definition of "Content-Type"
do
add_header_key_value (name_content_type, t)
end
- put_content_type_with_name (t: STRING; n: STRING)
+ put_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8)
do
put_header_key_value (name_content_type, t + "; name=%"" + n + "%"")
end
- add_content_type_with_name (t: STRING; n: STRING)
+ add_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8)
-- same as `put_content_type_with_name', but allow multiple definition of "Content-Type"
do
add_header_key_value (name_content_type, t + "; name=%"" + n + "%"")
@@ -158,7 +158,7 @@ feature -- Content related header
put_header_key_value (name_content_length, n.out)
end
- put_content_transfer_encoding (a_mechanism: STRING)
+ put_content_transfer_encoding (a_mechanism: READABLE_STRING_8)
-- Put "Content-Transfer-Encoding" header with for instance "binary"
--| encoding := "Content-Transfer-Encoding" ":" mechanism
--|
@@ -173,7 +173,7 @@ feature -- Content related header
put_header_key_value ("Content-Transfer-Encoding", a_mechanism)
end
- put_content_disposition (a_type: STRING; a_params: detachable STRING)
+ put_content_disposition (a_type: READABLE_STRING_8; a_params: detachable READABLE_STRING_8)
-- Put "Content-Disposition" header
--| See RFC2183
--| disposition := "Content-Disposition" ":"
@@ -212,13 +212,13 @@ feature -- Others
put_header_key_value ("Expires", n.out)
end
- put_cache_control (s: STRING)
+ put_cache_control (s: READABLE_STRING_8)
-- `s' could be for instance "no-cache, must-revalidate"
do
put_header_key_value ("Cache-Control", s)
end
- put_pragma (s: STRING)
+ put_pragma (s: READABLE_STRING_8)
do
put_header_key_value ("Pragma", s)
end
@@ -230,13 +230,13 @@ feature -- Others
feature -- Redirection
- put_redirection (a_location: STRING; a_code: INTEGER)
- -- Tell the client to redirect to page with `a_location' right away
+ put_location (a_location: READABLE_STRING_8)
+ -- Tell the client the new location `a_location'
do
put_header_key_value ("Location", a_location)
end
- put_refresh (a_location: STRING; a_timeout: INTEGER; a_code: INTEGER)
+ put_refresh (a_location: READABLE_STRING_8; a_timeout: INTEGER)
-- Tell the client to refresh page with `a_location' after `a_timeout' in seconds
do
put_header_key_value ("Refresh", a_timeout.out + "; url=" + a_location)
@@ -244,7 +244,7 @@ feature -- Redirection
feature -- Cookie
- put_cookie (key, value: STRING_8; expiration, path, domain, secure: detachable STRING_8)
+ put_cookie (key, value: READABLE_STRING_8; expiration, path, domain, secure: detachable READABLE_STRING_8)
-- Set a cookie on the client's machine
-- with key 'key' and value 'value'.
require
@@ -270,7 +270,7 @@ feature -- Cookie
feature -- Status report
- has_header_named (a_name: STRING): BOOLEAN
+ has_header_named (a_name: READABLE_STRING_8): BOOLEAN
-- Has header item for `n'?
local
c: like headers.new_cursor
@@ -295,7 +295,7 @@ feature -- Status report
feature {NONE} -- Implementation: Header
- force_header_by_name (n: detachable STRING; h: STRING)
+ force_header_by_name (n: detachable READABLE_STRING_8; h: READABLE_STRING_8)
-- Add header `h' or replace existing header of same header name `n'
require
h_has_name_n: (n /= Void and attached header_name (h) as hn) implies n.same_string (hn)
@@ -321,36 +321,38 @@ feature {NONE} -- Implementation: Header
end
end
- header_name (h: STRING): detachable STRING
+ header_name (h: READABLE_STRING_8): detachable READABLE_STRING_8
-- If any, header's name with colon
--| ex: for "Foo-bar: something", this will return "Foo-bar:"
local
+ s: detachable STRING_8
i,n: INTEGER
c: CHARACTER
do
from
i := 1
n := h.count
- create Result.make (10)
+ create s.make (10)
until
- i > n or c = ':' or Result = Void
+ i > n or c = ':' or s = Void
loop
c := h[i]
inspect c
when ':' then
- Result.extend (c)
+ s.extend (c)
when '-', 'a' .. 'z', 'A' .. 'Z' then
- Result.extend (c)
+ s.extend (c)
else
- Result := Void
+ s := Void
end
i := i + 1
end
+ Result := s
end
feature {NONE} -- Implementation
- append_line_to (s, h: STRING)
+ append_line_to (s: READABLE_STRING_8; h: like string)
do
h.append_string (s)
append_end_of_line_to (h)
diff --git a/library/server/ewsgi/tests/test_ewsgi_request.e b/library/server/ewsgi/tests/test_ewsgi_request.e
new file mode 100644
index 00000000..30ac9873
--- /dev/null
+++ b/library/server/ewsgi/tests/test_ewsgi_request.e
@@ -0,0 +1,208 @@
+note
+ description: "[
+ Eiffel tests that can be executed by testing tool.
+ ]"
+ author: "EiffelStudio test wizard"
+ date: "$Date$"
+ revision: "$Revision$"
+ testing: "type/manual"
+
+class
+ TEST_EWSGI_REQUEST
+
+inherit
+ EQA_TEST_SET
+ redefine
+ on_prepare,
+ on_clean
+ end
+
+feature {NONE} -- Events
+
+ web_app: detachable NINO_APPLICATION
+
+ port_number: INTEGER
+ base_url: detachable STRING
+
+ on_prepare
+ --
+ local
+ app: NINO_APPLICATION
+ wt: WORKER_THREAD
+ e: EXECUTION_ENVIRONMENT
+ do
+ port_number := 8087
+ base_url := "test/"
+ create app.make_custom (agent execute, base_url)
+ web_app := app
+
+ create wt.make (agent app.listen (port_number))
+ wt.launch
+
+ create e
+ e.sleep (1_000_000_000 * 5)
+ end
+
+ execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
+ local
+ q: detachable STRING_32
+ do
+ if attached req.request_uri as l_uri then
+ if l_uri.starts_with (test_url ("get/01")) then
+ res.write_header (200, <<["Content-Type", "text/plain"]>>)
+ res.write_string ("get-01")
+ create q.make_empty
+
+ across
+ req.query_parameters as qcur
+ loop
+ if not q.is_empty then
+ q.append_character ('&')
+ end
+ q.append (qcur.item.name.as_string_32 + "=" + qcur.item.as_string)
+ end
+ if not q.is_empty then
+ res.write_string ("(" + q + ")")
+ end
+ elseif l_uri.starts_with (test_url ("post/01")) then
+ res.write_header (200, <<["Content-Type", "text/plain"]>>)
+ res.write_string ("post-01")
+ create q.make_empty
+
+ across
+ req.query_parameters as qcur
+ loop
+ if not q.is_empty then
+ q.append_character ('&')
+ end
+ q.append (qcur.item.name.as_string_32 + "=" + qcur.item.as_string)
+ end
+
+ if not q.is_empty then
+ res.write_string ("(" + q + ")")
+ end
+
+ create q.make_empty
+
+
+ across
+ req.form_data_parameters as fcur
+ loop
+ if not q.is_empty then
+ q.append_character ('&')
+ end
+ q.append (fcur.item.name.as_string_32 + "=" + fcur.item.as_string)
+ end
+
+ if not q.is_empty then
+ res.write_string (" : " + q )
+ end
+ else
+ res.write_header (200, <<["Content-Type", "text/plain"]>>)
+ res.write_string ("Hello")
+ end
+ else
+ res.write_header (200, <<["Content-Type", "text/plain"]>>)
+ res.write_string ("Bye")
+ end
+ end
+
+ test_url (a_query_url: READABLE_STRING_8): READABLE_STRING_8
+ local
+ b: like base_url
+ do
+ b := base_url
+ if b = Void then
+ b := ""
+ end
+ Result := "/" + b + a_query_url
+ end
+
+ on_clean
+ --
+ do
+ if attached web_app as app then
+ app.shutdown
+ end
+ end
+
+ http_session: detachable HTTP_CLIENT_SESSION
+
+ get_http_session
+ local
+ h: LIBCURL_HTTP_CLIENT
+ b: like base_url
+ do
+ create h.make
+ b := base_url
+ if b = Void then
+ b := ""
+ end
+ if attached {HTTP_CLIENT_SESSION} h.new_session ("localhost:" + port_number.out + "/" + b) as sess then
+ http_session := sess
+ sess.set_timeout (-1)
+ sess.set_connect_timeout (-1)
+ end
+ end
+
+ test_get_request (a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; a_expected_body: READABLE_STRING_8)
+ do
+ get_http_session
+ if attached http_session as sess then
+ if attached sess.get (a_url, ctx) as res and then not res.error_occurred and then attached res.body as l_body then
+ assert ("Good answer got=%""+l_body+"%" expected=%""+a_expected_body+"%"", l_body.same_string (a_expected_body))
+ else
+ assert ("Request %""+a_url+"%" failed", False)
+ end
+ end
+ end
+
+ test_post_request (a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; a_expected_body: READABLE_STRING_8)
+ do
+ get_http_session
+ if attached http_session as sess then
+ if attached sess.post (a_url, ctx) as res and then not res.error_occurred and then attached res.body as l_body then
+ assert ("Good answer got=%""+l_body+"%" expected=%""+a_expected_body+"%"", l_body.same_string (a_expected_body))
+ else
+ assert ("Request %""+a_url+"%" failed", False)
+ end
+ end
+ end
+
+feature -- Test routines
+
+ test_get_request_01
+ -- New test routine
+ do
+ get_http_session
+ if attached http_session as sess then
+ test_get_request ("get/01", Void, "get-01")
+ test_get_request ("get/01/?foo=bar", Void, "get-01(foo=bar)")
+ test_get_request ("get/01/?foo=bar&abc=def", Void, "get-01(foo=bar&abc=def)")
+ test_get_request ("get/01/?lst=a&lst=b", Void, "get-01(lst=[a,b])")
+ else
+ assert ("not_implemented", False)
+ end
+ end
+
+ test_post_request_01
+ -- New test routine
+ local
+ ctx: HTTP_CLIENT_REQUEST_CONTEXT
+ do
+ get_http_session
+ if attached http_session as sess then
+ create ctx.make
+ ctx.add_form_data_parameter ("id", "123")
+ test_post_request ("post/01", ctx, "post-01 : id=123")
+ test_post_request ("post/01/?foo=bar", ctx, "post-01(foo=bar) : id=123")
+ test_post_request ("post/01/?foo=bar&abc=def", ctx, "post-01(foo=bar&abc=def) : id=123")
+ test_post_request ("post/01/?lst=a&lst=b", ctx, "post-01(lst=[a,b]) : id=123")
+ else
+ assert ("not_implemented", False)
+ end
+ end
+
+end
+
+
diff --git a/library/server/ewsgi/tests/tests-safe.ecf b/library/server/ewsgi/tests/tests-safe.ecf
new file mode 100644
index 00000000..fa29a674
--- /dev/null
+++ b/library/server/ewsgi/tests/tests-safe.ecf
@@ -0,0 +1,21 @@
+
+
+
+
+
+ /.git$
+ /EIFGENs$
+ /.svn$
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/server/ewsgi/tests/tests.ecf b/library/server/ewsgi/tests/tests.ecf
new file mode 100644
index 00000000..cb26c87a
--- /dev/null
+++ b/library/server/ewsgi/tests/tests.ecf
@@ -0,0 +1,19 @@
+
+
+
+
+
+ /.git$
+ /EIFGENs$
+ /.svn$
+
+
+
+
+
+
+
+
+
+
diff --git a/library/server/request/rest/src/uri/rest_request_uri_routing_handler_i.e b/library/server/request/rest/src/uri/rest_request_uri_routing_handler_i.e
index badbe29d..6fc843d4 100644
--- a/library/server/request/rest/src/uri/rest_request_uri_routing_handler_i.e
+++ b/library/server/request/rest/src/uri/rest_request_uri_routing_handler_i.e
@@ -25,7 +25,14 @@ create
feature -- Status report
- authentication_required: BOOLEAN
+ authentication_required (req: WGI_REQUEST): BOOLEAN
+ do
+ Result := internal_authentication_required
+ end
+
+feature {NONE} -- Implementation
+
+ internal_authentication_required: BOOLEAN
feature -- Execution
diff --git a/library/server/request/rest/tests/src/app/app_account_verify_credential.e b/library/server/request/rest/tests/src/app/app_account_verify_credential.e
index 17efb516..3161dff7 100644
--- a/library/server/request/rest/tests/src/app/app_account_verify_credential.e
+++ b/library/server/request/rest/tests/src/app/app_account_verify_credential.e
@@ -63,9 +63,9 @@ feature -- Execution
do
content_type_supported := <<{HTTP_CONSTANTS}.json_app, {HTTP_CONSTANTS}.xml_text, {HTTP_CONSTANTS}.plain_text>>
l_format_id := ctx.request_format_id ("format", content_type_supported)
- if ctx.authenticated then
+ if authenticated (ctx) then
l_full := attached ctx.query_parameter ("details") as v and then v.is_case_insensitive_equal ("true")
- if attached ctx.authenticated_identifier as log then
+ if attached authenticated_identifier (ctx) as log then
l_login := log.as_string_8
create h.make
diff --git a/library/server/request/rest/tests/src/app/app_test.e b/library/server/request/rest/tests/src/app/app_test.e
index f642977a..1b54ae5e 100644
--- a/library/server/request/rest/tests/src/app/app_test.e
+++ b/library/server/request/rest/tests/src/app/app_test.e
@@ -65,12 +65,12 @@ feature -- Execution
(create {DEVELOPER_EXCEPTION}).raise
elseif l_op.starts_with ("env") then
s.append_string ("%N%NAll variables:")
- s.append (wgi_value_iteration_to_string (req.parameters, False))
+ s.append (wgi_value_iteration_to_string (req.items, False))
s.append_string (" script_url(%"" + req.path_info + "%")=" + ctx.script_url (req.path_info) + "%N")
-- if attached ctx.http_authorization_login_password as t then
-- s.append_string ("Check login=" + t.login + " %N")
-- end
- if ctx.authenticated and then attached ctx.authenticated_identifier as l_login then
+ if authenticated (ctx) and then attached authenticated_identifier (ctx) as l_login then
s.append_string ("Authenticated: login=" + l_login.as_string_8 + " %N")
end
end
diff --git a/library/server/request/rest/tests/src/app_server.e b/library/server/request/rest/tests/src/app_server.e
index 51c6399e..0da1ce72 100644
--- a/library/server/request/rest/tests/src/app_server.e
+++ b/library/server/request/rest/tests/src/app_server.e
@@ -83,15 +83,15 @@ feature -- Execution
l_redir_url: STRING
do
create h.make
--- h.put_refresh (ctx.script_url ("/doc"), 2, {HTTP_STATUS_CODE}.temp_redirect)
+-- h.put_refresh (ctx.script_url ("/doc"), 2)
l_redir_url := "/doc"
- h.put_refresh (l_redir_url, 2, {HTTP_STATUS_CODE}.temp_redirect)
+ h.put_refresh (l_redir_url, 2)
h.put_content_type_text_html
create s.make_empty
s := "Request [" + req.path_info + "] is not available. %N";
s.append ("You are being redirected to /doc in 2 seconds ...%N")
h.put_content_length (s.count)
- res.set_status_code (200)
+ res.set_status_code ({HTTP_STATUS_CODE}.temp_redirect)
res.write_headers_string (h.string)
res.write_string (s)
end
diff --git a/library/server/request/rest/tests/src/handler/app_request_agent_handler.e b/library/server/request/rest/tests/src/handler/app_request_agent_handler.e
index a59ab7ab..49551d2a 100644
--- a/library/server/request/rest/tests/src/handler/app_request_agent_handler.e
+++ b/library/server/request/rest/tests/src/handler/app_request_agent_handler.e
@@ -14,6 +14,9 @@ inherit
end
REST_REQUEST_AGENT_HANDLER [APP_REQUEST_HANDLER_CONTEXT]
+ undefine
+ authenticated
+ end
create
make
diff --git a/library/server/request/rest/tests/src/handler/app_request_handler.e b/library/server/request/rest/tests/src/handler/app_request_handler.e
index 01e78d9c..1c5e8116 100644
--- a/library/server/request/rest/tests/src/handler/app_request_handler.e
+++ b/library/server/request/rest/tests/src/handler/app_request_handler.e
@@ -8,6 +8,9 @@ deferred class
inherit
REST_REQUEST_HANDLER [APP_REQUEST_HANDLER_CONTEXT]
+ redefine
+ authenticated
+ end
APP_REQUEST_HELPER
@@ -17,27 +20,43 @@ feature {NONE} -- Initialization
-- Initialize various attributes
do
end
-
+
feature {NONE} -- Implementation
- wgi_value_iteration_to_string (cur: ITERATION_CURSOR [WGI_VALUE]; using_pre: BOOLEAN): STRING_8
+ wgi_value_iteration_to_string (v: ITERABLE [WGI_VALUE]; using_pre: BOOLEAN): STRING_8
do
create Result.make (100)
if using_pre then
Result.append ("
")
end
- from
- until
- cur.after
+ across
+ v as cur
loop
Result.append_string (cur.item.name.as_string_8 + " = " + cur.item.as_string.as_string_8 + "%N")
- cur.forth
end
if using_pre then
Result.append ("
")
end
end
+feature -- Auth
+
+ authenticated (ctx: APP_REQUEST_HANDLER_CONTEXT): BOOLEAN
+ -- Is authenticated?
+ do
+ --| To redefine if needed
+ if attached ctx.request.http_authorization as l_http_authorization then
+ Result := True
+ end
+ end
+
+ authenticated_identifier (ctx: APP_REQUEST_HANDLER_CONTEXT): detachable READABLE_STRING_32
+ do
+ if attached ctx.request.http_authorization as l_http_authorization then
+ Result := "foo" -- Implement it as you want
+ end
+ end
+
feature -- Helpers
format_id (s: detachable STRING): INTEGER
diff --git a/library/server/request/rest/tests/src/handler/app_request_handler_context.e b/library/server/request/rest/tests/src/handler/app_request_handler_context.e
index 98bd12de..76b703a0 100644
--- a/library/server/request/rest/tests/src/handler/app_request_handler_context.e
+++ b/library/server/request/rest/tests/src/handler/app_request_handler_context.e
@@ -9,29 +9,10 @@ class
inherit
REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT
- redefine
- authenticated,
- authenticated_identifier
- end
create
make
-feature -- Auth
-
- authenticated: BOOLEAN
- do
- if attached request.http_authorization as l_http_auth then
- Result := True
- end
- end
-
- authenticated_identifier: detachable READABLE_STRING_32
- do
- if authenticated then
- Result := "foo"
- end
- end
feature -- Format
diff --git a/library/server/request/rest/tests/src/handler/app_request_routing_handler.e b/library/server/request/rest/tests/src/handler/app_request_routing_handler.e
index 63e0196f..f6db6ec1 100644
--- a/library/server/request/rest/tests/src/handler/app_request_routing_handler.e
+++ b/library/server/request/rest/tests/src/handler/app_request_routing_handler.e
@@ -10,12 +10,14 @@ class
inherit
APP_REQUEST_HANDLER
undefine
- execute,
- pre_execute,
- post_execute
+ execute
end
REST_REQUEST_URI_TEMPLATE_ROUTING_HANDLER_I [APP_REQUEST_HANDLER, APP_REQUEST_HANDLER_CONTEXT]
+ undefine
+ authenticated,
+ pre_execute,
+ post_execute
redefine
router
end
diff --git a/library/server/request/router/src/misc/routed_application_helper.e b/library/server/request/router/src/misc/routed_application_helper.e
index 0cce19bf..092511d2 100644
--- a/library/server/request/router/src/misc/routed_application_helper.e
+++ b/library/server/request/router/src/misc/routed_application_helper.e
@@ -14,31 +14,28 @@ feature -- Helper
execute_content_type_not_allowed (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_content_types: detachable ARRAY [STRING]; a_uri_formats: detachable ARRAY [STRING])
local
- s, uri_s: detachable STRING
+ accept_s, uri_s: detachable STRING
i, n: INTEGER
- h: EWF_HEADER
do
- create h.make
- h.put_status ({HTTP_STATUS_CODE}.unsupported_media_type)
- h.put_content_type_text_plain
-
if a_content_types /= Void then
- create s.make (10)
+ create accept_s.make (10)
from
i := a_content_types.lower
n := a_content_types.upper
until
i > n
loop
- s.append_string (a_content_types[i])
+ accept_s.append_string (a_content_types[i])
if i < n then
- s.append_character (',')
- s.append_character (' ')
+ accept_s.append_character (',')
+ accept_s.append_character (' ')
end
i := i + 1
end
- h.put_header_key_value ("Accept", s)
+ else
+ accept_s := "*/*"
end
+
if a_uri_formats /= Void then
create uri_s.make (10)
from
@@ -56,9 +53,9 @@ feature -- Helper
end
end
res.set_status_code ({HTTP_STATUS_CODE}.unsupported_media_type)
- res.write_headers_string (h.string)
- if s /= Void then
- res.write_string ("Unsupported request content-type, Accept: " + s + "%N")
+ res.write_header ({HTTP_STATUS_CODE}.unsupported_media_type, << ["Content-Type", "text/plain"], ["Accept", accept_s]>>)
+ if accept_s /= Void then
+ res.write_string ("Unsupported request content-type, Accept: " + accept_s + "%N")
end
if uri_s /= Void then
res.write_string ("Unsupported request format from the URI: " + uri_s + "%N")