Merge changes from Javier
- update on RESTbuck examples - new example - fixed bad typo in WSF_REQUEST Reverted some changes such as - http_client_response: keep the headers as a list to handle multiple message-value with same message-name Fixed simple and simple_file example Improved HTTP_HEADER Changed libcurl implementation for http client - now the header from the context really overwrite any of the session headers - better design which is more strict, and remove any doubt about context's header usage
This commit is contained in:
@@ -12,16 +12,25 @@ inherit
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_url: READABLE_STRING_8; a_session: like session)
|
||||
make (a_url: READABLE_STRING_8; a_session: like session; ctx: like context)
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
session := a_session
|
||||
url := a_url
|
||||
headers := session.headers.twin
|
||||
if ctx /= Void then
|
||||
context := ctx
|
||||
import (ctx)
|
||||
end
|
||||
ensure
|
||||
context_set: context = ctx
|
||||
ctx_header_set: ctx /= Void implies across ctx.headers as ctx_h all attached headers.item (ctx_h.key) as v and then v.same_string (ctx_h.item) end
|
||||
end
|
||||
|
||||
session: HTTP_CLIENT_SESSION
|
||||
|
||||
context: detachable HTTP_CLIENT_REQUEST_CONTEXT
|
||||
|
||||
feature -- Access
|
||||
|
||||
request_method: READABLE_STRING_8
|
||||
@@ -32,14 +41,23 @@ feature -- Access
|
||||
|
||||
headers: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
|
||||
feature -- Execution
|
||||
feature {HTTP_CLIENT_SESSION} -- Execution
|
||||
|
||||
import (ctx: HTTP_CLIENT_REQUEST_CONTEXT)
|
||||
local
|
||||
l_headers: like headers
|
||||
do
|
||||
headers.fill (ctx.headers)
|
||||
l_headers := headers
|
||||
across
|
||||
ctx.headers as ctx_headers
|
||||
loop
|
||||
--| fill header from `ctx'
|
||||
--| and use `force' to overwrite the "session" value if any
|
||||
l_headers.force (ctx_headers.item, ctx_headers.key)
|
||||
end
|
||||
end
|
||||
|
||||
execute (ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
execute: HTTP_CLIENT_RESPONSE
|
||||
deferred
|
||||
end
|
||||
|
||||
|
||||
@@ -41,8 +41,43 @@ feature -- Access
|
||||
raw_header: READABLE_STRING_8
|
||||
-- Raw http header of the response.
|
||||
|
||||
header (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- Header entry value related to `a_name'
|
||||
-- if multiple entries, just concatenate them using comma character
|
||||
--| See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html
|
||||
--| Multiple message-header fields with the same field-name MAY be present in a message
|
||||
--| if and only if the entire field-value for that header field is defined as a comma-separated list [i.e., #(values)].
|
||||
--| It MUST be possible to combine the multiple header fields into one "field-name: field-value" pair,
|
||||
--| without changing the semantics of the message, by appending each subsequent field-value to the first, each separated by a comma.
|
||||
--| The order in which header fields with the same field-name are received is therefore significant
|
||||
--| to the interpretation of the combined field value, and thus a proxy MUST NOT change the order of
|
||||
--| these field values when a message is forwarded.
|
||||
local
|
||||
s: detachable STRING_8
|
||||
k,v: READABLE_STRING_8
|
||||
do
|
||||
across
|
||||
headers as hds
|
||||
loop
|
||||
k := hds.item.key
|
||||
if k.same_string (a_name) then
|
||||
v := hds.item.value
|
||||
if s = Void then
|
||||
create s.make_from_string (v)
|
||||
else
|
||||
s.append_character (',')
|
||||
s.append (v)
|
||||
end
|
||||
end
|
||||
end
|
||||
Result := s
|
||||
end
|
||||
|
||||
headers: LIST [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]]
|
||||
-- Computed table of http headers of the response.
|
||||
--| We use a LIST since one might have multiple message-header fields with the same field-name
|
||||
--| Then the user can handle those case using default or custom concatenation
|
||||
--| (note: `header' is concatenating using comma)
|
||||
local
|
||||
tb: like internal_headers
|
||||
pos, l_start, l_end, n, c: INTEGER
|
||||
@@ -126,6 +161,6 @@ feature -- Change
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
internal_headers: detachable ARRAYED_LIST [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]]
|
||||
-- Internal cached value for the headers
|
||||
-- Internal cached value for the headers
|
||||
|
||||
end
|
||||
|
||||
@@ -20,9 +20,9 @@ create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_url: READABLE_STRING_8; a_request_method: like request_method; a_session: like session)
|
||||
make (a_url: READABLE_STRING_8; a_request_method: like request_method; a_session: like session; ctx: like context)
|
||||
do
|
||||
make_request (a_url, a_session)
|
||||
make_request (a_url, a_session, ctx)
|
||||
request_method := a_request_method
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ feature -- Access
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute (ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
execute: HTTP_CLIENT_RESPONSE
|
||||
local
|
||||
l_result: INTEGER
|
||||
l_curl_string: CURL_STRING
|
||||
@@ -45,7 +45,9 @@ feature -- Execution
|
||||
curl: CURL_EXTERNALS
|
||||
curl_easy: CURL_EASY_EXTERNALS
|
||||
curl_handle: POINTER
|
||||
ctx: like context
|
||||
do
|
||||
ctx := context
|
||||
curl := session.curl
|
||||
curl_easy := session.curl_easy
|
||||
|
||||
@@ -167,7 +169,15 @@ feature -- Execution
|
||||
p := curl.slist_append (p, curs.key + ": " + curs.item)
|
||||
end
|
||||
end
|
||||
|
||||
if ctx /= Void then
|
||||
if attached ctx.headers as l_headers_2 then
|
||||
across
|
||||
l_headers_2 as curs_2
|
||||
loop
|
||||
p := curl.slist_append (p, curs_2.key + ": " + curs_2.item)
|
||||
end
|
||||
end
|
||||
end
|
||||
p := curl.slist_append (p, "Expect:")
|
||||
curl_easy.setopt_slist (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpheader, p)
|
||||
|
||||
|
||||
@@ -27,16 +27,16 @@ feature -- Basic operation
|
||||
local
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "GET", Current)
|
||||
Result := execute_request (req, ctx)
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "GET", Current, ctx)
|
||||
Result := req.execute
|
||||
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)
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "HEAD", Current, ctx)
|
||||
Result := req.execute
|
||||
end
|
||||
|
||||
post (a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; data: detachable READABLE_STRING_8): HTTP_CLIENT_RESPONSE
|
||||
@@ -54,7 +54,6 @@ feature -- Basic operation
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "POST", Current)
|
||||
ctx := a_ctx
|
||||
if data /= Void then
|
||||
if ctx = Void then
|
||||
@@ -68,7 +67,8 @@ feature -- Basic operation
|
||||
end
|
||||
ctx.set_upload_filename (fn)
|
||||
end
|
||||
Result := execute_request (req, ctx)
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "POST", Current, ctx)
|
||||
Result := req.execute
|
||||
end
|
||||
|
||||
put (a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; data: detachable READABLE_STRING_8): HTTP_CLIENT_RESPONSE
|
||||
@@ -76,7 +76,6 @@ feature -- Basic operation
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "PUT", Current)
|
||||
ctx := a_ctx
|
||||
if data /= Void then
|
||||
if ctx = Void then
|
||||
@@ -84,7 +83,8 @@ feature -- Basic operation
|
||||
end
|
||||
ctx.set_upload_data (data)
|
||||
end
|
||||
Result := execute_request (req, ctx)
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "PUT", Current, ctx)
|
||||
Result := req.execute
|
||||
end
|
||||
|
||||
put_file (a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; fn: detachable READABLE_STRING_8): HTTP_CLIENT_RESPONSE
|
||||
@@ -92,7 +92,6 @@ feature -- Basic operation
|
||||
req: HTTP_CLIENT_REQUEST
|
||||
ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT
|
||||
do
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "PUT", Current)
|
||||
ctx := a_ctx
|
||||
if fn /= Void then
|
||||
if ctx = Void then
|
||||
@@ -100,25 +99,16 @@ feature -- Basic operation
|
||||
end
|
||||
ctx.set_upload_filename (fn)
|
||||
end
|
||||
Result := execute_request (req, ctx)
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "PUT", Current, ctx)
|
||||
Result := req.execute
|
||||
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)
|
||||
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "DELETE", Current, ctx)
|
||||
Result := req.execute
|
||||
end
|
||||
|
||||
feature {LIBCURL_HTTP_CLIENT_REQUEST} -- Curl implementation
|
||||
|
||||
@@ -196,13 +196,13 @@ feature -- Content related header
|
||||
put_transfer_encoding_binary
|
||||
-- Put "Transfer-Encoding: binary" header
|
||||
do
|
||||
put_transfer_encoding ("binary")
|
||||
put_transfer_encoding (str_binary)
|
||||
end
|
||||
|
||||
put_transfer_encoding_chunked
|
||||
-- Put "Transfer-Encoding: chunked" header
|
||||
do
|
||||
put_transfer_encoding ("chunked")
|
||||
put_transfer_encoding (str_chunked)
|
||||
end
|
||||
|
||||
put_content_disposition (a_type: READABLE_STRING_8; a_params: detachable READABLE_STRING_8)
|
||||
@@ -354,6 +354,35 @@ feature -- Cookie
|
||||
|
||||
feature -- Status report
|
||||
|
||||
header_named_value (a_name: READABLE_STRING_8): detachable STRING_8
|
||||
-- Has header item for `n'?
|
||||
require
|
||||
has_header: has_header_named (a_name)
|
||||
local
|
||||
c: like headers.new_cursor
|
||||
n: INTEGER
|
||||
l_line: READABLE_STRING_8
|
||||
do
|
||||
from
|
||||
n := a_name.count
|
||||
c := headers.new_cursor
|
||||
until
|
||||
c.after or Result /= Void
|
||||
loop
|
||||
l_line := c.item
|
||||
if l_line.starts_with (a_name) then
|
||||
if l_line.valid_index (n + 1) then
|
||||
if l_line [n + 1] = ':' then
|
||||
Result := l_line.substring (n + 2, l_line.count)
|
||||
Result.left_adjust
|
||||
Result.right_adjust
|
||||
end
|
||||
end
|
||||
end
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
has_header_named (a_name: READABLE_STRING_8): BOOLEAN
|
||||
-- Has header item for `n'?
|
||||
local
|
||||
@@ -378,11 +407,26 @@ feature -- Status report
|
||||
end
|
||||
|
||||
has_content_length: BOOLEAN
|
||||
-- Has header "content_length"
|
||||
-- Has header "Content-Length"
|
||||
do
|
||||
Result := has_header_named ({HTTP_HEADER_NAMES}.header_content_length)
|
||||
end
|
||||
|
||||
has_content_type: BOOLEAN
|
||||
-- Has header "Content-Type"
|
||||
do
|
||||
Result := has_header_named ({HTTP_HEADER_NAMES}.header_content_type)
|
||||
end
|
||||
|
||||
has_transfer_encoding_chunked: BOOLEAN
|
||||
-- Has "Transfer-Encoding: chunked" header
|
||||
do
|
||||
if has_header_named ({HTTP_HEADER_NAMES}.header_transfer_encoding) then
|
||||
Result := attached header_named_value ({HTTP_HEADER_NAMES}.header_transfer_encoding) as v and then v.same_string (str_chunked)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation: Header
|
||||
|
||||
force_header_by_name (n: detachable READABLE_STRING_8; h: READABLE_STRING_8)
|
||||
@@ -456,6 +500,9 @@ feature {NONE} -- Implementation
|
||||
|
||||
feature {NONE} -- Constants
|
||||
|
||||
str_binary: STRING = "binary"
|
||||
str_chunked: STRING = "chunked"
|
||||
|
||||
colon_space: STRING = ": "
|
||||
semi_colon_space: STRING = "; "
|
||||
|
||||
|
||||
@@ -11,7 +11,11 @@ inherit
|
||||
WSF_RESPONSE_MESSAGE
|
||||
|
||||
create
|
||||
make
|
||||
make,
|
||||
make_with_body
|
||||
|
||||
convert
|
||||
make_with_body ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8})
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
@@ -21,6 +25,12 @@ feature {NONE} -- Initialization
|
||||
create header.make
|
||||
end
|
||||
|
||||
make_with_body (a_body: READABLE_STRING_8)
|
||||
do
|
||||
make
|
||||
body := a_body
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
status_code: INTEGER
|
||||
@@ -34,10 +44,24 @@ feature -- Header
|
||||
feature -- Output
|
||||
|
||||
send_to (res: WSF_RESPONSE)
|
||||
local
|
||||
b: like body
|
||||
h: like header
|
||||
do
|
||||
h := header
|
||||
b := body
|
||||
res.set_status_code (status_code)
|
||||
res.write_header_text (header.string)
|
||||
if attached body as b then
|
||||
|
||||
if b /= Void then
|
||||
if not h.has_content_length then
|
||||
h.put_content_length (b.count)
|
||||
end
|
||||
if not h.has_content_type then
|
||||
h.put_content_type_text_plain
|
||||
end
|
||||
end
|
||||
res.write_header_text (h.string)
|
||||
if b /= Void then
|
||||
res.write_string (b)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,19 +26,22 @@ convert
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_from_wgi (r: WGI_REQUEST)
|
||||
local
|
||||
tb: like meta_variables_table
|
||||
do
|
||||
wgi_request := r
|
||||
if attached r.meta_variables as l_vars then
|
||||
create meta_variables_table.make (l_vars.count)
|
||||
create tb.make (l_vars.count)
|
||||
across
|
||||
l_vars as c
|
||||
loop
|
||||
meta_variables_table.force (new_string_value (c.key, c.item), c.item)
|
||||
tb.force (new_string_value (c.key, c.item), c.key)
|
||||
end
|
||||
else
|
||||
create meta_variables_table.make (0)
|
||||
create tb.make (0)
|
||||
end
|
||||
meta_variables := meta_variables_table
|
||||
meta_variables_table := tb
|
||||
meta_variables := tb
|
||||
create error_handler.make
|
||||
create uploaded_files.make (0)
|
||||
raw_post_data_recorded := True
|
||||
|
||||
Reference in New Issue
Block a user