Addition to "http" library, separated constants into

- HTTP_MIME_TYPES
 - HTTP_HEADER_NAMES
 - HTTP_REQUEST_METHODS
 - HTTP_STATUS_CODE   (already exists)

Do not set the "Status" header when using WGI_RESPONSE_BUFFER.write_header (...)
Cosmetic
This commit is contained in:
Jocelyn Fiat
2011-10-12 11:51:49 +02:00
parent 0144e97d69
commit 035a133b5b
13 changed files with 695 additions and 219 deletions

View File

@@ -30,7 +30,6 @@ feature {NONE} -- Initialization
create_router create_router
do do
-- (create {EXCEPTIONS}).raise ("ouch")
check False end check False end
create router.make (5) create router.make (5)
end end
@@ -38,33 +37,28 @@ feature {NONE} -- Initialization
setup_router setup_router
local local
ra: REQUEST_AGENT_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT] ra: REQUEST_AGENT_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
rag: REQUEST_URI_TEMPLATE_ROUTING_HANDLER hello: REQUEST_URI_TEMPLATE_ROUTING_HANDLER
do do
router.map_agent ("/home", agent execute_home) router.map_agent ("/home", agent execute_home)
create rag.make (3) --| Map all "/hello*" using a ROUTING_HANDLER
create hello.make (3)
router.map ("/hello", hello)
create ra.make (agent handle_hello) create ra.make (agent handle_hello)
rag.map ("/hello/{name}.{format}", ra) hello.map ("/hello/{name}.{format}", ra)
rag.map ("/hello.{format}/{name}", ra) hello.map ("/hello.{format}/{name}", ra)
rag.map ("/hello/{name}", ra) hello.map ("/hello/{name}", ra)
-- router.map ("/hello/{name}.{format}", ra)
-- router.map ("/hello.{format}/{name}", ra)
-- router.map ("/hello/{name}", ra)
create ra.make (agent handle_anonymous_hello) create ra.make (agent handle_anonymous_hello)
rag.map ("/hello", ra) hello.map ("/hello", ra)
rag.map ("/hello.{format}", ra) hello.map ("/hello.{format}", ra)
-- router.map ("/hello", ra)
-- router.map ("/hello.{format}", ra)
router.map ("/hello", rag)
--| Various various route, directly on the "router"
router.map_agent_with_request_methods ("/method/any", agent handle_method_any, Void) router.map_agent_with_request_methods ("/method/any", agent handle_method_any, Void)
router.map_agent_with_request_methods ("/method/guess", agent handle_method_get_or_post, <<"GET", "POST">>) router.map_agent_with_request_methods ("/method/guess", agent handle_method_get_or_post, <<"GET", "POST">>)
router.map_agent_with_request_methods ("/method/custom", agent handle_method_get, <<"GET">>) router.map_agent_with_request_methods ("/method/custom", agent handle_method_get, <<"GET">>)
router.map_agent_with_request_methods ("/method/custom", agent handle_method_post, <<"POST">>) router.map_agent_with_request_methods ("/method/custom", agent handle_method_post, <<"POST">>)
end end
feature -- Execution feature -- Execution
@@ -81,8 +75,9 @@ feature -- Execution
n := 3 n := 3
create h.make create h.make
h.put_refresh (l_url, 5) h.put_refresh (l_url, 5)
res.set_status_code (200) res.set_status_code ({HTTP_STATUS_CODE}.moved_permanently)
res.write_headers_string (h.string) res.write_headers_string (h.string)
from from
create e create e
until until
@@ -115,49 +110,53 @@ feature -- Execution
end end
execute_home (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) execute_home (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
local
l_body: STRING_8
do do
res.write_header (200, <<["Content-Type", "text/html"]>>) create l_body.make (255)
res.write_string ("<html><body>Hello World ?!%N") l_body.append ("<html><body>Hello World ?!%N")
res.write_string ("<h3>Please try the following links</h3><ul>%N") l_body.append ("<h3>Please try the following links</h3><ul>%N")
res.write_string ("<li><a href=%""+ req.script_url ("/") + "%">default</a></li>%N") l_body.append ("<li><a href=%""+ req.script_url ("/") + "%">default</a></li>%N")
res.write_string ("<li><a href=%""+ req.script_url ("/hello") + "%">/hello</a></li>%N") l_body.append ("<li><a href=%""+ req.script_url ("/hello") + "%">/hello</a></li>%N")
res.write_string ("<li><a href=%""+ req.script_url ("/hello.html/Joce") + "%">/hello.html/Joce</a></li>%N") l_body.append ("<li><a href=%""+ req.script_url ("/hello.html/Joce") + "%">/hello.html/Joce</a></li>%N")
res.write_string ("<li><a href=%""+ req.script_url ("/hello.json/Joce") + "%">/hello.json/Joce</a></li>%N") l_body.append ("<li><a href=%""+ req.script_url ("/hello.json/Joce") + "%">/hello.json/Joce</a></li>%N")
res.write_string ("<li><a href=%""+ req.script_url ("/hello/Joce.html") + "%">/hello/Joce.html</a></li>%N") l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce.html") + "%">/hello/Joce.html</a></li>%N")
res.write_string ("<li><a href=%""+ req.script_url ("/hello/Joce.xml") + "%">/hello/Joce.xml</a></li>%N") l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce.xml") + "%">/hello/Joce.xml</a></li>%N")
res.write_string ("<li><a href=%""+ req.script_url ("/hello/Joce") + "%">/hello/Joce</a></li>%N") l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce") + "%">/hello/Joce</a></li>%N")
res.write_string ("</ul>%N") l_body.append ("</ul>%N")
if attached req.item ("REQUEST_COUNT") as rqc then if attached req.item ("REQUEST_COUNT") as rqc then
res.write_string ("request #"+ rqc.as_string + "%N") l_body.append ("request #"+ rqc.as_string + "%N")
end end
res.write_string ("</body></html>%N") l_body.append ("</body></html>%N")
res.write_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_body.count.out]>>)
res.write_string (l_body)
end end
execute_hello (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_name: detachable READABLE_STRING_32; ctx: REQUEST_HANDLER_CONTEXT) execute_hello (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_name: detachable READABLE_STRING_32; ctx: REQUEST_HANDLER_CONTEXT)
local local
l_response_content_type: detachable STRING l_response_content_type: detachable STRING
msg: STRING
h: EWF_HEADER h: EWF_HEADER
content_type_supported: ARRAY [STRING] content_type_supported: ARRAY [STRING]
l_body: STRING_8
do do
if a_name /= Void then if a_name /= Void then
msg := "Hello %"" + a_name + "%" !%N" l_body := "Hello %"" + a_name + "%" !%N"
else else
msg := "Hello anonymous visitor !%N" l_body := "Hello anonymous visitor !%N"
end end
content_type_supported := <<{HTTP_CONSTANTS}.json_app, {HTTP_CONSTANTS}.html_text, {HTTP_CONSTANTS}.xml_text, {HTTP_CONSTANTS}.plain_text>> content_type_supported := <<{HTTP_MIME_TYPES}.application_json, {HTTP_MIME_TYPES}.text_html, {HTTP_MIME_TYPES}.text_xml, {HTTP_MIME_TYPES}.text_plain>>
inspect ctx.request_format_id ("format", content_type_supported) inspect ctx.request_format_id ("format", content_type_supported)
when {HTTP_FORMAT_CONSTANTS}.json then when {HTTP_FORMAT_CONSTANTS}.json then
l_response_content_type := {HTTP_CONSTANTS}.json_app l_response_content_type := {HTTP_MIME_TYPES}.application_json
msg := "{%N%"application%": %"/hello%",%N %"message%": %"" + msg + "%" %N}" l_body := "{%N%"application%": %"/hello%",%N %"message%": %"" + l_body + "%" %N}"
when {HTTP_FORMAT_CONSTANTS}.html then when {HTTP_FORMAT_CONSTANTS}.html then
l_response_content_type := {HTTP_CONSTANTS}.html_text l_response_content_type := {HTTP_MIME_TYPES}.text_html
when {HTTP_FORMAT_CONSTANTS}.xml then when {HTTP_FORMAT_CONSTANTS}.xml then
l_response_content_type := {HTTP_CONSTANTS}.xml_text l_response_content_type := {HTTP_MIME_TYPES}.text_xml
msg := "<response><application>/hello</application><message>" + msg + "</message></response>%N" l_body := "<response><application>/hello</application><message>" + l_body + "</message></response>%N"
when {HTTP_FORMAT_CONSTANTS}.text then when {HTTP_FORMAT_CONSTANTS}.text then
l_response_content_type := {HTTP_CONSTANTS}.plain_text l_response_content_type := {HTTP_MIME_TYPES}.text_plain
else else
execute_content_type_not_allowed (req, res, content_type_supported, execute_content_type_not_allowed (req, res, content_type_supported,
<<{HTTP_FORMAT_CONSTANTS}.json_name, {HTTP_FORMAT_CONSTANTS}.html_name, {HTTP_FORMAT_CONSTANTS}.xml_name, {HTTP_FORMAT_CONSTANTS}.text_name>> <<{HTTP_FORMAT_CONSTANTS}.json_name, {HTTP_FORMAT_CONSTANTS}.html_name, {HTTP_FORMAT_CONSTANTS}.xml_name, {HTTP_FORMAT_CONSTANTS}.text_name>>
@@ -165,16 +164,11 @@ feature -- Execution
end end
if l_response_content_type /= Void then if l_response_content_type /= Void then
create h.make create h.make
h.put_status (200)
h.put_content_type (l_response_content_type) h.put_content_type (l_response_content_type)
h.put_content_length (msg.count) h.put_content_length (l_body.count)
res.set_status_code (200) res.set_status_code ({HTTP_STATUS_CODE}.ok)
res.write_headers_string (h.string) res.write_headers_string (h.string)
-- res.write_header (200, << res.write_string (l_body)
-- ["Content-Type", l_response_content_type],
-- ["Content-Length", msg.count.out
-- >>)
res.write_string (msg)
end end
end end

View File

@@ -1,5 +1,7 @@
note note
description: "Summary description for {HTTP_CONSTANTS}." description: "[
Constants class providing most common constants used in HTTP communication
]"
legal: "See notice at end of class." legal: "See notice at end of class."
status: "See notice at end of class." status: "See notice at end of class."
date: "$Date$" date: "$Date$"
@@ -8,83 +10,29 @@ note
class class
HTTP_CONSTANTS HTTP_CONSTANTS
inherit
HTTP_MIME_TYPES
HTTP_HEADER_NAMES
HTTP_STATUS_CODE
HTTP_REQUEST_METHODS
feature -- Ports feature -- Ports
default_http_port: INTEGER = 80 default_http_port: INTEGER = 80
default_https_port: INTEGER = 443 default_https_port: INTEGER = 443
feature -- Method feature -- Server, header
method_get: STRING = "GET"
method_post: STRING = "POST"
method_put: STRING = "PUT"
method_delete: STRING = "DELETE"
method_head: STRING = "HEAD"
method_download: STRING = "DOWNLOAD"
feature -- Content type
octet_stream: STRING = "application/octet-stream"
-- Octet stream content-type header
multipart_form: STRING = "multipart/form-data"
-- Starting chars of multipart form data content-type header
form_encoded: STRING = "application/x-www-form-urlencoded"
-- Starting chars of form url-encoded data content-type header
xml_text: STRING = "text/xml"
-- XML text content-type header
html_text: STRING = "text/html"
-- HTML text content-type header
json_text: STRING = "text/json"
-- JSON text content-type header
json_app: STRING = "application/json"
-- JSON application content-type header
js_text: STRING = "text/javascript"
-- Javascript text content-type header
js_app: STRING = "application/javascript"
-- JavaScript application content-type header
plain_text: STRING = "text/plain"
-- Plain text content-type header
feature -- Server
http_version_1_0: STRING = "HTTP/1.0" http_version_1_0: STRING = "HTTP/1.0"
http_version_1_1: STRING = "HTTP/1.1" http_version_1_1: STRING = "HTTP/1.1"
http_host_header: STRING = "Host"
http_authorization_header: STRING = "Authorization: "
http_end_of_header_line: STRING = "%R%N"
http_end_of_command: STRING = "%R%N%R%N"
http_content_length: STRING = "Content-Length: "
http_content_type: STRING = "Content-Type: "
http_content_location: STRING = "Content-Location: "
http_content_disposition: STRING = "Content-Disposition: "
http_path_translated: STRING = "Path-Translated: "
http_agent: STRING = "User-agent: "
http_from: STRING = "From: "
feature -- Server: header
header_host: STRING = "Host"
header_authorization: STRING = "Authorization"
header_content_length: STRING = "Content-Length"
header_content_type: STRING = "Content-Type"
header_content_location: STRING = "Content-Location"
header_content_disposition: STRING = "Content-Disposition"
header_cache_control: STRING = "Cache-Control"
header_path_translated: STRING = "Path-Translated"
header_agent: STRING = "User-Agent"
header_referer: STRING = "Referer" -- Officially mispelled in std
header_location: STRING = "Location"
header_from: STRING = "From"
header_status: STRING = "Status"
header_multipart_tag_value_separator: CHARACTER = ';'
feature -- Misc feature -- Misc
http_status_ok: STRING = "200 OK"
default_bufsize: INTEGER = 16384 --| 16K default_bufsize: INTEGER = 16384 --| 16K
note note
copyright: "2011-2011, Eiffel Software and others" copyright: "2011-2011, 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

@@ -0,0 +1,257 @@
note
description: "[
See http://en.wikipedia.org/wiki/List_of_HTTP_headers
]"
date: "$Date$"
revision: "$Revision$"
class
HTTP_HEADER_NAMES
feature -- Request header name
header_accept: STRING = "Accept"
-- Content-Types that are acceptable
--| Example: Accept: text/plain
header_accept_charset: STRING = "Accept-Charset"
-- Character sets that are acceptable
--| Example: Accept-Charset: utf-8
header_accept_encoding: STRING = "Accept-Encoding"
-- Acceptable encodings. See HTTP compression.
--| Example: Accept-Encoding: <compress | gzip | deflate | sdch | identity>
header_accept_language: STRING = "Accept-Language"
-- Acceptable languages for response
--| Example: Accept-Language: en-US
header_authorization: STRING = "Authorization"
-- Authentication credentials for HTTP authentication
--| Example: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
header_cookie: STRING = "Cookie"
-- an HTTP cookie previously sent by the server with Set-Cookie (below)
--| Example: Cookie: $Version=1; Skin=new;
header_expect: STRING = "Expect"
-- Indicates that particular server behaviors are required by the client
--| Example: Expect: 100-continue
header_from: STRING = "From"
-- The email address of the user making the request
--| Example: From: user@example.com
header_host: STRING = "Host"
-- The domain name of the server (for virtual hosting), mandatory since HTTP/1.1
--| Example: Host: en.wikipedia.org
header_if_match: STRING = "If-Match"
-- Only perform the action if the client supplied entity matches the same entity on the server. This is mainly for methods like PUT to only update a resource if it has not been modified since the user last updated it.
--| Example: If-Match: "737060cd8c284d8af7ad3082f209582d"
header_if_modified_since: STRING = "If-Modified-Since"
-- Allows a 304 Not Modified to be returned if content is unchanged
--| Example: If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
header_if_none_match: STRING = "If-None-Match"
-- Allows a 304 Not Modified to be returned if content is unchanged, see HTTP ETag
--| Example: If-None-Match: "737060cd8c284d8af7ad3082f209582d"
header_if_range: STRING = "If-Range"
-- If the entity is unchanged, send me the part(s) that I am missing; otherwise, send me the entire new entity
--| Example: If-Range: "737060cd8c284d8af7ad3082f209582d"
header_if_unmodified_since: STRING = "If-Unmodified-Since"
-- Only send the response if the entity has not been modified since a specific time.
--| Example: If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
header_max_forwards: STRING = "Max-Forwards"
-- Limit the number of times the message can be forwarded through proxies or gateways.
--| Example: Max-Forwards: 10
header_proxy_authorization: STRING = "Proxy-Authorization"
-- Authorization credentials for connecting to a proxy.
--| Example: Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
header_range: STRING = "Range"
-- Request only part of an entity. Bytes are numbered from 0.
--| Example: Range: bytes=500-999
header_referer: STRING = "Referer[sic]"
-- This is the address of the previous web page from which a link to the currently requested page was followed. (The word “referrer” is misspelled in the RFC as well as in most implementations.)
--| Example: Referer: http://en.wikipedia.org/wiki/Main_Page
header_te: STRING = "TE"
-- The transfer encodings the user agent is willing to accept: the same values as for the response header Transfer-Encoding can be used, plus the "trailers" value (related to the "chunked" transfer method) to notify the server it accepts to receive additional headers (the trailers) after the last, zero-sized, chunk.
--| Example: TE: trailers, deflate
header_upgrade: STRING = "Upgrade"
-- Ask the server to upgrade to another protocol.
--| Example: Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
header_user_agent: STRING = "User-Agent"
-- The user agent string of the user agent
--| Example: User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
feature -- Response header name
header_accept_ranges: STRING = "Accept-Ranges"
-- "Accept-Ranges" What partial content range types this server supports
--| Example: Accept-Ranges: bytes
header_age: STRING = "Age"
-- The age the object has been in a proxy cache in seconds
--| Example: Age: 12
header_allow: STRING = "Allow"
-- Valid actions for a specified resource. To be used for a 405 Method not allowed
--| Example: Allow: GET, HEAD
header_content_encoding: STRING = "Content-Encoding"
-- The type of encoding used on the data. See HTTP compression.
--| Example: Content-Encoding: gzip
header_content_language: STRING = "Content-Language"
-- The language the content is in
--| Example: Content-Language: da
header_content_location: STRING = "Content-Location"
-- An alternate location for the returned data
--| Example: Content-Location: /index.htm
header_content_disposition: STRING = "Content-Disposition"
-- An opportunity to raise a "File Download" dialogue box for a known MIME type
--| Example: Content-Disposition: attachment; filename=fname.ext
header_content_range: STRING = "Content-Range"
-- Where in a full body message this partial message belongs
--| Example: Content-Range: bytes 21010-47021/47022
header_etag: STRING = "ETag"
-- An identifier for a specific version of a resource, often a message digest
--| Example: ETag: "737060cd8c284d8af7ad3082f209582d"
header_expires: STRING = "Expires"
-- Gives the date/time after which the response is considered stale
--| Example: Expires: Thu, 01 Dec 1994 16:00:00 GMT
header_last_modified: STRING = "Last-Modified"
-- The last modified date for the requested object, in RFC 2822 format
--| Example: Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
header_link: STRING = "Link"
-- Used to express a typed relationship with another resource, where the relation type is defined by RFC 5988
--| Example: Link: </feed>; rel="alternate"
header_location: STRING = "Location"
-- Used in redirection, or when a new resource has been created.
--| Example: Location: http://www.w3.org/pub/WWW/People.html
header_p3p: STRING = "P3P"
-- This header is supposed to set P3P policy, in the form of P3P:CP="your_compact_policy". However, P3P did not take off,[5] most browsers have never fully implemented it, a lot of websites set this header with fake policy text, that was enough to fool browsers the existence of P3P policy and grant permissions for third party cookies.
--| Example: P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
header_proxy_authenticate: STRING = "Proxy-Authenticate"
-- Request authentication to access the proxy.
--| Example: Proxy-Authenticate: Basic
header_refresh: STRING = "Refresh"
-- Used in redirection, or when a new resource has been created. This refresh redirects after 5 seconds. This is a proprietary, non-standard header extension introduced by Netscape and supported by most web browsers.
--| Example: Refresh: 5; url=http://www.w3.org/pub/WWW/People.html
header_retry_after: STRING = "Retry-After"
-- If an entity is temporarily unavailable, this instructs the client to try again after a specified period of time.
--| Example: Retry-After: 120
header_server: STRING = "Server"
-- A name for the server
--| Example: Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
header_set_cookie: STRING = "Set-Cookie"
-- an HTTP cookie
--| Example: Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
header_strict_transport_security: STRING = "Strict-Transport-Security"
-- A HSTS Policy informing the HTTP client how long to cache the HTTPS only policy and whether this applies to subdomains.
--| Example: Strict-Transport-Security: max-age=16070400; includeSubDomains
header_trailer: STRING = "Trailer"
-- The Trailer general field value indicates that the given set of header fields is present in the trailer of a message encoded with chunked transfer-coding.
--| Example: Trailer: Max-Forwards
header_transfer_encoding: STRING = "Transfer-Encoding"
-- The form of encoding used to safely transfer the entity to the user. Currently defined methods are: chunked, compress, deflate, gzip, identity.
--| Example: Transfer-Encoding: chunked
header_vary: STRING = "Vary"
-- Tells downstream proxies how to match future request headers to decide whether the cached response
-- can be used rather than requesting a fresh one from the origin server.
--| Example: Vary: *
header_www_authenticate: STRING = "WWW-Authenticate"
-- Indicates the authentication scheme that should be used to access the requested entity.
--| Example: WWW-Authenticate: Basic
feature -- Request or Response header name
header_cache_control: STRING = "Cache-Control"
-- Request: Used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain
-- Response: Tells all caching mechanisms from server to client whether they may cache this object. It is measured in seconds
--| Request example: Cache-Control: no-cache
--| Response example: Cache-Control: max-age=3600
header_connection: STRING = "Connection"
-- Request: What type of connection the user-agent would prefer
-- Response: Options that are desired for the connection[4]
--| Example: Connection: close
header_content_length: STRING = "Content-Length"
-- Request: The length of the request body in octets (8-bit bytes)
-- Response: The length of the response body in octets (8-bit bytes)
--| Example: Content-Length: 348
header_content_md5: STRING = "Content-MD5"
-- Request: A Base64-encoded binary MD5 sum of the content of the request body
-- Response: A Base64-encoded binary MD5 sum of the content of the response
--| Example: Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
header_content_type: STRING = "Content-Type"
-- Request: The mime type of the body of the request (used with POST and PUT requests)
-- Response : The mime type of this content
--| Request example: Content-Type: application/x-www-form-urlencoded
--| Response example: Content-Type: text/html; charset=utf-8
header_date: STRING = "Date"
-- The date and time that the message was sent
--| Example: Date: Tue, 15 Nov 1994 08:12:31 GMT
header_pragma: STRING = "Pragma"
-- Implementation-specific headers that may have various effects anywhere along the request-response chain.
--| Example: Pragma: no-cache
header_via: STRING = "Via"
-- Request: Informs the server of proxies through which the request was sent.
-- Response: Informs the client of proxies through which the response was sent.
--| Example: Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
header_warning: STRING = "Warning"
-- A general warning about possible problems with the entity body.
--| Example: Warning: 199 Miscellaneous warning
feature -- MIME related
header_content_transfer_encoding: STRING = "Content-Transfer-Encoding"
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

View File

@@ -0,0 +1,140 @@
note
description: "[
Various common MIME types
See also for longer list and description
http://www.iana.org/assignments/media-types/index.html
http://www.webmaster-toolkit.com/mime-types.shtml
Please suggest common/popular MIME type which might be missing here
]"
date: "$Date$"
revision: "$Revision$"
class
HTTP_MIME_TYPES
feature -- Content type : application
application_atom_xml: STRING = "application/atom+xml"
-- atom application content-type header
application_x_www_form_encoded: STRING = "application/x-www-form-urlencoded"
-- Starting chars of form url-encoded data content-type header
application_octet_stream: STRING = "application/octet-stream"
-- Octet stream content-type header
application_javascript: STRING = "application/javascript"
-- JavaScript application content-type header
application_json: STRING = "application/json"
-- JSON application content-type header
application_pdf: STRING = "application/pdf"
-- pdf application content-type header
application_rss_xml: STRING = "application/rss+xml"
-- rss application content-type header
application_xml: STRING = "application/xml"
-- xml application content-type header
application_x_compressed: STRING = "application/x-compressed"
-- x-compressed application content-type header
application_zip: STRING = "application/zip"
-- ZIP application content-type header
feature -- Content type : audio
feature -- Content type : image
image_gif: STRING = "image/gif"
-- GIF image content-type header
image_jpeg: STRING = "image/jpeg"
-- JPEG image content-type header
image_jpg: STRING = "image/jpg"
-- JPEG image content-type header
image_png: STRING = "image/png"
-- PNG image content-type header
image_svg_xml: STRING = "image/svg+xml"
-- SVG+XML image content-type header
feature -- Content type : message
message_http: STRING = "message/http"
-- http message content-type header
message_s_http: STRING = "message/s-http"
-- s-http message content-type
message_partial: STRING = "message/partial"
-- partial message content-type
message_sip: STRING = "message/sip"
-- sip message content-type
feature -- Content type : model
feature -- Content type : multipart
multipart_mixed: STRING = "multipart/mixed"
multipart_alternative: STRING = "multipart/alternative"
multipart_related: STRING = "multipart/related"
multipart_form_data: STRING = "multipart/form-data"
multipart_signed: STRING = "multipart/signed"
multipart_encrypted: STRING = "multipart/encrypted"
feature -- Content type : text
text_css: STRING = "text/css"
-- CSS text content-type header
text_csv: STRING = "text/csv"
-- CSV text content-type header
text_html: STRING = "text/html"
-- HTML text content-type header
text_javascript: STRING = "text/javascript"
-- Javascript text content-type header
-- OBSOLETE
text_json: STRING = "text/json"
-- JSON text content-type header
text_plain: STRING = "text/plain"
-- Plain text content-type header
text_rtf: STRING = "text/rtf"
-- rtf content-type header
text_xml: STRING = "text/xml"
-- XML text content-type header
text_vcard: STRING = "text/vcard"
-- vcard text content-type header
feature -- Content type : video
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

View File

@@ -6,31 +6,30 @@ note
class class
HTTP_REQUEST_METHOD_CONSTANTS HTTP_REQUEST_METHOD_CONSTANTS
inherit
HTTP_REQUEST_METHODS
feature -- Id feature -- Id
method_get: INTEGER = 0x1 head: INTEGER = 0x1
method_post: INTEGER = 0x2 get: INTEGER = 0x2
method_put: INTEGER = 0x4 trace: INTEGER = 0x4
method_delete: INTEGER = 0x8 options: INTEGER = 0x8
method_head: INTEGER = 0x10 post: INTEGER = 0x10
put: INTEGER = 0x20
delete: INTEGER = 0x40
connect: INTEGER = 0x80
feature -- Name feature -- Name
method_get_name: STRING = "GET" method_empty: STRING = ""
method_post_name: STRING = "POST"
method_put_name: STRING = "PUT"
method_delete_name: STRING = "DELETE"
method_head_name: STRING = "HEAD"
method_empty_name: STRING = ""
feature -- Query feature -- Query
@@ -39,35 +38,45 @@ feature -- Query
s: STRING s: STRING
do do
s := a_id.as_lower s := a_id.as_lower
if s.same_string (method_get_name) then if s.same_string (method_get) then
Result := method_get Result := get
elseif s.same_string (method_post_name) then elseif s.same_string (method_post) then
Result := method_post Result := post
elseif s.same_string (method_put_name) then elseif s.same_string (method_put) then
Result := method_put Result := put
elseif s.same_string (method_delete_name) then elseif s.same_string (method_delete) then
Result := method_delete Result := delete
elseif s.same_string (method_head_name) then elseif s.same_string (method_head) then
Result := method_head Result := head
elseif s.same_string (method_trace) then
Result := trace
elseif s.same_string (method_options) then
Result := options
elseif s.same_string (method_connect) then
Result := connect
end end
end end
method_name (a_id: INTEGER): STRING method_name (a_id: INTEGER): STRING
do do
inspect a_id inspect a_id
when method_get then Result := method_get_name when head then Result := method_head
when method_post then Result := method_post_name when get then Result := method_get
when method_put then Result := method_put_name when trace then Result := method_trace
when method_delete then Result := method_delete_name when options then Result := method_options
when method_head then Result := method_head_name when post then Result := method_post
else Result := method_empty_name when put then Result := method_put
when delete then Result := method_delete
when connect then Result := method_connect
else
Result := method_empty
end end
ensure ensure
result_is_upper_case: Result /= Void and then Result.as_upper ~ Result result_is_upper_case: Result /= Void and then Result.as_upper ~ Result
end end
note note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others" copyright: "2011-2011, 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
@@ -76,4 +85,5 @@ note
Website http://www.eiffel.com Website http://www.eiffel.com
Customer support http://support.eiffel.com Customer support http://support.eiffel.com
]" ]"
end end

View File

@@ -0,0 +1,75 @@
note
description: "[
Safe method: HEAD, GET, TRACE, OPTIONS
Intended only for information retrieval, should not change state of server
See http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods
]"
date: "$Date$"
revision: "$Revision$"
class
HTTP_REQUEST_METHODS
feature -- Safe Methods
method_head: STRING = "HEAD"
-- Asks for the response identical to the one that would correspond
-- to a GET request, but without the response body.
-- This is useful for retrieving meta-information written in response headers,
-- without having to transport the entire content.
method_get: STRING = "GET"
-- Requests a representation of the specified resource.
-- Requests using GET (and a few other HTTP methods)
-- "SHOULD NOT have the significance of taking an action other than retrieval"
-- The W3C has published guidance principles on this distinction, saying,
-- "Web application design should be informed by the above principles,
-- but also by the relevant limitations."
method_trace: STRING = "TRACE"
-- Echoes back the received request, so that a client can see what
-- (if any) changes or additions have been made by intermediate servers.
method_options: STRING = "OPTIONS"
-- Returns the HTTP methods that the server supports for specified URL.
-- This can be used to check the functionality of a web server by requesting '*'
-- instead of a specific resource.
feature -- Methods intented for actions
method_post: STRING = "POST"
-- Submits data to be processed (e.g., from an HTML form) to the identified resource.
-- The data is included in the body of the request.
-- This may result in the creation of a new resource or the updates of existing
-- resources or both.
method_put: STRING = "PUT"
-- Uploads a representation of the specified resource.
method_delete: STRING = "DELETE"
-- Deletes the specified resource.
feature -- Other Methods
method_connect: STRING = "CONNECT"
-- Converts the request connection to a transparent TCP/IP tunnel,
-- usually to facilitate SSL-encrypted communication (HTTPS) through
-- an unencrypted HTTP proxy.
method_patch: STRING = "PATCH"
-- Is used to apply partial modifications to a resource
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

View File

@@ -1,8 +1,18 @@
note note
description: "[ description: "[
Summary description for {EWF_HEADER}. The class provides an easy way to build HTTP header.
You will also find some helper feature to help coding most common usage
Please, have a look at constants classes such as
HTTP_MIME_TYPES
HTTP_HEADER_NAMES
HTTP_STATUS_CODE
HTTP_REQUEST_METHODS
(or HTTP_CONSTANTS which groups them for convenience)
Note the return status code is not part of the HTTP header Note the return status code is not part of the HTTP header
However you can set the "Status: " header line if you want
]" ]"
legal: "See notice at end of class." legal: "See notice at end of class."
status: "See notice at end of class." status: "See notice at end of class."
@@ -15,25 +25,33 @@ class
inherit inherit
ANY ANY
HTTP_STATUS_CODE_MESSAGES HTTP_STATUS_CODE_MESSAGES --| useful for `put_status'
export export
{NONE} all {NONE} all
end end
create create
make make,
make_with_count
feature {NONE} -- Initialization feature {NONE} -- Initialization
make make
-- Initialize current -- Initialize current
do do
create {ARRAYED_LIST [READABLE_STRING_8]} headers.make (3) make_with_count (3)
end
make_with_count (n: INTEGER)
-- Make with a capacity of `n' header entries
do
create {ARRAYED_LIST [READABLE_STRING_8]} headers.make (n)
end end
feature -- Recycle feature -- Recycle
recycle recycle
-- Recycle current object
do do
headers.wipe_out headers.wipe_out
end end
@@ -68,12 +86,19 @@ feature -- Access
feature -- Header change: general feature -- Header change: general
add_header (h: READABLE_STRING_8) add_header (h: READABLE_STRING_8)
-- Add header `h'
-- if it already exists, there will be multiple header with same name
-- which can also be valid
require
h_not_empty: not h.is_empty
do do
headers.force (h) headers.force (h)
end end
put_header (h: READABLE_STRING_8) put_header (h: READABLE_STRING_8)
-- Add header `h' or replace existing header of same header name -- Add header `h' or replace existing header of same header name
require
h_not_empty: not h.is_empty
do do
force_header_by_name (header_name (h), h) force_header_by_name (header_name (h), h)
end end
@@ -90,9 +115,11 @@ feature -- Header change: general
put_header (k + colon_space + v) put_header (k + colon_space + v)
end end
feature -- Content related header feature -- Status related
put_status (c: INTEGER) put_status (c: INTEGER)
-- Put "Status: " header
-- Rarely used
local local
s: STRING s: STRING
do do
@@ -104,58 +131,33 @@ feature -- Content related header
put_header_key_value ("Status", s) put_header_key_value ("Status", s)
end end
feature -- Content related header
put_content_type (t: READABLE_STRING_8) put_content_type (t: READABLE_STRING_8)
do do
put_header_key_value (name_content_type, t) put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t)
end end
add_content_type (t: READABLE_STRING_8) add_content_type (t: READABLE_STRING_8)
-- same as `put_content_type', but allow multiple definition of "Content-Type" -- same as `put_content_type', but allow multiple definition of "Content-Type"
do do
add_header_key_value (name_content_type, t) add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t)
end end
put_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8) put_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8)
do do
put_header_key_value (name_content_type, t + "; name=%"" + n + "%"") put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; name=%"" + n + "%"")
end end
add_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8) add_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8)
-- same as `put_content_type_with_name', but allow multiple definition of "Content-Type" -- same as `put_content_type_with_name', but allow multiple definition of "Content-Type"
do do
add_header_key_value (name_content_type, t + "; name=%"" + n + "%"") add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; name=%"" + n + "%"")
end end
put_content_type_text_css do put_content_type ("text/css") end
put_content_type_text_csv do put_content_type ("text/csv") end
put_content_type_text_html do put_content_type ("text/html") end
put_content_type_text_javascript do put_content_type ("text/javascript") end
put_content_type_text_json do put_content_type ("text/json") end
put_content_type_text_plain do put_content_type ("text/plain") end
put_content_type_text_xml do put_content_type ("text/xml") end
put_content_type_application_json do put_content_type ("application/json") end
put_content_type_application_javascript do put_content_type ("application/javascript") end
put_content_type_application_zip do put_content_type ("application/zip") end
put_content_type_image_gif do put_content_type ("image/gif") end
put_content_type_image_png do put_content_type ("image/png") end
put_content_type_image_jpg do put_content_type ("image/jpg") end
put_content_type_image_svg_xml do put_content_type ("image/svg+xml") end
put_content_type_message_http do put_content_type ("message/http") end
put_content_type_multipart_mixed do put_content_type ("multipart/mixed") end
put_content_type_multipart_alternative do put_content_type ("multipart/alternative") end
put_content_type_multipart_related do put_content_type ("multipart/related") end
put_content_type_multipart_form_data do put_content_type ("multipart/form-data") end
put_content_type_multipart_signed do put_content_type ("multipart/signed") end
put_content_type_multipart_encrypted do put_content_type ("multipart/encrypted") end
put_content_length (n: INTEGER) put_content_length (n: INTEGER)
do do
put_header_key_value (name_content_length, n.out) put_header_key_value ({HTTP_HEADER_NAMES}.header_content_length, n.out)
end end
put_content_transfer_encoding (a_mechanism: READABLE_STRING_8) put_content_transfer_encoding (a_mechanism: READABLE_STRING_8)
@@ -170,7 +172,19 @@ feature -- Content related header
--| / x-token --| / x-token
do do
put_header_key_value ("Content-Transfer-Encoding", a_mechanism) put_header_key_value ({HTTP_HEADER_NAMES}.header_content_transfer_encoding, a_mechanism)
end
put_transfer_encoding (a_enc: READABLE_STRING_8)
-- Put "Transfer-Encoding" header with for instance "chunked"
do
put_header_key_value ({HTTP_HEADER_NAMES}.header_transfer_encoding, a_enc)
end
put_transfer_encoding_chunked
-- Put "Transfer-Encoding: chunked" header
do
put_transfer_encoding ("chunked")
end end
put_content_disposition (a_type: READABLE_STRING_8; a_params: detachable READABLE_STRING_8) put_content_disposition (a_type: READABLE_STRING_8; a_params: detachable READABLE_STRING_8)
@@ -199,17 +213,46 @@ feature -- Content related header
--| ; numeric timezones (+HHMM or -HHMM) MUST be used --| ; numeric timezones (+HHMM or -HHMM) MUST be used
do do
if a_params /= Void then if a_params /= Void then
put_header_key_value ("Content-Disposition", a_type + "; " + a_params) put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type + semi_colon_space + a_params)
else else
put_header_key_value ("Content-Disposition", a_type) put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type)
end end
end end
feature -- Others feature -- Content-type helpers
put_content_type_text_css do put_content_type ({HTTP_MIME_TYPES}.text_css) end
put_content_type_text_csv do put_content_type ({HTTP_MIME_TYPES}.text_csv) end
put_content_type_text_html do put_content_type ({HTTP_MIME_TYPES}.text_html) end
put_content_type_text_javascript do put_content_type ({HTTP_MIME_TYPES}.text_javascript) end
put_content_type_text_json do put_content_type ({HTTP_MIME_TYPES}.text_json) end
put_content_type_text_plain do put_content_type ({HTTP_MIME_TYPES}.text_plain) end
put_content_type_text_xml do put_content_type ({HTTP_MIME_TYPES}.text_xml) end
put_content_type_application_json do put_content_type ({HTTP_MIME_TYPES}.application_json) end
put_content_type_application_javascript do put_content_type ({HTTP_MIME_TYPES}.application_javascript) end
put_content_type_application_zip do put_content_type ({HTTP_MIME_TYPES}.application_zip) end
put_content_type_image_gif do put_content_type ({HTTP_MIME_TYPES}.image_gif) end
put_content_type_image_png do put_content_type ({HTTP_MIME_TYPES}.image_png) end
put_content_type_image_jpg do put_content_type ({HTTP_MIME_TYPES}.image_jpg) end
put_content_type_image_svg_xml do put_content_type ({HTTP_MIME_TYPES}.image_svg_xml) end
put_content_type_message_http do put_content_type ({HTTP_MIME_TYPES}.message_http) end
put_content_type_multipart_mixed do put_content_type ({HTTP_MIME_TYPES}.multipart_mixed) end
put_content_type_multipart_alternative do put_content_type ({HTTP_MIME_TYPES}.multipart_alternative) end
put_content_type_multipart_related do put_content_type ({HTTP_MIME_TYPES}.multipart_related) end
put_content_type_multipart_form_data do put_content_type ({HTTP_MIME_TYPES}.multipart_form_data) end
put_content_type_multipart_signed do put_content_type ({HTTP_MIME_TYPES}.multipart_signed) end
put_content_type_multipart_encrypted do put_content_type ({HTTP_MIME_TYPES}.multipart_encrypted) end
feature -- Date
put_date (s: READABLE_STRING_8) put_date (s: READABLE_STRING_8)
-- Put "Date: " header
do do
put_header_key_value ("Date", s) put_header_key_value ({HTTP_HEADER_NAMES}.header_date, s)
end end
put_current_date put_current_date
@@ -224,6 +267,8 @@ feature -- Others
put_date (dt.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT") put_date (dt.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
end end
feature -- Others
put_expires (n: INTEGER) put_expires (n: INTEGER)
do do
put_header_key_value ("Expires", n.out) put_header_key_value ("Expires", n.out)
@@ -249,14 +294,18 @@ feature -- Redirection
put_location (a_location: READABLE_STRING_8) put_location (a_location: READABLE_STRING_8)
-- Tell the client the new location `a_location' -- Tell the client the new location `a_location'
require
a_location_valid: not a_location.is_empty
do do
put_header_key_value ("Location", a_location) put_header_key_value ({HTTP_HEADER_NAMES}.header_location, a_location)
end end
put_refresh (a_location: READABLE_STRING_8; a_timeout_in_seconds: INTEGER) put_refresh (a_location: READABLE_STRING_8; a_timeout_in_seconds: INTEGER)
-- Tell the client to refresh page with `a_location' after `a_timeout_in_seconds' in seconds -- Tell the client to refresh page with `a_location' after `a_timeout_in_seconds' in seconds
require
a_location_valid: not a_location.is_empty
do do
put_header_key_value ("Refresh", a_timeout_in_seconds.out + "; url=" + a_location) put_header_key_value ({HTTP_HEADER_NAMES}.header_refresh, a_timeout_in_seconds.out + "; url=" + a_location)
end end
feature -- Cookie feature -- Cookie
@@ -269,18 +318,18 @@ feature -- Cookie
local local
s: STRING s: STRING
do do
s := "Set-Cookie:" + key + "=" + value s := {HTTP_HEADER_NAMES}.header_set_cookie + colon_space + key + "=" + value
if expiration /= Void then if expiration /= Void then
s.append (";expires=" + expiration) s.append ("; expires=" + expiration)
end end
if path /= Void then if path /= Void then
s.append (";path=" + path) s.append ("; path=" + path)
end end
if domain /= Void then if domain /= Void then
s.append (";domain=" + domain) s.append ("; domain=" + domain)
end end
if secure /= Void then if secure /= Void then
s.append (";secure=" + secure) s.append ("; secure=" + secure)
end end
add_header (s) add_header (s)
end end
@@ -292,6 +341,7 @@ feature -- Status report
local local
c: like headers.new_cursor c: like headers.new_cursor
n: INTEGER n: INTEGER
l_line: READABLE_STRING_8
do do
from from
n := a_name.count n := a_name.count
@@ -299,7 +349,12 @@ feature -- Status report
until until
c.after or Result c.after or Result
loop loop
Result := c.item.starts_with (a_name) and then c.item [n + 1] = ':' l_line := c.item
if l_line.starts_with (a_name) then
if l_line.valid_index (n + 1) then
Result := l_line [n + 1] = ':'
end
end
c.forth c.forth
end end
end end
@@ -307,7 +362,7 @@ feature -- Status report
has_content_length: BOOLEAN has_content_length: BOOLEAN
-- Has header "content_length" -- Has header "content_length"
do do
Result := has_header_named (name_content_length) Result := has_header_named ({HTTP_HEADER_NAMES}.header_content_length)
end end
feature {NONE} -- Implementation: Header feature {NONE} -- Implementation: Header
@@ -384,8 +439,7 @@ feature {NONE} -- Implementation
feature {NONE} -- Constants feature {NONE} -- Constants
colon_space: STRING = ": " colon_space: STRING = ": "
name_content_length: STRING = "Content-Length" semi_colon_space: STRING = "; "
name_content_type: STRING = "Content-Type"
note note
copyright: "2011-2011, Eiffel Software and others" copyright: "2011-2011, Eiffel Software and others"

View File

@@ -513,7 +513,7 @@ feature {NONE} -- Form fields and related
l_type := content_type l_type := content_type
if if
l_type /= Void and then l_type /= Void and then
l_type.starts_with ({HTTP_CONSTANTS}.multipart_form) l_type.starts_with ({HTTP_MIME_TYPES}.multipart_form_data)
then then
create vars.make (5) create vars.make (5)
vars.compare_objects vars.compare_objects

View File

@@ -90,7 +90,6 @@ feature -- Header output operation
do do
set_status_code (a_status_code) set_status_code (a_status_code)
create h.make create h.make
h.put_status (a_status_code)
if a_headers /= Void then if a_headers /= Void then
from from
i := a_headers.lower i := a_headers.lower

View File

@@ -161,7 +161,7 @@ feature {NONE} -- Events
do do
get_http_session get_http_session
if attached http_session as sess then if attached http_session as sess then
if attached sess.post (a_url, ctx) as res and then not res.error_occurred and then attached res.body as l_body then if attached sess.post (a_url, ctx, Void) as res and then not res.error_occurred and then attached res.body as l_body then
assert ("Good answer got=%""+l_body+"%" expected=%""+a_expected_body+"%"", l_body.same_string (a_expected_body)) assert ("Good answer got=%""+l_body+"%" expected=%""+a_expected_body+"%"", l_body.same_string (a_expected_body))
else else
assert ("Request %""+a_url+"%" failed", False) assert ("Request %""+a_url+"%" failed", False)

View File

@@ -15,21 +15,21 @@ feature -- Execute template
m: READABLE_STRING_8 m: READABLE_STRING_8
do do
m := req.request_method.as_upper m := req.request_method.as_upper
if m.same_string ("GET") then if m.same_string ({HTTP_REQUEST_METHODS}.method_get) then
execute_get (ctx, req, res) execute_get (ctx, req, res)
elseif m.same_string ("PUT") then elseif m.same_string ({HTTP_REQUEST_METHODS}.method_put) then
execute_put (ctx, req, res) execute_put (ctx, req, res)
elseif m.same_string ("DELETE") then elseif m.same_string ({HTTP_REQUEST_METHODS}.method_delete) then
execute_delete (ctx, req, res) execute_delete (ctx, req, res)
elseif m.same_string ("POST") then elseif m.same_string ({HTTP_REQUEST_METHODS}.method_post) then
execute_post (ctx, req, res) execute_post (ctx, req, res)
elseif m.same_string ("TRACE") then elseif m.same_string ({HTTP_REQUEST_METHODS}.method_trace) then
execute_trace (ctx, req, res) execute_trace (ctx, req, res)
elseif m.same_string ("OPTIONS") then elseif m.same_string ({HTTP_REQUEST_METHODS}.method_options) then
execute_options (ctx, req, res) execute_options (ctx, req, res)
elseif m.same_string ("HEAD") then elseif m.same_string ({HTTP_REQUEST_METHODS}.method_head) then
execute_head (ctx, req, res) execute_head (ctx, req, res)
elseif m.same_string ("CONNECT") then elseif m.same_string ({HTTP_REQUEST_METHODS}.method_connect) then
execute_connect (ctx, req, res) execute_connect (ctx, req, res)
else else
--| Eventually handle other methods... --| Eventually handle other methods...

View File

@@ -79,7 +79,7 @@ feature -- Helper
end end
res.set_status_code ({HTTP_STATUS_CODE}.method_not_allowed) res.set_status_code ({HTTP_STATUS_CODE}.method_not_allowed)
res.write_header ({HTTP_STATUS_CODE}.method_not_allowed, << res.write_header ({HTTP_STATUS_CODE}.method_not_allowed, <<
["Content-Type", {HTTP_CONSTANTS}.plain_text], ["Content-Type", {HTTP_MIME_TYPES}.text_plain],
["Allow", s] ["Allow", s]
>>) >>)
res.write_string ("Unsupported request method, Allow: " + s + "%N") res.write_string ("Unsupported request method, Allow: " + s + "%N")

View File

@@ -1,6 +1,5 @@
note note
description: "Summary description for {REQUEST_HANDLER_CONTEXT}." description: "Summary description for {REQUEST_HANDLER_CONTEXT}."
author: ""
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
@@ -56,15 +55,15 @@ feature -- Query
-- `a_content_type' converted into a request format name -- `a_content_type' converted into a request format name
do do
if a_content_type /= Void then if a_content_type /= Void then
if a_content_type.same_string ({HTTP_CONSTANTS}.json_text) then if a_content_type.same_string ({HTTP_MIME_TYPES}.text_json) then
Result := {HTTP_FORMAT_CONSTANTS}.json_name Result := {HTTP_FORMAT_CONSTANTS}.json_name
elseif a_content_type.same_string ({HTTP_CONSTANTS}.json_app) then elseif a_content_type.same_string ({HTTP_MIME_TYPES}.application_json) then
Result := {HTTP_FORMAT_CONSTANTS}.json_name Result := {HTTP_FORMAT_CONSTANTS}.json_name
elseif a_content_type.same_string ({HTTP_CONSTANTS}.xml_text) then elseif a_content_type.same_string ({HTTP_MIME_TYPES}.text_xml) then
Result := {HTTP_FORMAT_CONSTANTS}.xml_name Result := {HTTP_FORMAT_CONSTANTS}.xml_name
elseif a_content_type.same_string ({HTTP_CONSTANTS}.html_text) then elseif a_content_type.same_string ({HTTP_MIME_TYPES}.text_html) then
Result := {HTTP_FORMAT_CONSTANTS}.html_name Result := {HTTP_FORMAT_CONSTANTS}.html_name
elseif a_content_type.same_string ({HTTP_CONSTANTS}.plain_text) then elseif a_content_type.same_string ({HTTP_MIME_TYPES}.text_plain) then
Result := {HTTP_FORMAT_CONSTANTS}.text_name Result := {HTTP_FORMAT_CONSTANTS}.text_name
end end
end end