This commit is contained in:
jvelilla
2013-05-03 10:57:19 -03:00
13 changed files with 230 additions and 18 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@ tests/temp/
.svn/
*.swp
*~
*#

View File

@@ -113,6 +113,27 @@ feature -- Element change
headers.force (v, k)
end
add_header_line (s: READABLE_STRING_8)
local
i: INTEGER
do
i := s.index_of (':', 1)
if i > 0 then
add_header (s.substring (1, i - 1), s.substring (i + 1, s.count))
end
end
add_header_lines (lst: ITERABLE [READABLE_STRING_8])
local
i: INTEGER
do
across
lst as c
loop
add_header_line (c.item)
end
end
add_query_parameter (k: READABLE_STRING_32; v: READABLE_STRING_32)
do
query_parameters.force (v, k)

View File

@@ -76,6 +76,11 @@ feature -- Basic operation
end
end
custom (a_method: READABLE_STRING_8; a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
-- Response for `a_method' request based on Current, `a_path' and `ctx'.
deferred
end
get (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
-- Response for GET request based on Current, `a_path' and `ctx'.
deferred
@@ -124,7 +129,7 @@ feature -- Status report
-- Is interface usable?
deferred
end
feature -- Settings
timeout: INTEGER

View File

@@ -33,20 +33,22 @@ feature -- Status report
feature -- Basic operation
get (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
custom (a_method: READABLE_STRING_8; 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, ctx)
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, a_method, 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
get (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
do
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "HEAD", Current, ctx)
Result := req.execute
Result := custom ("GET", a_path, ctx)
end
head (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
do
Result := custom ("HEAD", a_path, ctx)
end
post (a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; data: detachable READABLE_STRING_8): HTTP_CLIENT_RESPONSE
@@ -87,8 +89,7 @@ feature -- Basic operation
ctx.set_upload_filename (f.name)
end
end
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "PUT", Current, ctx)
Result := req.execute
Result := custom ("PUT", a_path, ctx)
if f /= Void then
f.delete
end
@@ -100,7 +101,6 @@ feature -- Basic operation
put_file (a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; fn: detachable READABLE_STRING_8): HTTP_CLIENT_RESPONSE
local
req: HTTP_CLIENT_REQUEST
ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT
do
ctx := a_ctx
@@ -110,16 +110,12 @@ feature -- Basic operation
end
ctx.set_upload_filename (fn)
end
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, "PUT", Current, ctx)
Result := req.execute
Result := custom ("PUT", a_path, 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, ctx)
Result := req.execute
Result := custom ("DELETE", a_path, ctx)
end
feature {NONE} -- Implementation

View File

@@ -52,6 +52,8 @@ feature -- Access
http_access_control_request_headers: STRING = "HTTP_ACCESS_CONTROL_REQUEST_HEADERS"
http_if_match: STRING = "HTTP_IF_MATCH"
gateway_interface: STRING = "GATEWAY_INTERFACE"
auth_type: STRING = "AUTH_TYPE"

View File

@@ -604,6 +604,11 @@ feature -- HTTP_*
deferred
end
http_if_match: detachable READABLE_STRING_8
-- Existence check on resource
deferred
end
feature -- Extra CGI environment variables
request_uri: READABLE_STRING_8

View File

@@ -248,6 +248,12 @@ feature -- Access: HTTP_* CGI meta parameters - 1.1
Result := meta_string_variable ({WGI_META_NAMES}.http_access_control_request_headers)
end
http_if_match: detachable READABLE_STRING_8
-- Existence check on resource
do
Result := meta_string_variable ({WGI_META_NAMES}.http_if_match)
end
feature -- Access: Extension to CGI meta parameters - 1.1
request_uri: READABLE_STRING_8

View File

@@ -256,6 +256,7 @@ feature {NONE} -- Implementation
h.put_current_date
h.put_location (proxy_server (req).string)
h.put_content_length (0)
res.put_header_lines (h)
res.set_status_code ({HTTP_STATUS_CODE}.use_proxy)
ensure
response_status_is_set: res.status_is_set

View File

@@ -58,8 +58,20 @@ feature {WSF_RESPONSE} -- Output
if req.is_request_method ({HTTP_REQUEST_METHODS}.method_trace) then
msg := trace_message (req)
elseif attached method_not_allowed_message (req) as not_allowed then
--| We give this precedence over 412 Precondition Failed or 404 Not Found,
--| as we assume the existence of a handler for at least one method
--| indicates existence of the resource. This is obviously not the
--| case if the only method allowed is POST, but the handler ought
--| to handle the 404 Not Found and 412 Precondition Failed cases in that case.
--| Ditto for template URI handlers where not all template variable
--| values map to existing resources.
msg := not_allowed
elseif attached req.http_if_match as l_match and then l_match.same_string ("*") then
msg := precondition_failed_message (req)
else
--| Other response codes are possible, such as 301 Moved permananently,
--| 302 Found and 410 Gone. But these require handlers to implement,
--| so no other code can be given at this point.
msg := not_found_message (req)
end
res.send (msg)
@@ -67,7 +79,17 @@ feature {WSF_RESPONSE} -- Output
feature {NONE} -- Implementation
precondition_failed_message (req: WSF_REQUEST): WSF_PRECONDITION_FAILED_MESSAGE
-- Automatically generated response for 412 Precondition Failed response
require
req_attached: req /= Void
do
create Result.make (req)
end
method_not_allowed_message (req: WSF_REQUEST): detachable WSF_METHOD_NOT_ALLOWED_RESPONSE
require
req_attached: req /= Void
local
vis: WSF_ROUTER_AGENT_ITERATOR
do

View File

@@ -45,6 +45,7 @@ feature {NONE} -- Initialization
initialize
local
h: like header
d: HTTP_DATE
do
create h.make
header := h
@@ -52,6 +53,9 @@ feature {NONE} -- Initialization
h.put_transfer_encoding_binary
h.put_content_length (filesize (file_name))
h.put_content_disposition ("attachment", "filename=%""+ base_name +"%"")
if attached filedate (file_name) as dt then
h.put_last_modified (dt)
end
end
feature -- Element change
@@ -138,6 +142,19 @@ feature {NONE} -- Implementation: file system helper
end
end
filedate (fn: STRING): detachable DATE_TIME
-- Size of the file `fn'.
local
f: RAW_FILE
d: HTTP_DATE
do
create f.make (fn)
if f.exists then
create d.make_from_timestamp (f.date)
Result := d.date_time
end
end
file_extension (fn: STRING): STRING
-- Extension of file `fn'.
local

View File

@@ -0,0 +1,130 @@
note
description: "[
This class is used to report a 412 Precondition Failed page
]"
date: "$Date$"
revision: "$Revision$"
class WSF_PRECONDITION_FAILED_MESSAGE
inherit
WSF_RESPONSE_MESSAGE
SHARED_HTML_ENCODER
create
make
feature {NONE} -- Initialization
make (req: WSF_REQUEST)
-- Initialize setting `request' from `req'.
do
request := req
create header.make
ensure
req_aliased: request = req
end
feature -- Header
header: HTTP_HEADER
-- Response' header
request: WSF_REQUEST
-- Associated request.
body: detachable READABLE_STRING_8
-- Optional body
-- Displayed as extra content
feature -- Element change
set_body (b: like body)
-- Set `body' to `b'
do
body := b
end
feature {WSF_RESPONSE} -- Output
send_to (res: WSF_RESPONSE)
local
s: STRING
l_text: detachable READABLE_STRING_GENERAL
l_loc: detachable READABLE_STRING_8
h: like header
do
h := header
res.set_status_code ({HTTP_STATUS_CODE}.precondition_failed)
if request.is_content_type_accepted ({HTTP_MIME_TYPES}.text_html) then
s := "<html lang=%"en%"><head>"
s.append ("<title>")
s.append (html_encoder.encoded_string (request.request_uri))
s.append ("Error 412 (Precondition Failed)")
s.append ("</title>%N")
s.append ("[
<style type="text/css">
div#header {color: #fff; background-color: #000; padding: 20px; width: 100%; text-align: center; font-size: 2em; font-weight: bold;}
div#message { margin: 40px; width: 100%; text-align: center; font-size: 1.5em; }
div#footer {color: #999; background-color: #eee; padding: 10px; width: 100%; text-align: center; }
div#logo { float: right; margin: 20px; width: 60px height: auto; font-size: 0.8em; text-align: center; }
div#logo div.outter { padding: 6px; width: 60px; border: solid 3px #500; background-color: #b00;}
div#logo div.outter div.inner1 { display: block; margin: 10px 15px; width: 30px; height: 50px; color: #fff; background-color: #fff; border: solid 2px #900; }
div#logo div.outter div.inner2 { margin: 10px 15px; width: 30px; height: 15px; color: #fff; background-color: #fff; border: solid 2px #900; }
</style>
</head>
<body>
<div id="header">Error 412 (Precondition Failed)</div>
]")
s.append ("<div id=%"logo%">")
s.append ("<div class=%"outter%"> ")
s.append ("<div class=%"inner1%"></div>")
s.append ("<div class=%"inner2%"></div>")
s.append ("</div>")
s.append ("Error 412 (Precondition Failed)</div>")
s.append ("<div id=%"message%">Error 412 (Precondition Failed): <code>" + html_encoder.encoded_string (request.request_uri) + "</code></div>")
if attached body as b then
s.append ("<div>")
s.append (b)
s.append ("</div>%N")
end
s.append ("<div id=%"footer%"></div>")
s.append ("</body>%N")
s.append ("</html>%N")
h.put_content_type_text_html
else
s := "Error 412 (Precondition Failed): "
s.append (request.request_uri)
s.append_character ('%N')
if attached body as b then
s.append ("%N")
s.append (b)
s.append ("%N")
end
h.put_content_type_text_plain
end
h.put_content_length (s.count)
res.put_header_text (h.string)
res.put_string (s)
res.flush
end
note
copyright: "2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, 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

View File

@@ -1042,6 +1042,12 @@ feature -- HTTP_*
Result := wgi_request.http_access_control_request_headers
end
http_if_match: detachable READABLE_STRING_8
-- Existence check on resource
do
Result := wgi_request.http_if_match
end
feature -- Extra CGI environment variables
request_uri: READABLE_STRING_8

View File

@@ -207,7 +207,7 @@ feature -- Header output operation
if header_committed then
report_content_already_sent_and_header_ignored
else
header.append_raw_header_data (a_text)
header.put_raw_header_data (a_text)
end
ensure
message_writable: message_writable