Change structure of EWF, to follow better categorization
This commit is contained in:
8
library/network/protocol/http/README.md
Normal file
8
library/network/protocol/http/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# HTTP library
|
||||
|
||||
## Overview
|
||||
|
||||
## Usage
|
||||
|
||||
## Examples
|
||||
|
||||
17
library/network/protocol/http/http-safe.ecf
Normal file
17
library/network/protocol/http/http-safe.ecf
Normal 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>
|
||||
18
library/network/protocol/http/http.ecf
Normal file
18
library/network/protocol/http/http.ecf
Normal 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>
|
||||
|
||||
10
library/network/protocol/http/license.lic
Normal file
10
library/network/protocol/http/license.lic
Normal 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
|
||||
]"
|
||||
48
library/network/protocol/http/src/http_constants.e
Normal file
48
library/network/protocol/http/src/http_constants.e
Normal 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
|
||||
46
library/network/protocol/http/src/http_content_type.e
Normal file
46
library/network/protocol/http/src/http_content_type.e
Normal 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
|
||||
71
library/network/protocol/http/src/http_date_time_utilities.e
Normal file
71
library/network/protocol/http/src/http_date_time_utilities.e
Normal 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
|
||||
@@ -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
|
||||
86
library/network/protocol/http/src/http_format_constants.e
Normal file
86
library/network/protocol/http/src/http_format_constants.e
Normal 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
|
||||
689
library/network/protocol/http/src/http_header.e
Normal file
689
library/network/protocol/http/src/http_header.e
Normal 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
|
||||
260
library/network/protocol/http/src/http_header_names.e
Normal file
260
library/network/protocol/http/src/http_header_names.e
Normal 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
|
||||
346
library/network/protocol/http/src/http_media_type.e
Normal file
346
library/network/protocol/http/src/http_media_type.e
Normal 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
|
||||
185
library/network/protocol/http/src/http_mime_types.e
Normal file
185
library/network/protocol/http/src/http_mime_types.e
Normal 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
|
||||
@@ -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
|
||||
104
library/network/protocol/http/src/http_request_methods.e
Normal file
104
library/network/protocol/http/src/http_request_methods.e
Normal 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
|
||||
106
library/network/protocol/http/src/http_status_code.e
Normal file
106
library/network/protocol/http/src/http_status_code.e
Normal 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
|
||||
160
library/network/protocol/http/src/http_status_code_messages.e
Normal file
160
library/network/protocol/http/src/http_status_code_messages.e
Normal 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
|
||||
Reference in New Issue
Block a user