Merge remote-tracking branch 'jocelynEWF/master'
This commit is contained in:
36
library/client/http_client/http_client-safe.ecf
Normal file
36
library/client/http_client/http_client-safe.ecf
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http_client" uuid="628F5A96-021B-4191-926B-B3BF49272866" library_target="http_client">
|
||||
<target name="http_client">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="cURL" location="$ISE_LIBRARY\library\cURL\cURL-safe.ecf"/>
|
||||
<library name="encoder" location="../../text/encoder/encoder-safe.ecf"/>
|
||||
<cluster name="src" location=".\src\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/request$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
|
||||
<target name="tests" extends="http_client" >
|
||||
<root class="ANY" feature="default_create"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
<assertions precondition="true"/>
|
||||
</option>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<tests name="tests" location="./tests"/>
|
||||
</target>
|
||||
|
||||
</system>
|
||||
21
library/client/http_client/http_client.ecf
Normal file
21
library/client/http_client/http_client.ecf
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http_client" uuid="628F5A96-021B-4191-926B-B3BF49272866" library_target="http_client">
|
||||
<target name="http_client">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<library name="cURL" location="$ISE_LIBRARY/library/cURL/cURL.ecf"/>
|
||||
<library name="encoder" location="../../text/encoder/encoder.ecf"/>
|
||||
<cluster name="src" location=".\src\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/request$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
16
library/client/http_client/src/http_client.e
Normal file
16
library/client/http_client/src/http_client.e
Normal file
@@ -0,0 +1,16 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTP_CLIENT
|
||||
|
||||
feature -- Status
|
||||
|
||||
new_session (a_base_url: READABLE_STRING_8): HTTP_CLIENT_SESSION
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
37
library/client/http_client/src/http_client_constants.e
Normal file
37
library/client/http_client/src/http_client_constants.e
Normal file
@@ -0,0 +1,37 @@
|
||||
note
|
||||
description: "Summary description for {HTTP_CLIENT_CONSTANTS}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HTTP_CLIENT_CONSTANTS
|
||||
|
||||
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
|
||||
Result := Auth_type_basic
|
||||
elseif s.same_string_general ("digest") then
|
||||
Result := Auth_type_digest
|
||||
elseif s.same_string_general ("any") then
|
||||
Result := Auth_type_any
|
||||
elseif s.same_string_general ("anysafe") then
|
||||
Result := Auth_type_anysafe
|
||||
elseif s.same_string_general ("none") then
|
||||
Result := Auth_type_none
|
||||
end
|
||||
end
|
||||
|
||||
Auth_type_none: INTEGER = 0
|
||||
Auth_type_basic: INTEGER = 1
|
||||
Auth_type_digest: INTEGER = 2
|
||||
Auth_type_any: INTEGER = 3
|
||||
Auth_type_anysafe: INTEGER = 4
|
||||
|
||||
end
|
||||
183
library/client/http_client/src/http_client_request.e
Normal file
183
library/client/http_client/src/http_client_request.e
Normal file
@@ -0,0 +1,183 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTP_CLIENT_REQUEST
|
||||
|
||||
inherit
|
||||
REFACTORING_HELPER
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_url: READABLE_STRING_8; a_session: like session)
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
session := a_session
|
||||
url := a_url
|
||||
headers := session.headers.twin
|
||||
end
|
||||
|
||||
session: HTTP_CLIENT_SESSION
|
||||
|
||||
feature -- Access
|
||||
|
||||
request_method: READABLE_STRING_8
|
||||
deferred
|
||||
end
|
||||
|
||||
url: READABLE_STRING_8
|
||||
|
||||
headers: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
|
||||
feature -- Execution
|
||||
|
||||
import (ctx: HTTP_CLIENT_REQUEST_CONTEXT)
|
||||
do
|
||||
headers.fill (ctx.headers)
|
||||
end
|
||||
|
||||
execute (ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Authentication
|
||||
|
||||
auth_type: STRING
|
||||
-- Set the authentication type for the request.
|
||||
-- Types: "basic", "digest", "any"
|
||||
do
|
||||
Result := session.auth_type
|
||||
end
|
||||
|
||||
auth_type_id: INTEGER
|
||||
-- Set the authentication type for the request.
|
||||
-- Types: "basic", "digest", "any"
|
||||
do
|
||||
Result := session.auth_type_id
|
||||
end
|
||||
|
||||
username: detachable READABLE_STRING_8
|
||||
do
|
||||
Result := session.username
|
||||
end
|
||||
|
||||
password: detachable READABLE_STRING_8
|
||||
do
|
||||
Result := session.password
|
||||
end
|
||||
|
||||
credentials: detachable READABLE_STRING_8
|
||||
do
|
||||
Result := session.credentials
|
||||
end
|
||||
|
||||
feature -- Settings
|
||||
|
||||
timeout: INTEGER
|
||||
-- HTTP transaction timeout in seconds.
|
||||
do
|
||||
Result := session.timeout
|
||||
end
|
||||
|
||||
connect_timeout: INTEGER
|
||||
-- HTTP connection timeout in seconds.
|
||||
do
|
||||
Result := session.connect_timeout
|
||||
end
|
||||
|
||||
max_redirects: INTEGER
|
||||
-- Maximum number of times to follow redirects.
|
||||
do
|
||||
Result := session.max_redirects
|
||||
end
|
||||
|
||||
ignore_content_length: BOOLEAN
|
||||
-- Does this session ignore Content-Size headers?
|
||||
do
|
||||
Result := session.ignore_content_length
|
||||
end
|
||||
|
||||
buffer_size: NATURAL
|
||||
-- Set the buffer size for request. This option will
|
||||
-- only be set if buffer_size is positive
|
||||
do
|
||||
Result := session.buffer_size
|
||||
end
|
||||
|
||||
default_response_charset: detachable READABLE_STRING_8
|
||||
-- Default encoding of responses. Used if no charset is provided by the host.
|
||||
do
|
||||
Result := session.default_response_charset
|
||||
end
|
||||
|
||||
feature {NONE} -- Utilities
|
||||
|
||||
append_parameters_to_url (a_url: STRING; a_parameters: detachable ARRAY [detachable TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
|
||||
-- Append parameters `a_parameters' to `a_url'
|
||||
require
|
||||
a_url_attached: a_url /= Void
|
||||
local
|
||||
i: INTEGER
|
||||
l_first_param: BOOLEAN
|
||||
do
|
||||
if a_parameters /= Void and then a_parameters.count > 0 then
|
||||
if a_url.index_of ('?', 1) > 0 then
|
||||
l_first_param := False
|
||||
elseif a_url.index_of ('&', 1) > 0 then
|
||||
l_first_param := False
|
||||
else
|
||||
l_first_param := True
|
||||
end
|
||||
from
|
||||
i := a_parameters.lower
|
||||
until
|
||||
i > a_parameters.upper
|
||||
loop
|
||||
if attached a_parameters[i] as a_param then
|
||||
if l_first_param then
|
||||
a_url.append_character ('?')
|
||||
else
|
||||
a_url.append_character ('&')
|
||||
end
|
||||
a_url.append_string (a_param.name)
|
||||
a_url.append_character ('=')
|
||||
a_url.append_string (a_param.value)
|
||||
l_first_param := False
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Utilities: encoding
|
||||
|
||||
url_encoder: URL_ENCODER
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
urlencode (s: READABLE_STRING_32): READABLE_STRING_8
|
||||
-- URL encode `s'
|
||||
do
|
||||
Result := url_encoder.encoded_string (s)
|
||||
end
|
||||
|
||||
urldecode (s: READABLE_STRING_8): READABLE_STRING_32
|
||||
-- URL decode `s'
|
||||
do
|
||||
Result := url_encoder.decoded_string (s)
|
||||
end
|
||||
|
||||
stripslashes (s: STRING): STRING
|
||||
do
|
||||
Result := s.string
|
||||
Result.replace_substring_all ("\%"", "%"")
|
||||
Result.replace_substring_all ("\'", "'")
|
||||
Result.replace_substring_all ("\/", "/")
|
||||
Result.replace_substring_all ("\\", "\")
|
||||
end
|
||||
|
||||
end
|
||||
48
library/client/http_client/src/http_client_request_context.e
Normal file
48
library/client/http_client/src/http_client_request_context.e
Normal file
@@ -0,0 +1,48 @@
|
||||
note
|
||||
description: "Summary description for {HTTP_CLIENT_REQUEST_CONTEXT}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HTTP_CLIENT_REQUEST_CONTEXT
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create headers.make (2)
|
||||
create query_parameters.make (5)
|
||||
create form_data_parameters.make (10)
|
||||
end
|
||||
|
||||
feature -- Settings
|
||||
|
||||
credentials_required: BOOLEAN
|
||||
|
||||
feature -- Access
|
||||
|
||||
headers: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
|
||||
query_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_8]
|
||||
|
||||
form_data_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_8]
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_form_data: BOOLEAN
|
||||
do
|
||||
Result := not form_data_parameters.is_empty
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_credentials_required (b: BOOLEAN)
|
||||
do
|
||||
credentials_required := b
|
||||
end
|
||||
|
||||
end
|
||||
60
library/client/http_client/src/http_client_response.e
Normal file
60
library/client/http_client/src/http_client_response.e
Normal file
@@ -0,0 +1,60 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
HTTP_CLIENT_RESPONSE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
status := 200
|
||||
raw_headers := ""
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
feature -- Access
|
||||
|
||||
status: INTEGER assign set_status
|
||||
|
||||
raw_headers: READABLE_STRING_8
|
||||
|
||||
headers: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
local
|
||||
tb: like internal_headers
|
||||
do
|
||||
tb := internal_headers
|
||||
if tb = Void then
|
||||
create tb.make (3)
|
||||
internal_headers := tb
|
||||
end
|
||||
Result := tb
|
||||
end
|
||||
|
||||
body: detachable READABLE_STRING_8 assign set_body
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_status (s: INTEGER)
|
||||
do
|
||||
status := s
|
||||
end
|
||||
|
||||
set_body (s: like body)
|
||||
do
|
||||
body := s
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
internal_headers: detachable like headers
|
||||
|
||||
end
|
||||
163
library/client/http_client/src/http_client_session.e
Normal file
163
library/client/http_client/src/http_client_session.e
Normal file
@@ -0,0 +1,163 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
deferred class
|
||||
HTTP_CLIENT_SESSION
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_base_url: READABLE_STRING_8)
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
set_defaults
|
||||
create headers.make (3)
|
||||
|
||||
base_url := a_base_url
|
||||
initialize
|
||||
end
|
||||
|
||||
set_defaults
|
||||
do
|
||||
timeout := 5
|
||||
connect_timeout := 1
|
||||
max_redirects := 5
|
||||
set_basic_auth_type
|
||||
end
|
||||
|
||||
initialize
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operation
|
||||
|
||||
get (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
deferred
|
||||
end
|
||||
|
||||
head (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
deferred
|
||||
end
|
||||
|
||||
post (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
deferred
|
||||
end
|
||||
|
||||
put (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
deferred
|
||||
end
|
||||
|
||||
delete (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Settings
|
||||
|
||||
timeout: INTEGER
|
||||
-- HTTP transaction timeout in seconds. Defaults to 5 seconds.
|
||||
|
||||
|
||||
connect_timeout: INTEGER
|
||||
-- HTTP connection timeout in seconds. Defaults to 1 second.
|
||||
|
||||
max_redirects: INTEGER
|
||||
-- Maximum number of times to follow redirects.
|
||||
-- Set to 0 to disable and -1 to follow all redirects. Defaults to 5.
|
||||
|
||||
ignore_content_length: BOOLEAN
|
||||
-- Does this session ignore Content-Size headers?
|
||||
|
||||
buffer_size: NATURAL
|
||||
-- Set the buffer size for request. This option will
|
||||
-- only be set if buffer_size is positive
|
||||
|
||||
default_response_charset: detachable READABLE_STRING_8
|
||||
-- Default encoding of responses. Used if no charset is provided by the host.
|
||||
|
||||
feature -- Access
|
||||
|
||||
base_url: READABLE_STRING_8
|
||||
|
||||
headers: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
|
||||
feature -- Authentication
|
||||
|
||||
auth_type: STRING
|
||||
-- Set the authentication type for the request.
|
||||
-- Types: "basic", "digest", "any"
|
||||
|
||||
auth_type_id: INTEGER
|
||||
-- See {HTTP_CLIENT_CONSTANTS}.Auth_type_*
|
||||
|
||||
username,
|
||||
password: detachable READABLE_STRING_8
|
||||
|
||||
credentials: detachable READABLE_STRING_8
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_timeout (n: like timeout)
|
||||
do
|
||||
timeout := n
|
||||
end
|
||||
|
||||
set_user_agent (v: READABLE_STRING_8)
|
||||
do
|
||||
add_header ("User-Agent", v)
|
||||
end
|
||||
|
||||
add_header (k: READABLE_STRING_8; v: READABLE_STRING_8)
|
||||
do
|
||||
headers.force (v, k)
|
||||
end
|
||||
|
||||
set_credentials (u: like username; p: like password)
|
||||
do
|
||||
username := u
|
||||
password := p
|
||||
if u /= Void and p /= Void then
|
||||
credentials := u + ":" + p
|
||||
else
|
||||
credentials := Void
|
||||
end
|
||||
end
|
||||
|
||||
set_auth_type (s: READABLE_STRING_8)
|
||||
do
|
||||
auth_type := s
|
||||
auth_type_id := http_client_constants.auth_type_id (s)
|
||||
end
|
||||
|
||||
set_basic_auth_type
|
||||
do
|
||||
auth_type := "basic"
|
||||
auth_type_id := {HTTP_CLIENT_CONSTANTS}.auth_type_basic
|
||||
end
|
||||
|
||||
set_digest_auth_type
|
||||
do
|
||||
auth_type := "digest"
|
||||
auth_type_id := {HTTP_CLIENT_CONSTANTS}.auth_type_digest
|
||||
end
|
||||
|
||||
set_any_auth_type
|
||||
do
|
||||
auth_type := "any"
|
||||
auth_type_id := {HTTP_CLIENT_CONSTANTS}.auth_type_any
|
||||
end
|
||||
|
||||
set_anysafe_auth_type
|
||||
do
|
||||
auth_type := "anysafe"
|
||||
auth_type_id := {HTTP_CLIENT_CONSTANTS}.auth_type_anysafe
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
http_client_constants: HTTP_CLIENT_CONSTANTS
|
||||
once
|
||||
create Result
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,30 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
LIBCURL_HTTP_CLIENT
|
||||
|
||||
inherit
|
||||
HTTP_CLIENT
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
new_session (a_base_url: READABLE_STRING_8): LIBCURL_HTTP_CLIENT_SESSION
|
||||
do
|
||||
create Result.make (a_base_url)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,192 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
LIBCURL_HTTP_CLIENT_REQUEST
|
||||
|
||||
inherit
|
||||
HTTP_CLIENT_REQUEST
|
||||
rename
|
||||
make as make_request
|
||||
redefine
|
||||
session
|
||||
end
|
||||
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_url: READABLE_STRING_8; a_request_method: like request_method; a_session: like session)
|
||||
do
|
||||
make_request (a_url, a_session)
|
||||
request_method := a_request_method
|
||||
end
|
||||
|
||||
session: LIBCURL_HTTP_CLIENT_SESSION
|
||||
|
||||
feature -- Access
|
||||
|
||||
request_method: READABLE_STRING_8
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
local
|
||||
l_result: INTEGER
|
||||
l_curl_string: CURL_STRING
|
||||
l_url: READABLE_STRING_8
|
||||
p: POINTER
|
||||
a_data: CELL [detachable ANY]
|
||||
l_form, l_last: CURL_FORM
|
||||
curl: CURL_EXTERNALS
|
||||
curl_easy: CURL_EASY_EXTERNALS
|
||||
curl_handle: POINTER
|
||||
do
|
||||
curl := session.curl
|
||||
curl_easy := session.curl_easy
|
||||
|
||||
l_url := url
|
||||
if ctx /= Void then
|
||||
if attached ctx.query_parameters as l_query_params then
|
||||
from
|
||||
l_query_params.start
|
||||
until
|
||||
l_query_params.after
|
||||
loop
|
||||
append_parameters_to_url (l_url, <<[l_query_params.key_for_iteration, urlencode (l_query_params.item_for_iteration)]>>)
|
||||
l_query_params.forth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--| Configure cURL session
|
||||
curl_handle := curl_easy.init
|
||||
|
||||
--| URL
|
||||
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_url, l_url)
|
||||
|
||||
--| Timeout
|
||||
if timeout > 0 then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_timeout, timeout)
|
||||
end
|
||||
--| Connect Timeout
|
||||
if connect_timeout > 0 then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_connecttimeout, timeout)
|
||||
end
|
||||
--| Redirection
|
||||
if max_redirects /= 0 then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_followlocation, 1)
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_maxredirs, max_redirects)
|
||||
else
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_followlocation, 0)
|
||||
end
|
||||
|
||||
if request_method.is_case_insensitive_equal ("GET") then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpget, 1)
|
||||
elseif request_method.is_case_insensitive_equal ("POST") then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_post, 1)
|
||||
elseif request_method.is_case_insensitive_equal ("PUT") then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_put, 1)
|
||||
elseif request_method.is_case_insensitive_equal ("HEAD") then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_nobody, 1)
|
||||
elseif request_method.is_case_insensitive_equal ("DELETE") then
|
||||
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_customrequest, "DELETE")
|
||||
else
|
||||
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_customrequest, request_method)
|
||||
--| ignored
|
||||
end
|
||||
|
||||
--| Credential
|
||||
if ctx /= Void and then ctx.credentials_required then
|
||||
if attached credentials as l_credentials then
|
||||
inspect auth_type_id
|
||||
when {HTTP_CLIENT_CONSTANTS}.Auth_type_none then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_none)
|
||||
when {HTTP_CLIENT_CONSTANTS}.Auth_type_basic then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_basic)
|
||||
when {HTTP_CLIENT_CONSTANTS}.Auth_type_digest then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_digest)
|
||||
when {HTTP_CLIENT_CONSTANTS}.Auth_type_any then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_any)
|
||||
when {HTTP_CLIENT_CONSTANTS}.Auth_type_anysafe then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpauth, {CURL_OPT_CONSTANTS}.curlauth_anysafe)
|
||||
else
|
||||
end
|
||||
|
||||
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_userpwd, l_credentials)
|
||||
else
|
||||
--| Credentials not prov ided ...
|
||||
end
|
||||
end
|
||||
|
||||
if ctx /= Void and then ctx.has_form_data then
|
||||
if attached ctx.form_data_parameters as l_posts and then not l_posts.is_empty then
|
||||
-- curl_easy.set_debug_function (curl_handle)
|
||||
-- curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_verbose, 1)
|
||||
|
||||
create l_form.make
|
||||
create l_last.make
|
||||
from
|
||||
l_posts.start
|
||||
until
|
||||
l_posts.after
|
||||
loop
|
||||
curl.formadd_string_string (l_form, l_last, {CURL_FORM_CONSTANTS}.CURLFORM_COPYNAME, l_posts.key_for_iteration, {CURL_FORM_CONSTANTS}.CURLFORM_COPYCONTENTS, l_posts.item_for_iteration, {CURL_FORM_CONSTANTS}.CURLFORM_END)
|
||||
l_posts.forth
|
||||
end
|
||||
l_last.release_item
|
||||
curl_easy.setopt_form (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httppost, l_form)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
curl.global_init
|
||||
if attached headers as l_headers then
|
||||
across
|
||||
l_headers as curs
|
||||
loop
|
||||
p := curl.slist_append (p, curs.key + ": " + curs.item)
|
||||
-- curl_easy.setopt_slist (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpheader, p)
|
||||
end
|
||||
end
|
||||
|
||||
p := curl.slist_append (p, "Expect:")
|
||||
curl_easy.setopt_slist (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpheader, p)
|
||||
|
||||
|
||||
curl.global_cleanup
|
||||
|
||||
curl_easy.set_read_function (curl_handle)
|
||||
curl_easy.set_write_function (curl_handle)
|
||||
create l_curl_string.make_empty
|
||||
curl_easy.setopt_curl_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_writedata, l_curl_string)
|
||||
|
||||
debug ("service")
|
||||
io.put_string ("SERVICE: " + l_url)
|
||||
io.put_new_line
|
||||
end
|
||||
|
||||
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
|
||||
else
|
||||
Result.status := 0
|
||||
end
|
||||
|
||||
-- last_api_call := l_url
|
||||
curl_easy.cleanup (curl_handle)
|
||||
|
||||
|
||||
Result.body := l_curl_string.string
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,85 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
LIBCURL_HTTP_CLIENT_SESSION
|
||||
|
||||
inherit
|
||||
HTTP_CLIENT_SESSION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
do
|
||||
create curl -- cURL externals
|
||||
create curl_easy -- cURL easy externals
|
||||
end
|
||||
|
||||
feature -- Basic operation
|
||||
|
||||
get (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
local
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "GET", Current)
|
||||
Result := execute_request (req, ctx)
|
||||
end
|
||||
|
||||
head (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
local
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "HEAD", Current)
|
||||
Result := execute_request (req, ctx)
|
||||
end
|
||||
|
||||
post (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
local
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "POST", Current)
|
||||
Result := execute_request (req, ctx)
|
||||
end
|
||||
|
||||
put (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
local
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "PUT", Current)
|
||||
Result := execute_request (req, ctx)
|
||||
end
|
||||
|
||||
delete (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
local
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "DELETE", Current)
|
||||
Result := execute_request (req, ctx)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
execute_request (req: HTTP_CLIENT_REQUEST; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
do
|
||||
if ctx /= Void then
|
||||
req.import (ctx)
|
||||
end
|
||||
Result := req.execute (ctx)
|
||||
end
|
||||
|
||||
feature {LIBCURL_HTTP_CLIENT_REQUEST} -- Curl implementation
|
||||
|
||||
curl: CURL_EXTERNALS
|
||||
-- cURL externals
|
||||
|
||||
curl_easy: CURL_EASY_EXTERNALS
|
||||
-- cURL easy externals
|
||||
|
||||
|
||||
end
|
||||
@@ -22,6 +22,7 @@ feature {NONE} -- Initialization
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
create {ARRAYED_LIST [ERROR]} errors.make (3)
|
||||
create error_added_actions
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
@@ -37,6 +38,8 @@ feature -- Status
|
||||
Result := errors.count
|
||||
end
|
||||
|
||||
feature {ERROR_HANDLER, ERROR_VISITOR} -- Restricted access
|
||||
|
||||
errors: LIST [ERROR]
|
||||
-- Errors container
|
||||
|
||||
@@ -52,12 +55,26 @@ feature -- Status report
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Events
|
||||
|
||||
error_added_actions: ACTION_SEQUENCE [TUPLE [ERROR]]
|
||||
-- Actions triggered when a new error is added
|
||||
|
||||
feature {NONE} -- Event: implementation
|
||||
|
||||
on_error_added (e: ERROR)
|
||||
-- Error `e' was just added
|
||||
do
|
||||
error_added_actions.call ([e])
|
||||
end
|
||||
|
||||
feature -- Basic operation
|
||||
|
||||
add_error (a_error: ERROR)
|
||||
-- Add `a_error' to the stack of error
|
||||
do
|
||||
errors.force (a_error)
|
||||
on_error_added (a_error)
|
||||
end
|
||||
|
||||
add_error_details, add_custom_error (a_code: INTEGER; a_name: STRING; a_message: detachable STRING_32)
|
||||
@@ -69,10 +86,25 @@ feature -- Basic operation
|
||||
add_error (e)
|
||||
end
|
||||
|
||||
append (a_err_handler: ERROR_HANDLER)
|
||||
append (other: ERROR_HANDLER)
|
||||
-- Append errors from `a_err_handler'
|
||||
local
|
||||
other_errs: LIST [ERROR]
|
||||
do
|
||||
errors.append (a_err_handler.errors)
|
||||
other_errs := other.errors
|
||||
if other_errs.count > 0 then
|
||||
from
|
||||
other_errs.start
|
||||
until
|
||||
other_errs.after
|
||||
loop
|
||||
add_error (other_errs.item)
|
||||
other_errs.forth
|
||||
end
|
||||
end
|
||||
ensure
|
||||
other_error_appended: other.has_error implies has_error
|
||||
new_count: count = old count + other.count
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
@@ -107,7 +139,7 @@ feature -- Element changes
|
||||
do
|
||||
if count > 1 and then attached as_single_error as e then
|
||||
wipe_out
|
||||
add_error (e)
|
||||
errors.force (e)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
11
library/error/src/error_handler_with_event.e
Normal file
11
library/error/src/error_handler_with_event.e
Normal file
@@ -0,0 +1,11 @@
|
||||
note
|
||||
|
||||
description: "Summary description for {ERROR_HANDLER_WITH_EVENT}."
|
||||
|
||||
author: ""
|
||||
|
||||
date: "$Date$"
|
||||
|
||||
revision: "$Revision$"
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http_authorization" uuid="321674DB-CE7C-417C-ADE8-64CFA376CD3E" library_target="http_authorization">
|
||||
<target name="http_authorization">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base-safe.ecf"/>
|
||||
<library name="encoder" location="..\..\..\text\encoder\encoder-safe.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http_authorization" uuid="321674DB-CE7C-417C-ADE8-64CFA376CD3E" library_target="http_authorization">
|
||||
<target name="http_authorization">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<library name="encoder" location="..\..\..\text\encoder\encoder.ecf"/>
|
||||
<cluster name="src" location="./src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -0,0 +1,48 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
HTTP_AUTHORIZATION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_http_authorization: detachable READABLE_STRING_GENERAL)
|
||||
-- Initialize `Current'.
|
||||
local
|
||||
p: INTEGER
|
||||
s: 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
|
||||
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
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
login: detachable READABLE_STRING_32
|
||||
|
||||
password: detachable READABLE_STRING_32
|
||||
|
||||
|
||||
end
|
||||
@@ -96,6 +96,16 @@ feature -- Access: CGI meta variables
|
||||
deferred
|
||||
end
|
||||
|
||||
meta_string_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
-- Environment variable related to `a_name'
|
||||
require
|
||||
a_name_valid: a_name /= Void and then not a_name.is_empty
|
||||
do
|
||||
if attached meta_variable (a_name) as val then
|
||||
Result := val.as_string
|
||||
end
|
||||
end
|
||||
|
||||
meta_variables: ITERATION_CURSOR [WGI_VALUE]
|
||||
-- These variables are specific to requests made with HTTP.
|
||||
-- Interpretation of these variables may depend on the value of
|
||||
@@ -687,10 +697,10 @@ invariant
|
||||
query_string_attached: query_string /= Void
|
||||
remote_addr_attached: remote_addr /= Void
|
||||
|
||||
same_orig_path_info: orig_path_info ~ meta_variable ({WGI_META_NAMES}.orig_path_info)
|
||||
same_path_info: path_info ~ meta_variable ({WGI_META_NAMES}.path_info)
|
||||
same_orig_path_info: orig_path_info ~ meta_string_variable ({WGI_META_NAMES}.orig_path_info)
|
||||
same_path_info: path_info ~ meta_string_variable ({WGI_META_NAMES}.path_info)
|
||||
|
||||
path_info_identical: path_info ~ meta_variable ({WGI_META_NAMES}.path_info)
|
||||
path_info_identical: path_info ~ meta_string_variable ({WGI_META_NAMES}.path_info)
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
|
||||
@@ -7,6 +7,9 @@ note
|
||||
deferred class
|
||||
WGI_VALUE
|
||||
|
||||
inherit
|
||||
DEBUG_OUTPUT
|
||||
|
||||
convert
|
||||
as_string: {READABLE_STRING_32, STRING_32}
|
||||
|
||||
@@ -29,6 +32,14 @@ feature -- Helper
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
create Result.make_from_string (name.as_string_8 + "=" + as_string.as_string_8)
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
as_string: STRING_32
|
||||
|
||||
@@ -114,13 +114,13 @@ feature {NONE} -- Initialization
|
||||
if attached request_uri as rq_uri then
|
||||
p := rq_uri.index_of ('?', 1)
|
||||
if p > 0 then
|
||||
set_meta_string_variable (rq_uri.substring (1, p-1), {WGI_META_NAMES}.self)
|
||||
set_meta_string_variable ({WGI_META_NAMES}.self, rq_uri.substring (1, p-1))
|
||||
else
|
||||
set_meta_string_variable (rq_uri, {WGI_META_NAMES}.self)
|
||||
set_meta_string_variable ({WGI_META_NAMES}.self, rq_uri)
|
||||
end
|
||||
end
|
||||
if meta_variable ({WGI_META_NAMES}.request_time) = Void then
|
||||
set_meta_string_variable (date_time_utilities.unix_time_stamp (Void).out, {WGI_META_NAMES}.request_time)
|
||||
set_meta_string_variable ({WGI_META_NAMES}.request_time, date_time_utilities.unix_time_stamp (Void).out)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -185,14 +185,6 @@ feature -- Access: CGI meta parameters
|
||||
Result := meta_variables_table.item (a_name)
|
||||
end
|
||||
|
||||
meta_string_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
-- CGI meta variable related to `a_name'
|
||||
do
|
||||
if attached meta_variables_table.item (a_name) as val then
|
||||
Result := val.as_string
|
||||
end
|
||||
end
|
||||
|
||||
meta_string_variable_or_default (a_name: READABLE_STRING_GENERAL; a_default: READABLE_STRING_32; use_default_when_empty: BOOLEAN): READABLE_STRING_32
|
||||
-- Value for meta parameter `a_name'
|
||||
-- If not found, return `a_default'
|
||||
|
||||
@@ -23,7 +23,7 @@ feature -- Access
|
||||
end
|
||||
|
||||
description: detachable STRING
|
||||
-- Optional descriptiong
|
||||
-- Optional description
|
||||
|
||||
feature -- Element change
|
||||
|
||||
@@ -42,7 +42,7 @@ feature -- Execution
|
||||
do
|
||||
if not rescued then
|
||||
if request_method_name_supported (req.request_method) then
|
||||
if authentication_required (req) and then not ctx.authenticated then
|
||||
if authentication_required (req) and then not authenticated (ctx) then
|
||||
execute_unauthorized (ctx, req, res)
|
||||
else
|
||||
pre_execute (ctx, req, res)
|
||||
@@ -83,6 +83,15 @@ feature -- Execution
|
||||
res.write_header ({HTTP_STATUS_CODE}.unauthorized, Void)
|
||||
res.write_string ("Unauthorized")
|
||||
end
|
||||
|
||||
feature -- Auth
|
||||
|
||||
authenticated (ctx: C): BOOLEAN
|
||||
-- Is authenticated?
|
||||
do
|
||||
--| To redefine if needed
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
supported_formats: INTEGER
|
||||
|
||||
@@ -54,17 +54,6 @@ feature -- Status report
|
||||
result_attached: Result /= Void
|
||||
end
|
||||
|
||||
authenticated: BOOLEAN
|
||||
do
|
||||
if request.http_authorization /= Void then
|
||||
Result := True
|
||||
end
|
||||
end
|
||||
|
||||
authenticated_identifier: detachable READABLE_STRING_32
|
||||
do
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -31,7 +31,7 @@ feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
Precursor {REST_REQUEST_HANDLER} (ctx, req, res)
|
||||
Precursor {REQUEST_URI_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
end
|
||||
|
||||
execute_application (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
|
||||
@@ -38,7 +38,7 @@ feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
do
|
||||
Precursor {REST_REQUEST_HANDLER} (ctx, req, res)
|
||||
Precursor {REQUEST_URI_TEMPLATE_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
end
|
||||
|
||||
execute_application (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<target name="sample_fcgi" extends="common">
|
||||
<root class="APP_SERVER" feature="make"/>
|
||||
<setting name="executable_name" value="sample"/>
|
||||
<library name="ewsgi_fcgi" location="..\..\..\ewsgi/connectors\fcgi\fcgi-safe.ecf" readonly="false"/>
|
||||
<library name="ewsgi_fcgi" location="..\..\..\ewsgi/connectors\libfcgi\libfcgi-safe.ecf" readonly="false"/>
|
||||
<cluster name="src" location=".\src\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/gateway$</exclude>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
<assertions precondition="true"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true">
|
||||
<option warning="true" full_class_checking="true" syntax="provisional">
|
||||
<assertions precondition="true"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
note
|
||||
description: "[
|
||||
Summary description for REQUEST_HANDLER_ROUTES_RECORDER.
|
||||
|
||||
You can inherit from this class from any REQUEST_HANDLER and redefine `on_handler_mapped'
|
||||
to record the available routes if your handler needs it.
|
||||
]"
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
REQUEST_HANDLER_ROUTES_RECORDER
|
||||
|
||||
feature {REQUEST_HANDLER} -- Routes access
|
||||
|
||||
available_routes: detachable LIST [TUPLE [resource: READABLE_STRING_8; rqst_methods: detachable ARRAY [READABLE_STRING_8]]]
|
||||
-- Available routes
|
||||
|
||||
feature {REQUEST_ROUTER} -- Routes change
|
||||
|
||||
on_handler_mapped (a_resource: READABLE_STRING_8; a_rqst_methods: detachable ARRAY [READABLE_STRING_8])
|
||||
local
|
||||
l_routes: like available_routes
|
||||
do
|
||||
l_routes := available_routes
|
||||
if l_routes = Void then
|
||||
create {ARRAYED_LIST [like available_routes.item]} l_routes.make (3)
|
||||
available_routes := l_routes
|
||||
end
|
||||
l_routes.force ([a_resource, a_rqst_methods])
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
@@ -65,6 +65,13 @@ feature -- Execution: report
|
||||
result_attached: Result /= Void
|
||||
end
|
||||
|
||||
feature {REQUEST_ROUTER} -- Routes change
|
||||
|
||||
on_handler_mapped (a_resource: READABLE_STRING_8; a_rqst_methods: detachable ARRAY [READABLE_STRING_8])
|
||||
-- Callback called when a router map a route to Current handler
|
||||
do
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -98,6 +98,8 @@ feature -- Query
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
else
|
||||
Result := s
|
||||
end
|
||||
l_accept_lst.forth
|
||||
end
|
||||
|
||||
@@ -26,6 +26,7 @@ feature -- Registration
|
||||
map_with_request_methods (p: READABLE_STRING_8; h: H; rqst_methods: detachable ARRAY [READABLE_STRING_8])
|
||||
do
|
||||
handlers.force ([h, p, formatted_request_methods (rqst_methods)])
|
||||
h.on_handler_mapped (p, rqst_methods)
|
||||
end
|
||||
|
||||
feature {NONE} -- Access: Implementation
|
||||
|
||||
@@ -33,6 +33,7 @@ feature -- Registration
|
||||
do
|
||||
handlers.force ([h, uri.template, formatted_request_methods (rqst_methods)])
|
||||
templates.force (uri, uri.template)
|
||||
h.on_handler_mapped (uri.template, rqst_methods)
|
||||
end
|
||||
|
||||
map_with_request_methods (tpl: READABLE_STRING_8; h: H; rqst_methods: detachable ARRAY [READABLE_STRING_8])
|
||||
@@ -53,7 +54,7 @@ feature {NONE} -- Access: Implementation
|
||||
l_req_method: READABLE_STRING_GENERAL
|
||||
l_res: URI_TEMPLATE_MATCH_RESULT
|
||||
do
|
||||
p := req.request_uri
|
||||
p := req.path_info
|
||||
from
|
||||
l_req_method := req.request_method
|
||||
l_handlers := handlers
|
||||
|
||||
@@ -6,7 +6,7 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
ENCODER [U -> STRING_GENERAL, E -> STRING_GENERAL] --| U:unencoded type, E:encoded type
|
||||
ENCODER [U -> READABLE_STRING_GENERAL, E -> READABLE_STRING_GENERAL] --| U:unencoded type, E:encoded type
|
||||
|
||||
feature -- Access
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class
|
||||
URL_ENCODER
|
||||
|
||||
inherit
|
||||
ENCODER [STRING_32, STRING_8]
|
||||
ENCODER [READABLE_STRING_32, READABLE_STRING_8]
|
||||
|
||||
PLATFORM
|
||||
export
|
||||
@@ -30,15 +30,17 @@ feature -- Status report
|
||||
|
||||
feature -- Encoder
|
||||
|
||||
encoded_string (s: STRING_32): STRING_8
|
||||
encoded_string (s: READABLE_STRING_32): READABLE_STRING_8
|
||||
-- URL-encoded value of `s'.
|
||||
local
|
||||
i, n: INTEGER
|
||||
uc: CHARACTER_32
|
||||
c: CHARACTER_8
|
||||
s8: STRING_8
|
||||
do
|
||||
has_error := False
|
||||
create Result.make (s.count + s.count // 10)
|
||||
create s8.make (s.count + s.count // 10)
|
||||
Result := s8
|
||||
n := s.count
|
||||
from i := 1 until i > n loop
|
||||
uc := s.item (i)
|
||||
@@ -50,28 +52,30 @@ feature -- Encoder
|
||||
'a' .. 'z', '0' .. '9',
|
||||
'.', '-', '~', '_'
|
||||
then
|
||||
Result.extend (c)
|
||||
s8.extend (c)
|
||||
when ' ' then
|
||||
Result.extend ('+')
|
||||
s8.extend ('+')
|
||||
else
|
||||
Result.append (url_encoded_char (uc))
|
||||
s8.append (url_encoded_char (uc))
|
||||
end
|
||||
else
|
||||
Result.append (url_encoded_char (uc))
|
||||
s8.append (url_encoded_char (uc))
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
partial_encoded_string (s: STRING_32; a_ignore: ARRAY [CHARACTER]): STRING_8
|
||||
partial_encoded_string (s: READABLE_STRING_32; a_ignore: ARRAY [CHARACTER]): READABLE_STRING_8
|
||||
-- URL-encoded value of `s'.
|
||||
local
|
||||
i, n: INTEGER
|
||||
uc: CHARACTER_32
|
||||
c: CHARACTER_8
|
||||
s8: STRING_8
|
||||
do
|
||||
has_error := False
|
||||
create Result.make (s.count + s.count // 10)
|
||||
create s8.make (s.count + s.count // 10)
|
||||
Result := s8
|
||||
n := s.count
|
||||
from i := 1 until i > n loop
|
||||
uc := s.item (i)
|
||||
@@ -83,21 +87,21 @@ feature -- Encoder
|
||||
'a' .. 'z', '0' .. '9',
|
||||
'.', '-', '~', '_'
|
||||
then
|
||||
Result.extend (c)
|
||||
s8.extend (c)
|
||||
when ' ' then
|
||||
Result.extend ('+')
|
||||
s8.extend ('+')
|
||||
else
|
||||
if a_ignore.has (c) then
|
||||
Result.extend (c)
|
||||
s8.extend (c)
|
||||
else
|
||||
Result.append (url_encoded_char (uc))
|
||||
s8.append (url_encoded_char (uc))
|
||||
end
|
||||
end
|
||||
else
|
||||
if a_ignore.has (c) then
|
||||
Result.extend (c)
|
||||
s8.extend (c)
|
||||
else
|
||||
Result.append (url_encoded_char (uc))
|
||||
s8.append (url_encoded_char (uc))
|
||||
end
|
||||
end
|
||||
i := i + 1
|
||||
@@ -127,33 +131,35 @@ feature {NONE} -- encoder character
|
||||
|
||||
feature -- Decoder
|
||||
|
||||
decoded_string (v: STRING_8): STRING_32
|
||||
decoded_string (v: READABLE_STRING_8): READABLE_STRING_32
|
||||
-- The URL-encoded equivalent of the given string
|
||||
local
|
||||
i, n: INTEGER
|
||||
c: CHARACTER
|
||||
pr: CELL [INTEGER]
|
||||
s32: STRING_32
|
||||
do
|
||||
n := v.count
|
||||
create Result.make (n)
|
||||
create s32.make (n)
|
||||
Result := s32
|
||||
from i := 1
|
||||
until i > n
|
||||
loop
|
||||
c := v.item (i)
|
||||
inspect c
|
||||
when '+' then
|
||||
Result.append_character ({CHARACTER_32}' ')
|
||||
s32.append_character ({CHARACTER_32}' ')
|
||||
when '%%' then
|
||||
-- An escaped character ?
|
||||
if i = n then
|
||||
Result.append_character (c.to_character_32)
|
||||
s32.append_character (c.to_character_32)
|
||||
else
|
||||
create pr.put (i)
|
||||
Result.append (url_decoded_char (v, pr))
|
||||
s32.append (url_decoded_char (v, pr))
|
||||
i := pr.item
|
||||
end
|
||||
else
|
||||
Result.append_character (c.to_character_32)
|
||||
s32.append_character (c.to_character_32)
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user