Now WGI_RESPONSE.set_status_code (..) has a new argument to pass optional custom reason phrase.

This is a minor breaking change (but prior to the first release, so acceptable)
   And then it is now possible to precise a custom reason phrase (useful for 4xx and 5xx response)

At the WSF_RESPONSE level, the status code is now sent only when the header are sent.
thus, it is possible to change the status code as long as no header is sent.
(in the future, we should also try to delay the sending of headers)

Removed WGI_RESPONSE.put_header_lines (..) which was not used, and WGI is not meant to provide such user friendly features
Now this is available directly on WSF_RESPONSE
This commit is contained in:
Jocelyn Fiat
2012-04-12 11:19:41 +02:00
parent 082def2b70
commit b541efcc8f
14 changed files with 149 additions and 70 deletions

View File

@@ -92,6 +92,11 @@ feature -- Authentication
Result := session.credentials Result := session.credentials
end end
proxy: detachable TUPLE [host: READABLE_STRING_8; port: INTEGER]
do
Result := session.proxy
end
feature -- Settings feature -- Settings
timeout: INTEGER timeout: INTEGER
@@ -131,6 +136,12 @@ feature -- Settings
Result := session.default_response_charset Result := session.default_response_charset
end end
is_insecure: BOOLEAN
-- Allow connections to SSL sites without certs
do
Result := session.is_insecure
end
feature {NONE} -- Utilities 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_to_url (a_url: STRING; a_parameters: detachable ARRAY [detachable TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])

View File

@@ -105,6 +105,12 @@ feature -- Settings
default_response_charset: detachable READABLE_STRING_8 default_response_charset: detachable READABLE_STRING_8
-- Default encoding of responses. Used if no charset is provided by the host. -- Default encoding of responses. Used if no charset is provided by the host.
is_insecure: BOOLEAN
-- Allow connections to SSL sites without certs
proxy: detachable TUPLE [host: READABLE_STRING_8; port: INTEGER]
-- Proxy information [`host' and `port']
feature -- Access feature -- Access
base_url: READABLE_STRING_8 base_url: READABLE_STRING_8
@@ -132,9 +138,9 @@ feature -- Change
base_url := u base_url := u
end end
set_timeout (n: like timeout) set_timeout (n_seconds: like timeout)
do do
timeout := n timeout := n_seconds
end end
set_connect_timeout (n: like connect_timeout) set_connect_timeout (n: like connect_timeout)
@@ -147,6 +153,11 @@ feature -- Change
add_header ("User-Agent", v) add_header ("User-Agent", v)
end end
set_is_insecure (b: BOOLEAN)
do
is_insecure := b
end
add_header (k: READABLE_STRING_8; v: READABLE_STRING_8) add_header (k: READABLE_STRING_8; v: READABLE_STRING_8)
do do
headers.force (v, k) headers.force (v, k)
@@ -203,6 +214,15 @@ feature -- Change
max_redirects := n max_redirects := n
end end
set_proxy (a_host: detachable READABLE_STRING_8; a_port: INTEGER)
do
if a_host = Void then
proxy := Void
else
proxy := [a_host, a_port]
end
end
note note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

@@ -54,6 +54,7 @@ feature -- Execution
curl_easy: CURL_EASY_EXTERNALS curl_easy: CURL_EASY_EXTERNALS
curl_handle: POINTER curl_handle: POINTER
ctx: like context ctx: like context
l_proxy: like proxy
do do
ctx := context ctx := context
curl := session.curl curl := session.curl
@@ -83,7 +84,14 @@ feature -- Execution
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_header, 1) curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_header, 1)
--| PROXY ... --| PROXY ...
if ctx /= Void and then attached ctx.proxy as l_proxy then
if ctx /= Void then
l_proxy := ctx.proxy
end
if l_proxy = Void then
l_proxy := proxy
end
if l_proxy /= Void then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_proxyport, l_proxy.port) curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_proxyport, l_proxy.port)
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_proxy, l_proxy.host) curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_proxy, l_proxy.host)
end end
@@ -104,6 +112,12 @@ feature -- Execution
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_followlocation, 0) curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_followlocation, 0)
end end
--| SSL
if is_insecure then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_ssl_verifyhost, 0)
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_ssl_verifypeer, 0)
end
if request_method.is_case_insensitive_equal ("GET") then if request_method.is_case_insensitive_equal ("GET") then
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpget, 1) curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpget, 1)
elseif request_method.is_case_insensitive_equal ("POST") then elseif request_method.is_case_insensitive_equal ("POST") then

View File

@@ -231,6 +231,9 @@ feature -- Request or Response header name
-- Implementation-specific headers that may have various effects anywhere along the request-response chain. -- Implementation-specific headers that may have various effects anywhere along the request-response chain.
--| Example: Pragma: no-cache --| Example: Pragma: no-cache
header_status: STRING = "Status"
-- CGI program can use this to return the HTTP status code to the client.
header_via: STRING = "Via" header_via: STRING = "Via"
-- Request: Informs the server of proxies through which the request was sent. -- Request: Informs the server of proxies through which the request was sent.
-- Response: Informs the client of proxies through which the response was sent. -- Response: Informs the client of proxies through which the response was sent.
@@ -245,7 +248,7 @@ feature -- MIME related
header_content_transfer_encoding: STRING = "Content-Transfer-Encoding" header_content_transfer_encoding: STRING = "Content-Transfer-Encoding"
note note
copyright: "2011-2011, Eiffel Software and others" copyright: "2011-2012, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -48,7 +48,7 @@ feature -- Execution
if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then
if res /= Void then if res /= Void then
if not res.status_is_set then if not res.status_is_set then
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error) res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void)
end end
if res.message_writable then if res.message_writable then
res.put_string ("<pre>" + l_trace + "</pre>") res.put_string ("<pre>" + l_trace + "</pre>")

View File

@@ -36,21 +36,24 @@ feature {NONE} -- Initialization
feature -- Status writing feature -- Status writing
put_status_line (a_code: INTEGER) put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
-- Put status code line for `a_code' -- <Precursor>
--| Note this is a default implementation, and could be redefined
--| for instance in relation to NPH CGI script
local local
s: STRING s: STRING
m: detachable READABLE_STRING_8
do do
if a_code /= 200 then if a_code /= 200 then
create s.make (16) create s.make (16)
s.append ("Status:") s.append ("Status:")
s.append_character (' ') s.append_character (' ')
s.append_integer (a_code) s.append_integer (a_code)
if attached http_status_code_message (a_code) as l_status_message then m := a_reason_phrase
if m = Void then
m := http_status_code_message (a_code)
end
if m /= Void then
s.append_character (' ') s.append_character (' ')
s.append_string (l_status_message) s.append_string (m)
end end
put_header_line (s) put_header_line (s)
end end

View File

@@ -69,7 +69,7 @@ feature -- Execution
if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then
if res /= Void then if res /= Void then
if not res.status_is_set then if not res.status_is_set then
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error) res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void)
end end
if res.message_writable then if res.message_writable then
res.put_string ("<pre>" + l_trace + "</pre>") res.put_string ("<pre>" + l_trace + "</pre>")

View File

@@ -40,23 +40,24 @@ feature -- Status report
feature -- Status writing feature -- Status writing
put_status_line (a_code: INTEGER) put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
-- Put status code line for `a_code' -- <Precursor>
--| Note this is a default implementation, and could be redefined
--| for instance in relation to NPH CGI script
local local
s: STRING s: STRING
m: detachable READABLE_STRING_8
do do
--| Do not send any Status line back to the FastCGI client
--| According to http://www.fastcgi.com/docs/faq.html#httpstatus
if a_code /= 200 then if a_code /= 200 then
create s.make (16) create s.make (16)
s.append ("Status:") s.append ("Status:")
s.append_character (' ') s.append_character (' ')
s.append_integer (a_code) s.append_integer (a_code)
if attached http_status_code_message (a_code) as l_status_message then m := a_reason_phrase
if m = Void then
m := http_status_code_message (a_code)
end
if m /= Void then
s.append_character (' ') s.append_character (' ')
s.append_string (l_status_message) s.append_string (m)
end end
put_header_line (s) put_header_line (s)
end end

View File

@@ -37,20 +37,23 @@ feature {WGI_NINO_CONNECTOR, WGI_SERVICE} -- Nino
feature -- Status writing feature -- Status writing
put_status_line (a_code: INTEGER) put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
-- Put status code line for `a_code' -- <Precursor>
--| Note this is a default implementation, and could be redefined
--| for instance in relation to NPH CGI script
local local
s: STRING s: STRING
m: detachable READABLE_STRING_8
do do
create s.make (16) create s.make (16)
s.append ({HTTP_CONSTANTS}.http_version_1_1) s.append ({HTTP_CONSTANTS}.http_version_1_1)
s.append_character (' ') s.append_character (' ')
s.append_integer (a_code) s.append_integer (a_code)
if attached http_status_code_message (a_code) as l_status_message then m := a_reason_phrase
if m = Void then
m := http_status_code_message (a_code)
end
if m /= Void then
s.append_character (' ') s.append_character (' ')
s.append_string (l_status_message) s.append_string (m)
end end
put_header_line (s) put_header_line (s)
end end

View File

@@ -49,15 +49,17 @@ feature -- Status setting
deferred deferred
end end
set_status_code (a_code: INTEGER) set_status_code (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
-- Set response status code -- Set response status code with custom `a_reason_phrase' if precised
-- Should be done before sending any data back to the client -- Should be done before sending any data back to the client
require require
a_code_positive: a_code > 0
status_not_set: not status_committed status_not_set: not status_committed
header_not_committed: not header_committed header_not_committed: not header_committed
deferred deferred
ensure ensure
status_code_set: status_code = a_code status_code_set: status_code = a_code
status_reason_phrase_set: status_reason_phrase = a_reason_phrase
status_set: status_is_set status_set: status_is_set
end end
@@ -66,6 +68,13 @@ feature -- Status setting
deferred deferred
end end
status_reason_phrase: detachable READABLE_STRING_8
-- Custom status reason phrase for the Response (optional)
deferred
ensure
Result /= Void implies status_is_set
end
feature -- Header output operation feature -- Header output operation
put_header_text (a_text: READABLE_STRING_8) put_header_text (a_text: READABLE_STRING_8)
@@ -79,17 +88,7 @@ feature -- Header output operation
deferred deferred
ensure ensure
status_set: status_is_set status_set: status_is_set
header_committed: header_committed status_committed: status_committed
message_writable: message_writable
end
put_header_lines (a_lines: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
require
status_set: status_is_set
header_not_committed: not header_committed
deferred
ensure
status_set: status_is_set
header_committed: header_committed header_committed: header_committed
message_writable: message_writable message_writable: message_writable
end end

View File

@@ -62,10 +62,13 @@ feature -- Specific output
feature -- Status writing feature -- Status writing
put_status_line (a_code: INTEGER) put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
-- Put status code line for `a_code' -- Put status code line for `a_code'
-- with custom `a_reason_phrase' if precised
--| Note this is a default implementation, and could be redefined --| Note this is a default implementation, and could be redefined
--| for instance in relation to NPH CGI script --| for instance in relation to NPH CGI script
require
a_code_positive: a_code > 0
deferred deferred
end end

View File

@@ -54,21 +54,25 @@ feature -- Status setting
status_is_set: BOOLEAN status_is_set: BOOLEAN
-- Is status set? -- Is status set?
do do
Result := status_code /= 0 Result := status_code > 0
end end
set_status_code (a_code: INTEGER) set_status_code (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
-- Set response status code -- Set response status code
-- Should be done before sending any data back to the client -- Should be done before sending any data back to the client
do do
status_code := a_code status_code := a_code
output.put_status_line (a_code) status_reason_phrase := a_reason_phrase
output.put_status_line (a_code, a_reason_phrase)
status_committed := True status_committed := True
end end
status_code: INTEGER status_code: INTEGER
-- Response status -- Response status
status_reason_phrase: detachable READABLE_STRING_8
-- Custom status reason phrase for the Response (optional)
feature -- Header output operation feature -- Header output operation
put_header_text (a_text: READABLE_STRING_8) put_header_text (a_text: READABLE_STRING_8)
@@ -78,24 +82,6 @@ feature -- Header output operation
header_committed := True header_committed := True
end end
put_header_lines (a_lines: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
local
h: STRING_8
do
create h.make (256)
across
a_lines as c
loop
h.append (c.item.name)
h.append_character (':')
h.append_character (' ')
h.append (c.item.value)
h.append_character ('%R')
h.append_character ('%N')
end
put_header_text (h)
end
feature -- Output operation feature -- Output operation
put_character (c: CHARACTER_8) put_character (c: CHARACTER_8)

View File

@@ -56,35 +56,57 @@ feature -- Status setting
status_is_set: BOOLEAN status_is_set: BOOLEAN
-- Is status set? -- Is status set?
do do
Result := wgi_response.status_is_set Result := status_code > 0
end end
set_status_code (a_code: INTEGER) set_status_code (a_code: INTEGER)
-- Set response status code -- Set response status code
-- Should be done before sending any data back to the client -- Should be done before sending any data back to the client
--| note: the status is really sent when the header are set
require require
a_code_valid: a_code > 0
status_not_set: not status_committed status_not_set: not status_committed
header_not_committed: not header_committed header_not_committed: not header_committed
do do
wgi_response.set_status_code (a_code) status_code := a_code
status_reason_phrase := Void
ensure ensure
status_code_set: status_code = a_code status_code_set: status_code = a_code
status_set: status_is_set status_set: status_is_set
end end
set_status_code_with_reason_phrase (a_code: INTEGER; a_reason_phrase: READABLE_STRING_8)
-- Set response status code
-- Should be done before sending any data back to the client
--| note: the status is really sent when the header are set
require
a_code_valid: a_code > 0
status_not_set: not status_committed
header_not_committed: not header_committed
do
set_status_code (a_code)
status_reason_phrase := a_reason_phrase
ensure
status_code_set: status_code = a_code
status_reason_phrase_set: status_reason_phrase = a_reason_phrase
status_set: status_is_set
end
status_code: INTEGER status_code: INTEGER
-- Response status -- Response status
do
Result := wgi_response.status_code status_reason_phrase: detachable READABLE_STRING_8
end -- Custom status reason phrase (optional)
feature -- Header output operation feature -- Header output operation
put_header_text (a_headers: READABLE_STRING_8) put_header_text (a_headers: READABLE_STRING_8)
-- Sent `a_headers' and just before send the status code
require require
status_set: status_is_set status_set: status_is_set
header_not_committed: not header_committed header_not_committed: not header_committed
do do
wgi_response.set_status_code (status_code, status_reason_phrase)
wgi_response.put_header_text (a_headers) wgi_response.put_header_text (a_headers)
ensure ensure
status_set: status_is_set status_set: status_is_set
@@ -93,7 +115,7 @@ feature -- Header output operation
message_writable: message_writable message_writable: message_writable
end end
put_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]]) put_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
-- Send headers with status `a_status', and headers from `a_headers' -- Send headers with status `a_status', and headers from `a_headers'
require require
status_not_committed: not status_committed status_not_committed: not status_committed
@@ -107,14 +129,28 @@ feature -- Header output operation
put_header_text (h.string) put_header_text (h.string)
end end
ensure ensure
header_committed: header_committed
status_set: status_is_set status_set: status_is_set
header_committed: header_committed
message_writable: message_writable message_writable: message_writable
end end
put_header_lines (a_lines: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]) put_header_lines (a_lines: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
-- Send headers from `a_lines'
local
h: STRING_8
do do
wgi_response.put_header_lines (a_lines) create h.make (256)
across
a_lines as c
loop
h.append (c.item.name)
h.append_character (':')
h.append_character (' ')
h.append (c.item.value)
h.append_character ('%R')
h.append_character ('%N')
end
put_header_text (h)
end end
feature -- Output report feature -- Output report