Change structure of EWF, to follow better categorization

This commit is contained in:
Jocelyn Fiat
2012-06-13 22:32:17 +02:00
parent 3df1a26220
commit db448001a1
134 changed files with 105 additions and 94 deletions

View File

@@ -0,0 +1,8 @@
# HTTP library
## Overview
## Usage
## Examples

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http" uuid="F8BE3C55-88E8-4103-A936-B1E5CB1D330E" library_target="http">
<target name="http">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http" uuid="F8BE3C55-88E8-4103-A936-B1E5CB1D330E" library_target="http">
<target name="http">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" syntax="provisional">
<assertions precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,10 @@
${NOTE_KEYWORD}
copyright: "2011-${YEAR}, Jocelyn Fiat, 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
]"

View File

@@ -0,0 +1,48 @@
note
description: "[
Constants class providing most common constants used in HTTP communication
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTTP_CONSTANTS
inherit
HTTP_MIME_TYPES
HTTP_HEADER_NAMES
HTTP_STATUS_CODE
HTTP_REQUEST_METHODS
feature -- Ports
default_http_port: INTEGER = 80
default_https_port: INTEGER = 443
feature -- Server, header
http_version_1_0: STRING = "HTTP/1.0"
http_version_1_1: STRING = "HTTP/1.1"
feature -- Misc
crlf: STRING = "%R%N"
default_bufsize: INTEGER = 16384 --| 16K
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,46 @@
note
description: "[
This class is to represent the CONTENT_TYPE value
]"
date: "$Date$"
revision: "$Revision$"
class
HTTP_CONTENT_TYPE
inherit
HTTP_MEDIA_TYPE
create
make,
make_from_string
feature -- Access
charset_parameter: detachable READABLE_STRING_8
do
if has_charset_parameter then
Result := parameter (charset_parameter_name)
end
end
has_charset_parameter: BOOLEAN
do
Result := has_parameter (charset_parameter_name)
end
feature -- Constant
charset_parameter_name: STRING_8 = "charset"
note
copyright: "2011-2012, Jocelyn Fiat, 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,71 @@
note
description: "Summary description for {HTTP_DATE_TIME_UTILITIES}."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTTP_DATE_TIME_UTILITIES
feature -- Access
now_utc: DATE_TIME
do
create Result.make_now_utc
end
epoch: DATE_TIME
once ("THREAD")
create Result.make_from_epoch (0)
end
feature -- Unix time stamp
unix_time_stamp (dt: detachable DATE_TIME): INTEGER_64
-- Unix time stamp from `dt' if attached or from epoch is detached
local
l_date_time: DATE_TIME
do
if dt /= Void then
l_date_time := dt
else
l_date_time := now_utc
end
Result := l_date_time.definite_duration (epoch).seconds_count
end
fine_unix_time_stamp (dt: detachable DATE_TIME): DOUBLE
-- Fine unix time stamp from `dt' if attached or from epoch is detached
local
l_date_time: DATE_TIME
do
if dt /= Void then
l_date_time := dt
else
l_date_time := now_utc
end
Result := l_date_time.definite_duration (epoch).fine_seconds_count
end
feature -- Unix time stamp conversion
unix_time_stamp_to_date_time (i64: INTEGER_64): DATE_TIME
-- Date time related to `i64'
do
create Result.make_from_epoch (i64.as_integer_32)
ensure
same_unix_time_stamp: unix_time_stamp (Result) = i64
end
;note
copyright: "Copyright (c) 1984-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,238 @@
note
description: "[
Various common MIME types for file extensions
See also for longer list and description
http://www.webmaster-toolkit.com/mime-types.shtml
Please suggest missing entries
]"
date: "$Date$"
revision: "$Revision$"
class
HTTP_FILE_EXTENSION_MIME_MAPPING
inherit
ANY
HTTP_MIME_TYPES
export
{NONE} all
end
create
make_empty,
make_default,
make_from_string,
make_from_file
feature {NONE} -- Initialization
make_empty (n: INTEGER)
-- Create with no mapping
-- but one can use `map' to add new mapping
do
create mapping.make (n)
mapping.compare_objects
end
make_default
-- Create with default limited mapping
-- One can use `map' to add new mapping
local
m: like mapping
do
create m.make (40)
mapping := m
m.compare_objects
m.force (text_css, "css")
m.force (text_html, "html")
m.force (text_xml, "xml")
m.force (application_json, "json")
m.force (application_javascript, "js")
m.force (application_rss_xml, "rss")
m.force (application_atom_xml, "atom")
m.force (image_x_ico, "ico")
m.force (image_gif, "gif")
m.force (image_jpeg, "jpeg")
m.force (image_jpg, "jpg")
m.force (image_png, "png")
m.force (application_zip, "zip")
m.force (application_x_bzip, "bz")
m.force (application_x_bzip2, "bz2")
m.force (application_x_gzip, "gz")
m.force (application_x_gzip, "gzip")
m.force (application_x_tar, "tar")
m.force (application_x_compressed, "tgz")
m.force (application_postscript, "ps")
m.force (application_pdf, "pdf")
m.force (application_x_shockwave_flash, "swf")
m.force (text_plain, "conf")
m.force (text_plain, "log")
m.force (text_plain, "text")
m.force (text_plain, "txt")
end
make_from_file (fn: READABLE_STRING_8)
-- Create with mime.types file
-- One can use `map' to add new mapping
local
f: RAW_FILE
do
create f.make (fn)
if f.exists and then f.is_readable then
make_empty (50)
f.open_read
from
f.read_line
until
f.exhausted or f.end_of_file
loop
add_mapping_line (f.last_string)
f.read_line
end
f.close
else
make_empty (0)
end
end
make_from_string (t: READABLE_STRING_8)
-- Set mapping from multiline string `t'
-- line should be formatted as in http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
--| # is a comment
--| mime-type space(s) extensions
local
i,j,n: INTEGER
do
make_empty (10)
n := t.count
if n > 0 then
from
i := 1
until
i = 0 or i > n
loop
j := t.index_of ('%N', i)
if j > 0 then
add_mapping_line (t.substring (i, j - 1))
i := j + 1
else
add_mapping_line (t.substring (i, n))
i := 0
end
end
end
end
feature -- Access
mime_type (ext: READABLE_STRING_8): detachable READABLE_STRING_8
-- Mime type for extension `ext'
do
Result := mapping.item (ext.as_lower)
end
feature -- Element change
map (e: READABLE_STRING_8; t: READABLE_STRING_8)
-- Add mapping extension `e' to mime type `t'
do
mapping.force (t, e.as_lower)
end
feature {NONE} -- Implementation
add_mapping_line (t: READABLE_STRING_8)
local
i,j,n: INTEGER
l_type, l_ext: READABLE_STRING_8
do
n := t.count
if n > 0 then
-- ignore blanks
i := next_non_blank_position (t, i)
if i > 0 then
if t[i] = '#' then
--| ignore
else
j := next_blank_position (t, i)
if j > i then
l_type := t.substring (i, j - 1)
from
until
i = 0
loop
i := next_non_blank_position (t, j)
if i > 0 then
j := next_blank_position (t, i)
if j = 0 then
l_ext := t.substring (i, n)
i := 0
else
l_ext := t.substring (i, j - 1)
i := j
end
map (l_ext, l_type)
end
end
end
end
end
end
end
next_blank_position (s: READABLE_STRING_8; p: INTEGER): INTEGER
local
i, n: INTEGER
do
n := s.count
from
i := p + 1
until
i > n or s[i].is_space
loop
i := i + 1
end
if i <= n then
Result := i
end
end
next_non_blank_position (s: READABLE_STRING_8; p: INTEGER): INTEGER
local
i, n: INTEGER
do
n := s.count
from
i := p + 1
until
i > n or not s[i].is_space
loop
i := i + 1
end
if i <= n then
Result := i
end
end
feature {NONE} -- Extension MIME mapping
mapping: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
invariant
mapping_keys_are_lowercase: across mapping as c all c.key.same_string (c.key.as_lower) end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,86 @@
note
description: "Summary description for {HTTP_FORMAT_CONSTANTS}."
date: "$Date$"
revision: "$Revision$"
class
HTTP_FORMAT_CONSTANTS
feature -- Id
json: INTEGER = 0x1
xml: INTEGER = 0x2
text: INTEGER = 0x4
html: INTEGER = 0x8
rss: INTEGER = 0x10
atom: INTEGER = 0x20
feature -- Name
json_name: STRING = "json"
xml_name: STRING = "xml"
text_name: STRING = "text"
html_name: STRING = "html"
rss_name: STRING = "rss"
atom_name: STRING = "atom"
empty_name: STRING = ""
feature -- Query
format_id (a_id: READABLE_STRING_GENERAL): INTEGER
local
s: STRING
do
s := a_id.as_string_8.as_lower
if s.same_string (json_name) then
Result := json
elseif s.same_string (xml_name) then
Result := xml
elseif s.same_string (text_name) then
Result := text
elseif s.same_string (html_name) then
Result := html
elseif s.same_string (rss_name) then
Result := rss
elseif s.same_string (atom_name) then
Result := atom
end
end
format_name (a_id: INTEGER): READABLE_STRING_8
do
inspect a_id
when json then Result := json_name
when xml then Result := xml_name
when text then Result := text_name
when html then Result := html_name
when rss then Result := rss_name
when atom then Result := atom_name
else Result := empty_name
end
ensure
result_is_lower_case: Result /= Void and then Result.as_lower ~ Result
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,689 @@
note
description: "[
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
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTTP_HEADER
inherit
ANY
create
make,
make_with_count,
make_from_array,
make_from_header,
make_from_raw_header_data
convert
make_from_array ({ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]]}),
string: {READABLE_STRING_8, STRING_8}
feature {NONE} -- Initialization
make
-- Initialize current
do
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
make_from_array (a_headers: ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]])
-- Create HEADER from array of pair (key,value)
do
if a_headers.is_empty then
make_with_count (0)
else
make_with_count (a_headers.count)
append_array (a_headers)
end
end
make_from_header (a_header: HTTP_HEADER)
-- Create Current from existing HEADER `a_header'
do
make_with_count (a_header.headers.count)
append_header_object (a_header)
end
make_from_raw_header_data (h: READABLE_STRING_8)
-- Create Current from raw header data
local
line : detachable STRING
lines: LIST [READABLE_STRING_8]
do
lines := h.split ('%N')
make_with_count (lines.count)
across
lines as c
loop
line := c.item
if not line.is_empty then
if line [line.count] = '%R' then
line.remove_tail (1)
end
add_header (line)
end
end
end
feature -- Recycle
recycle
-- Recycle current object
do
headers.wipe_out
end
feature -- Access
headers: ARRAYED_LIST [READABLE_STRING_8]
-- Header's lines
string: STRING_8
-- String representation of the headers
local
l_headers: like headers
do
l_headers := headers
if not l_headers.is_empty then
create Result.make (l_headers.count * 32)
across
l_headers as c
loop
append_line_to (c.item, Result)
end
else
create Result.make_empty
end
ensure
result_has_ending_cr_lf: Result.count >= 2 implies Result.substring (Result.count - 1, Result.count).same_string ("%R%N")
result_has_single_ending_cr_lf: Result.count >= 4 implies not Result.substring (Result.count - 3, Result.count).same_string ("%R%N%R%N")
end
to_name_value_iterable: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]
local
res: ARRAYED_LIST [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]
do
create res.make (headers.count)
across
headers as c
loop
if attached header_name_value (c.item) as tu then
res.extend (tu)
end
end
Result := res
end
feature -- Header: filling
append_array (a_headers: ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]])
-- Append array of key,value headers
do
headers.grow (headers.count + a_headers.count)
across
a_headers as c
loop
put_header_key_value (c.item.key, c.item.value)
end
end
append_header_object (h: HTTP_HEADER)
-- Append headers from `h'
do
headers.grow (headers.count + h.headers.count)
across
h.headers as c
loop
add_header (c.item.string)
end
end
feature -- Header change: general
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
headers.force (h)
end
put_header (h: READABLE_STRING_8)
-- Add header `h' or replace existing header of same header name
require
h_not_empty: not h.is_empty
do
force_header_by_name (header_name_colon (h), h)
end
add_header_key_value (k,v: READABLE_STRING_8)
-- Add header `k:v', or replace existing header of same header name/key
do
add_header (k + colon_space + v)
end
put_header_key_value (k,v: READABLE_STRING_8)
-- Add header `k:v', or replace existing header of same header name/key
do
put_header (k + colon_space + v)
end
feature -- Content related header
put_content_type (t: READABLE_STRING_8)
do
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t)
end
add_content_type (t: READABLE_STRING_8)
-- same as `put_content_type', but allow multiple definition of "Content-Type"
do
add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t)
end
put_content_type_with_parameters (t: READABLE_STRING_8; a_params: detachable ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
local
s: STRING_8
do
if a_params /= Void and then not a_params.is_empty then
create s.make_from_string (t)
across
a_params as p
loop
if attached p.item as nv then
s.append_character (';')
s.append_character (' ')
s.append (nv.name)
s.append_character ('=')
s.append_character ('%"')
s.append (nv.value)
s.append_character ('%"')
end
end
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, s)
else
put_content_type (t)
end
end
add_content_type_with_parameters (t: READABLE_STRING_8; a_params: detachable ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
local
s: STRING_8
do
if a_params /= Void and then not a_params.is_empty then
create s.make_from_string (t)
across
a_params as p
loop
if attached p.item as nv then
s.append_character (';')
s.append_character (' ')
s.append (nv.name)
s.append_character ('=')
s.append_character ('%"')
s.append (nv.value)
s.append_character ('%"')
end
end
add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, s)
else
add_content_type (t)
end
end
put_content_type_with_charset (t: READABLE_STRING_8; c: READABLE_STRING_8)
do
put_content_type_with_parameters (t, <<["charset", c]>>)
end
add_content_type_with_charset (t: READABLE_STRING_8; c: READABLE_STRING_8)
-- same as `put_content_type_with_charset', but allow multiple definition of "Content-Type"
do
add_content_type_with_parameters (t, <<["charset", c]>>)
end
put_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8)
do
put_content_type_with_parameters (t, <<["name", n]>>)
end
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"
do
add_content_type_with_parameters (t, <<["name", n]>>)
end
put_content_length (n: INTEGER)
do
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_length, n.out)
end
put_content_transfer_encoding (a_mechanism: READABLE_STRING_8)
-- Put "Content-Transfer-Encoding" header with for instance "binary"
--| encoding := "Content-Transfer-Encoding" ":" mechanism
--|
--| mechanism := "7bit" ; case-insensitive
--| / "quoted-printable"
--| / "base64"
--| / "8bit"
--| / "binary"
--| / x-token
do
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_binary
-- Put "Transfer-Encoding: binary" header
do
put_transfer_encoding (str_binary)
end
put_transfer_encoding_chunked
-- Put "Transfer-Encoding: chunked" header
do
put_transfer_encoding (str_chunked)
end
put_content_disposition (a_type: READABLE_STRING_8; a_params: detachable READABLE_STRING_8)
-- Put "Content-Disposition" header
--| See RFC2183
--| disposition := "Content-Disposition" ":"
--| disposition-type
--| *(";" disposition-parm)
--| disposition-type := "inline"
--| / "attachment"
--| / extension-token
--| ; values are not case-sensitive
--| disposition-parm := filename-parm
--| / creation-date-parm
--| / modification-date-parm
--| / read-date-parm
--| / size-parm
--| / parameter
--| filename-parm := "filename" "=" value
--| creation-date-parm := "creation-date" "=" quoted-date-time
--| modification-date-parm := "modification-date" "=" quoted-date-time
--| read-date-parm := "read-date" "=" quoted-date-time
--| size-parm := "size" "=" 1*DIGIT
--| quoted-date-time := quoted-string
--| ; contents MUST be an RFC 822 `date-time'
--| ; numeric timezones (+HHMM or -HHMM) MUST be used
do
if a_params /= Void then
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type + semi_colon_space + a_params)
else
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type)
end
end
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
put_content_type_application_x_www_form_encoded do put_content_type ({HTTP_MIME_TYPES}.application_x_www_form_encoded) end
feature -- Date
put_date (s: READABLE_STRING_8)
-- Put "Date: " header
do
put_header_key_value ({HTTP_HEADER_NAMES}.header_date, s)
end
put_current_date
-- Put current date time with "Date" header
do
put_utc_date (create {DATE_TIME}.make_now_utc)
end
put_utc_date (dt: DATE_TIME)
-- Put UTC date time `dt' with "Date" header
do
put_date (date_to_rfc1123_http_date_format (dt))
end
put_last_modified (dt: DATE_TIME)
-- Put UTC date time `dt' with "Date" header
do
put_header_key_value ({HTTP_HEADER_NAMES}.header_last_modified, date_to_rfc1123_http_date_format (dt))
end
feature -- Others
put_expires (n: INTEGER)
do
put_header_key_value ("Expires", n.out)
end
put_cache_control (s: READABLE_STRING_8)
-- `s' could be for instance "no-cache, must-revalidate"
do
put_header_key_value ("Cache-Control", s)
end
put_pragma (s: READABLE_STRING_8)
do
put_header_key_value ("Pragma", s)
end
put_pragma_no_cache
do
put_pragma ("no-cache")
end
feature -- Redirection
put_location (a_location: READABLE_STRING_8)
-- Tell the client the new location `a_location'
require
a_location_valid: not a_location.is_empty
do
put_header_key_value ({HTTP_HEADER_NAMES}.header_location, a_location)
end
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
require
a_location_valid: not a_location.is_empty
do
put_header_key_value ({HTTP_HEADER_NAMES}.header_refresh, a_timeout_in_seconds.out + "; url=" + a_location)
end
feature -- Cookie
put_cookie (key, value: READABLE_STRING_8; expiration, path, domain: detachable READABLE_STRING_8; secure, http_only: BOOLEAN)
-- Set a cookie on the client's machine
-- with key 'key' and value 'value'.
-- Note: you should avoid using "localhost" as `domain' for local cookies
-- since they are not always handled by browser (for instance Chrome)
require
make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty)
domain_without_port_info: domain /= Void implies domain.index_of (':', 1) = 0
local
s: STRING
do
s := {HTTP_HEADER_NAMES}.header_set_cookie + colon_space + key + "=" + value
if
domain /= Void and then not domain.same_string ("localhost")
then
s.append ("; Domain=" + domain)
end
if path /= Void then
s.append ("; Path=" + path)
end
if expiration /= Void then
s.append ("; Expires=" + expiration)
end
if secure then
s.append ("; Secure")
end
if http_only then
s.append ("; HttpOnly")
end
add_header (s)
end
put_cookie_with_expiration_date (key, value: READABLE_STRING_8; expiration: DATE_TIME; path, domain: detachable READABLE_STRING_8; secure, http_only: BOOLEAN)
-- Set a cookie on the client's machine
-- with key 'key' and value 'value'.
require
make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty)
do
put_cookie (key, value, date_to_rfc1123_http_date_format (expiration), path, domain, secure, http_only)
end
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
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
loop
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
end
end
has_content_length: BOOLEAN
-- 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)
-- Add header `h' or replace existing header of same header name `n'
require
h_has_name_n: (n /= Void and attached header_name_colon (h) as hn) implies n.same_string (hn)
local
l_headers: like headers
do
if n /= Void then
from
l_headers := headers
l_headers.start
until
l_headers.after or l_headers.item.starts_with (n)
loop
l_headers.forth
end
if not l_headers.after then
l_headers.replace (h)
else
add_header (h)
end
else
add_header (h)
end
end
header_name_colon (h: READABLE_STRING_8): detachable STRING_8
-- If any, header's name with colon
--| ex: for "Foo-bar: something", this will return "Foo-bar:"
local
s: detachable STRING_8
i,n: INTEGER
c: CHARACTER
do
from
i := 1
n := h.count
create s.make (10)
until
i > n or c = ':' or s = Void
loop
c := h[i]
inspect c
when ':' then
s.extend (c)
when '-', 'a' .. 'z', 'A' .. 'Z' then
s.extend (c)
else
s := Void
end
i := i + 1
end
Result := s
end
header_name_value (h: READABLE_STRING_8): detachable TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]
-- If any, header's [name,value]
--| ex: for "Foo-bar: something", this will return ["Foo-bar", "something"]
local
s: detachable STRING_8
i,n: INTEGER
c: CHARACTER
do
from
i := 1
n := h.count
create s.make (10)
until
i > n or c = ':' or s = Void
loop
c := h[i]
inspect c
when ':' then
when '-', 'a' .. 'z', 'A' .. 'Z' then
s.extend (c)
else
s := Void
end
i := i + 1
end
if s /= Void then
Result := [s, h.substring (i, n)]
end
end
feature {NONE} -- Implementation
append_line_to (s: READABLE_STRING_8; h: STRING_8)
do
h.append_string (s)
append_end_of_line_to (h)
end
append_end_of_line_to (h: STRING_8)
do
h.append_character ('%R')
h.append_character ('%N')
end
date_to_rfc1123_http_date_format (dt: DATE_TIME): STRING_8
-- String representation of `dt' using the RFC 1123
do
Result := dt.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT"
end
feature {NONE} -- Constants
str_binary: STRING = "binary"
str_chunked: STRING = "chunked"
colon_space: STRING = ": "
semi_colon_space: STRING = "; "
note
copyright: "2011-2012, Jocelyn Fiat, 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,260 @@
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_status: STRING = "Status"
-- CGI program can use this to return the HTTP status code to the client.
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-2012, Jocelyn Fiat, 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,346 @@
note
description: "[
This class is to represent a media type
the Internet Media Type [9] of the attached entity if the type
was provided via a "Content-type" field in the wgi_request header,
or if the server can determine it in the absence of a supplied
"Content-type" field. The syntax is the same as for the HTTP
"Content-Type" header field.
CONTENT_TYPE = "" | media-type
media-type = type "/" subtype *( ";" parameter)
type = token
subtype = token
parameter = attribute "=" value
attribute = token
value = token | quoted-string
The type, subtype, and parameter attribute names are not
case-sensitive. Parameter values MAY be case sensitive. Media
types and their use in HTTP are described in section 3.7 of
the HTTP/1.1 specification [8].
Example:
application/x-www-form-urlencoded
application/x-www-form-urlencoded; charset=UTF8
]"
date: "$Date$"
revision: "$Revision$"
class
HTTP_MEDIA_TYPE
inherit
DEBUG_OUTPUT
create
make,
make_from_string
feature {NONE} -- Initialization
make (a_type, a_subtype: READABLE_STRING_8)
-- Create Current based on `a_type/a_subtype'
require
not a_type.is_empty
not a_subtype.is_empty
do
type := a_type
subtype := a_subtype
ensure
has_no_error: not has_error
end
make_from_string (s: READABLE_STRING_8)
-- Create Current from `s'
-- if `s' does not respect the expected syntax, has_error is True
local
t: STRING_8
i,n: INTEGER
p: INTEGER
do
-- Ignore starting space (should not be any)
from
i := 1
n := s.count
until
i > n or not s[i].is_space
loop
i := i + 1
end
if i < n then
-- Look for semi colon as parameter separation
p := s.index_of (';', i)
if p > 0 then
t := s.substring (i, p - 1)
i := p + 1
p := s.index_of (';', i)
if p = 0 then
add_parameter_from_string (s, i, n)
i := n
else
add_parameter_from_string (s, i, p - 1)
i := p + 1
end
else
t := s.substring (i, n)
end
-- Remove eventual trailing space
t.right_adjust
-- Extract type and subtype
p := t.index_of ('/', 1)
if p = 0 then
has_error := True
type := t
subtype := ""
else
subtype := t.substring (p + 1, t.count)
type := t
t.keep_head (p - 1)
end
else
has_error := True
type := ""
subtype := type
end
ensure
not has_error implies (create {HTTP_CONTENT_TYPE}.make_from_string (string)).same_string (string)
end
feature -- Status report
has_error: BOOLEAN
-- Current has error?
--| Mainly in relation with `make_from_string'
feature -- Access
type: READABLE_STRING_8
-- Main type
subtype: READABLE_STRING_8
-- Sub type
has_parameter (a_name: READABLE_STRING_8): BOOLEAN
-- Has Current a parameter?
do
if attached parameters as plst then
Result := plst.has (a_name)
end
end
parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
-- Value for eventual parameter named `a_name'.
do
if attached parameters as plst then
Result := plst.item (a_name)
end
end
parameters: detachable HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
-- Parameters
feature -- Conversion
string: READABLE_STRING_8
-- String representation of type/subtype; attribute=value
local
res: like internal_string
do
res := internal_string
if res = Void then
create res.make_from_string (simple_type)
if attached parameters as plst then
across
plst as p
loop
res.append_character (';')
res.append_character (' ')
res.append (p.key)
res.append_character ('=')
res.append_character ('%"')
res.append (p.item)
res.append_character ('%"')
end
end
internal_string := res
end
Result := res
end
simple_type: READABLE_STRING_8
-- String representation of type/subtype
local
res: like internal_simple_type
s: like subtype
do
res := internal_simple_type
if res = Void then
create res.make_from_string (type)
s := subtype
if not s.is_empty then
check has_error: has_error end
-- Just in case not is_valid, we keep in `type' the original string
res.append_character ('/')
res.append (s)
end
internal_simple_type := res
end
Result := res
end
feature -- Status report
same_as (other: HTTP_CONTENT_TYPE): BOOLEAN
-- Current has same type/subtype and parameters as `other'?
local
plst,oplst: like parameters
do
Result := other.type.same_string (other.type) and then
other.subtype.same_string (other.subtype)
if Result then
plst := parameters
oplst := other.parameters
if plst = oplst then
elseif plst = Void then
Result := False -- since oplst /= Void
elseif oplst /= Void and then plst.count = oplst.count then
across
plst as p
until
not Result
loop
Result := attached oplst.item (p.key) as op_value and then p.item.same_string (op_value)
end
else
Result := False
end
end
end
same_simple_type (s: READABLE_STRING_8): BOOLEAN
-- Current has same type/subtype string representation as `s'?
do
Result := simple_type.same_string (s)
end
same_string (s: READABLE_STRING_8): BOOLEAN
-- Current has same string representation as `s'?
do
Result := string.same_string (s)
end
feature -- Element change
add_parameter (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8)
-- Set parameter for `a_name' to `a_value'
local
plst: like parameters
do
plst := parameters
if plst = Void then
create plst.make (1)
parameters := plst
end
plst.force (a_value, a_name)
internal_string := Void
end
remove_parameter (a_name: READABLE_STRING_8)
-- Remove parameter named `a_name'
do
if attached parameters as plst then
plst.prune (a_name)
if plst.is_empty then
parameters := Void
end
end
internal_string := Void
end
feature {NONE} -- Implementation
add_parameter_from_string (s: READABLE_STRING_8; start_index, end_index: INTEGER)
-- Add parameter from string " attribute=value "
local
pn,pv: STRING_8
i: INTEGER
p: INTEGER
err: BOOLEAN
do
-- Skip spaces
from
i := start_index
until
i > end_index or not s[i].is_space
loop
i := i + 1
end
if i < end_index then
p := s.index_of ('=', i)
if p > 0 and p < end_index then
pn := s.substring (i, p - 1)
pv := s.substring (p + 1, end_index)
pv.right_adjust
if pv.count > 0 and pv [1] = '%"' then
if pv [pv.count] = '%"' then
pv := pv.substring (2, pv.count - 1)
else
err := True
-- missing closing double quote.
end
end
if not err then
add_parameter (pn, pv)
end
else
-- expecting: attribute "=" value
err := True
end
end
has_error := has_error or err
end
feature {NONE} -- Internal
internal_string: detachable STRING_8
internal_simple_type: detachable STRING_8
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
if type /= Void and subtype /= Void then
Result := type + "/" + subtype
if attached parameters as plst then
across
plst as p
loop
Result.append ("; " + p.key + "=" + "%"" + p.item + "%"")
end
end
else
Result := ""
end
end
invariant
type_and_subtype_not_empty: not has_error implies not type.is_empty and not subtype.is_empty
note
copyright: "2011-2012, Jocelyn Fiat, 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,185 @@
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_force_download: STRING = "application/force-download"
application_javascript: STRING = "application/javascript"
-- JavaScript application content-type header
application_json: STRING = "application/json"
-- JSON application content-type header
application_octet_stream: STRING = "application/octet-stream"
-- Octet stream content-type header
application_pdf: STRING = "application/pdf"
-- pdf application content-type header
application_postscript: STRING = "application/postscript"
-- postscript application content-type header
application_rss_xml: STRING = "application/rss+xml"
-- rss application content-type header
application_rtf: STRING = "application/rtf"
-- RTF application content-type header
application_xml: STRING = "application/xml"
-- xml application content-type header
application_x_shockwave_flash: STRING = "application/x-shockwave-flash"
application_x_compressed: STRING = "application/x-compressed"
application_x_gzip: STRING = "application/x-gzip"
application_zip: STRING = "application/zip"
application_x_bzip: STRING = "application/x-bzip"
application_x_bzip2: STRING = "application/x-bzip2"
application_x_tar: STRING = "application/x-tar"
application_x_www_form_encoded: STRING = "application/x-www-form-urlencoded"
-- Starting chars of form url-encoded data content-type header
feature -- Content type : audio
audio_mpeg3: STRING = "audio/mpeg3"
audio_mpeg: STRING = "audio/mpeg"
audio_wav: STRING = "audio/wav"
feature -- Content type : image
image_bmp: STRING = "image/bmp"
-- BMP image content-type header
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
image_tiff: STRING = "image/tiff"
-- TIFF image content-type header
image_x_ico: STRING = "image/x-ico"
-- ICO 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
model_vrml: STRING = "model/vrml"
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"
multipart_x_gzip: STRING = "multipart/x-gzip"
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_tab_separated_values: STRING = "text/tab-separated-values"
-- TSV text 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
video_avi: STRING = "video/avi"
video_quicktime: STRING = "video/quicktime"
video_x_motion_jpeg: STRING = "video/x-motion-jpeg"
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,94 @@
note
description: "Summary description for {HTTP_REQUEST_METHOD_CONSTANTS}."
date: "$Date$"
revision: "$Revision$"
class
HTTP_REQUEST_METHOD_CONSTANTS
inherit
HTTP_REQUEST_METHODS
feature -- Id
head: INTEGER = 0x1
get: INTEGER = 0x2
trace: INTEGER = 0x4
options: INTEGER = 0x8
post: INTEGER = 0x10
put: INTEGER = 0x20
delete: INTEGER = 0x40
connect: INTEGER = 0x80
patch: INTEGER = 0x100
feature -- Name
method_empty: STRING = ""
feature -- Query
method_id (a_id: STRING): INTEGER
local
s: STRING
do
s := a_id.as_lower
if s.same_string (method_get) then
Result := get
elseif s.same_string (method_post) then
Result := post
elseif s.same_string (method_put) then
Result := put
elseif s.same_string (method_patch) then
Result := patch
elseif s.same_string (method_delete) then
Result := delete
elseif s.same_string (method_head) then
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
method_name (a_id: INTEGER): STRING
do
inspect a_id
when head then Result := method_head
when get then Result := method_get
when trace then Result := method_trace
when options then Result := method_options
when post then Result := method_post
when put then Result := method_put
when patch then Result := method_patch
when delete then Result := method_delete
when connect then Result := method_connect
else
Result := method_empty
end
ensure
result_is_upper_case: Result /= Void and then Result.as_upper ~ Result
end
note
copyright: "2011-2011, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,104 @@
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 -- Query
method (m: READABLE_STRING_8): READABLE_STRING_8
-- Return the associated constant object if any
-- otherwise the uppercased version of `m'
do
if m.is_case_insensitive_equal (method_get) then
Result := method_get
elseif m.is_case_insensitive_equal (method_post) then
Result := method_post
elseif m.is_case_insensitive_equal (method_head) then
Result := method_head
elseif m.is_case_insensitive_equal (method_trace) then
Result := method_trace
elseif m.is_case_insensitive_equal (method_options) then
Result := method_options
elseif m.is_case_insensitive_equal (method_put) then
Result := method_put
elseif m.is_case_insensitive_equal (method_delete) then
Result := method_delete
elseif m.is_case_insensitive_equal (method_connect) then
Result := method_connect
elseif m.is_case_insensitive_equal (method_patch) then
Result := method_patch
else
Result := m.as_upper
end
end
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-2012, Jocelyn Fiat, 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,106 @@
note
description: "[
Status code constants pertaining to the HTTP protocol
See http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTTP_STATUS_CODE
feature -- 1xx : Informational
continue: INTEGER = 100
switching_protocols: INTEGER = 101
processing: INTEGER = 102 -- WebDAV RFC 2518
ie7_request_uri_too_long: INTEGER = 122 -- non standard, IE7 only
feature -- 2xx : Success
ok: INTEGER = 200
created: INTEGER = 201
accepted: INTEGER = 202
nonauthoritative_info: INTEGER = 203
no_content: INTEGER = 204
reset_content: INTEGER = 205
partial_content: INTEGER = 206
multistatus: INTEGER = 207 -- WebDAV RFC 4918
im_used: INTEGER = 226 -- RFC 4918
feature -- 3xx : Redirection
multiple_choices: INTEGER = 300
moved_permanently: INTEGER = 301
found: INTEGER = 302
see_other: INTEGER = 303
not_modified: INTEGER = 304
use_proxy: INTEGER = 305
switch_proxy: INTEGER = 306
temp_redirect: INTEGER = 307
feature -- 4xx : Client Error
bad_request: INTEGER = 400
unauthorized: INTEGER = 401
payment_required: INTEGER = 402
forbidden: INTEGER = 403
not_found: INTEGER = 404
method_not_allowed: INTEGER = 405
not_acceptable: INTEGER = 406
proxy_auth_required: INTEGER = 407
request_timeout: INTEGER = 408
conflict: INTEGER = 409
gone: INTEGER = 410
length_required: INTEGER = 411
precondition_failed: INTEGER = 412
request_entity_too_large: INTEGER = 413
request_uri_too_long: INTEGER = 414
unsupported_media_type: INTEGER = 415
request_range_not_satisfiable: INTEGER = 416
expectation_failed: INTEGER = 417
teapot: INTEGER = 418
feature -- 4xx : Client Error : WebDAV errors
too_many_connections: INTEGER = 421
unprocessable_entity: INTEGER = 422
locked: INTEGER = 423
failed_dependency: INTEGER = 424
unordered_collection: INTEGER = 425
upgrade_required: INTEGER = 426
no_response: INTEGER = 444
retry_with: INTEGER = 449
blocked_parental: INTEGER = 450
client_closed_request: INTEGER = 499
feature -- 5xx : Server Error
internal_server_error: INTEGER = 500
not_implemented: INTEGER = 501
bad_gateway: INTEGER = 502
service_unavailable: INTEGER = 503
gateway_timeout: INTEGER = 504
http_version_not_supported: INTEGER = 505
variant_also_negotiates: INTEGER = 506
insufficient_storage: INTEGER = 507 -- WebDAV RFC 4918
bandwidth_limit_exceeded: INTEGER = 509
not_extended: INTEGER = 510
user_access_denied: INTEGER = 530
note
copyright: "2011-2012, Jocelyn Fiat, 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,160 @@
note
description: "[
Status code constants pertaining to the HTTP protocol
See http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
]"
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
HTTP_STATUS_CODE_MESSAGES
inherit
HTTP_STATUS_CODE
feature -- Status report
is_valid_http_status_code (v: INTEGER): BOOLEAN
-- Is the given value a valid http status code?
do
Result := v >= continue and v <= user_access_denied
end
feature -- Status messages
http_status_code_message (a_code: INTEGER): detachable STRING
-- Header message related to HTTP status code `a_code'
do
inspect a_code
when continue then
Result := "Continue"
when switching_protocols then
Result := "Switching Protocols"
when processing then
Result := "Processing"
when ok then
Result := "OK"
when created then
Result := "Created"
when accepted then
Result := "Accepted"
when nonauthoritative_info then
Result := "Non-Authoritative Information"
when no_content then
Result := "No Content"
when reset_content then
Result := "Reset Content"
when partial_content then
Result := "Partial Content"
when multistatus then
Result := "Multi-Status"
when multiple_choices then
Result := "Multiple Choices"
when moved_permanently then
Result := "Moved Permanently"
when found then
Result := "Found"
when see_other then
Result := "See Other"
when not_modified then
Result := "Not Modified"
when use_proxy then
Result := "Use Proxy"
when switch_proxy then
Result := "Switch Proxy"
when temp_redirect then
Result := "Temporary Redirect"
when bad_request then
Result := "Bad Request"
when unauthorized then
Result := "Unauthorized"
when payment_required then
Result := "Payment Required"
when forbidden then
Result := "Forbidden"
when not_found then
Result := "Not Found"
when method_not_allowed then
Result := "Method Not Allowed"
when not_acceptable then
Result := "Not Acceptable"
when proxy_auth_required then
Result := "Proxy Authentication Required"
when request_timeout then
Result := "Request Timeout"
when conflict then
Result := "Conflict"
when gone then
Result := "Gone"
when length_required then
Result := "Length Required"
when precondition_failed then
Result := "Precondition Failed"
when request_entity_too_large then
Result := "Request Entity Too Large"
when request_uri_too_long then
Result := "Request-URI Too Long"
when unsupported_media_type then
Result := "Unsupported Media Type"
when request_range_not_satisfiable then
Result := "Requested Range Not Satisfiable"
when expectation_failed then
Result := "Expectation Failed"
when teapot then
Result := "I'm a teapot"
when too_many_connections then
Result := "There are too many connections from your internet address"
when unprocessable_entity then
Result := "Unprocessable Entity"
when locked then
Result := "Locked"
when failed_dependency then
Result := "Failed Dependency"
when unordered_collection then
Result := "Unordered Collection"
when upgrade_required then
Result := "Upgrade Required"
when retry_with then
Result := "Retry With"
when blocked_parental then
Result := "Blocked by Windows Parental Controls"
when internal_server_error then
Result := "Internal Server Error"
when not_implemented then
Result := "Not Implemented"
when bad_gateway then
Result := "Bad Gateway"
when service_unavailable then
Result := "Service Unavailable"
when gateway_timeout then
Result := "Gateway Timeout"
when http_version_not_supported then
Result := "HTTP Version Not Supported"
when variant_also_negotiates then
Result := "Variant Also Negotiates"
when insufficient_storage then
Result := "Insufficient Storage"
when bandwidth_limit_exceeded then
Result := "Bandwidth Limit Exceeded"
when not_extended then
Result := "Not Extended"
when user_access_denied then
Result := "User access denied"
else
Result := Void
end
end
note
copyright: "2011-2012, Jocelyn Fiat, 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