diff --git a/library/protocol/http/src/http_content_type.e b/library/protocol/http/src/http_content_type.e
new file mode 100644
index 00000000..f8069818
--- /dev/null
+++ b/library/protocol/http/src/http_content_type.e
@@ -0,0 +1,318 @@
+note
+ description: "[
+ CGI Meta variable define the CONTENT_TYPE entity
+ This class is to represent it as an object
+
+ 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_CONTENT_TYPE
+
+inherit
+ DEBUG_OUTPUT
+
+create
+ make,
+ make_from_content_type_header
+
+convert
+ make_from_content_type_header ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
+ string: {READABLE_STRING_8}
+
+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_content_type_header (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
+ pn,pv: STRING_8
+ 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)
+ -- Skip eventual space
+ i := p + 1
+ from
+ until
+ i > n or not s[i].is_space
+ loop
+ i := i + 1
+ end
+ if i < n then
+ p := s.index_of ('=', i)
+ if p > 0 then
+ pn := s.substring (i, p - 1)
+ pv := s.substring (p + 1, n)
+ pv.right_adjust
+ if pv.count > 0 and pv [1] = '%"' then
+ if pv [pv.count] = '%"' then
+ pv := pv.substring (2, pv.count - 1)
+ else
+ has_error := True
+ -- missing closing double quote.
+ end
+ end
+ if not has_error then
+ set_parameter (pn, pv)
+ end
+ else
+ -- expecting: attribute "=" value
+ has_error := True
+ end
+ 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_content_type_header (string)).same_string (string)
+ end
+
+feature -- Access
+
+ has_error: BOOLEAN
+ -- Current has error?
+ --| Mainly in relation with `make_from_content_type_header'
+
+ type: READABLE_STRING_8
+ -- Main type
+
+ subtype: READABLE_STRING_8
+ -- Sub type
+
+ has_parameter: BOOLEAN
+ -- Has Current a parameter?
+ do
+ Result := parameter_information /= Void
+ end
+
+ parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
+ -- Value for eventual parameter named `a_name'.
+ do
+ if has_parameter and then parameter_name.same_string (a_name) then
+ Result := parameter_value
+ end
+ end
+
+ parameter_name: READABLE_STRING_8
+ -- Parameter's name if any.
+ require
+ has_parameter: has_parameter
+ do
+ if attached parameter_information as l_info then
+ Result := l_info.name
+ else
+ Result := ""
+ check has_parameter: False end
+ end
+ end
+
+ parameter_value: READABLE_STRING_8
+ -- Parameter's value if any.
+ require
+ has_parameter: has_parameter
+ do
+ if attached parameter_information as l_info then
+ Result := l_info.value
+ else
+ Result := ""
+ check has_parameter: False end
+ end
+ end
+
+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 (type_and_subtype_string)
+ if has_parameter then
+ res.append_character (';')
+ res.append_character (' ')
+ res.append (parameter_name)
+ res.append_character ('=')
+ res.append_character ('%"')
+ res.append (parameter_value)
+ res.append_character ('%"')
+ end
+ internal_string := res
+ end
+ Result := res
+ end
+
+ type_and_subtype_string: READABLE_STRING_8
+ -- String representation of type/subtype
+ local
+ res: like internal_type_and_subtype_string
+ s: like subtype
+ do
+ res := internal_type_and_subtype_string
+ 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_type_and_subtype_string := res
+ end
+ Result := res
+ end
+
+feature {NONE} -- Internal
+
+ internal_string: detachable STRING_8
+
+ internal_type_and_subtype_string: detachable STRING_8
+
+feature -- Status report
+
+ same_as (other: HTTP_CONTENT_TYPE): BOOLEAN
+ do
+ Result := other.type.same_string (other.type) and then
+ other.subtype.same_string (other.subtype)
+ if Result then
+ Result := has_parameter = other.has_parameter
+ if has_parameter then
+ Result := parameter_name.same_string (other.parameter_name) and then
+ parameter_value.same_string (other.parameter_value)
+ end
+ end
+ end
+
+ same_type_and_subtype (s: READABLE_STRING_8): BOOLEAN
+ do
+ Result := type_and_subtype_string.same_string (s)
+ end
+
+ same_string (s: READABLE_STRING_8): BOOLEAN
+ do
+ Result := string.same_string (s)
+ end
+
+feature -- Element change
+
+ set_parameter (a_name: like parameter_name; a_value: like parameter_value)
+ -- Set parameter for `a_name' to `a_value'
+ do
+ parameter_information := [a_name, a_value]
+ internal_string := Void
+ end
+
+ remove_parameter
+ -- Remove parameter
+ do
+ parameter_information := Void
+ internal_string := Void
+ end
+
+feature {NONE} -- Implementation
+
+ parameter_information: detachable TUPLE [name: READABLE_STRING_8; value: READABLE_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 parameter_information as p_info then
+ Result.append ("; " + p_info.name + "=" + "%"" + p_info.value + "%"")
+ end
+ else
+ Result := ""
+ end
+ end
+
+invariant
+ has_parameter implies parameter_name /= Void and parameter_value /= Void
+ 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
diff --git a/library/protocol/http/src/http_header.e b/library/protocol/http/src/http_header.e
index c2f59d59..d78e63f3 100644
--- a/library/protocol/http/src/http_header.e
+++ b/library/protocol/http/src/http_header.e
@@ -28,7 +28,8 @@ create
make,
make_with_count,
make_from_array,
- make_from_header
+ make_from_header,
+ make_from_raw_header_data
convert
make_from_array ({ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]]}),
@@ -66,6 +67,27 @@ feature {NONE} -- Initialization
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
@@ -100,6 +122,21 @@ feature -- Access
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]])
@@ -141,7 +178,7 @@ feature -- Header change: general
require
h_not_empty: not h.is_empty
do
- force_header_by_name (header_name (h), h)
+ force_header_by_name (header_name_colon (h), h)
end
add_header_key_value (k,v: READABLE_STRING_8)
@@ -529,7 +566,7 @@ 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 (h) as hn) implies n.same_string (hn)
+ 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
@@ -552,7 +589,7 @@ feature {NONE} -- Implementation: Header
end
end
- header_name (h: READABLE_STRING_8): detachable READABLE_STRING_8
+ 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
@@ -581,6 +618,36 @@ feature {NONE} -- Implementation: Header
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)
@@ -595,7 +662,7 @@ feature {NONE} -- Implementation
h.append_character ('%N')
end
- date_to_rfc1123_http_date_format (dt: DATE_TIME): READABLE_STRING_8
+ 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"
diff --git a/library/server/ewsgi/connectors/null/src/wgi_null_file_input_stream.e b/library/server/ewsgi/connectors/null/src/wgi_null_file_input_stream.e
new file mode 100644
index 00000000..6e0282f0
--- /dev/null
+++ b/library/server/ewsgi/connectors/null/src/wgi_null_file_input_stream.e
@@ -0,0 +1,89 @@
+note
+ description: "Summary description for WGI_NULL_FILE_INPUT_STREAM."
+ legal: "See notice at end of class."
+ status: "See notice at end of class."
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ WGI_NULL_FILE_INPUT_STREAM
+
+inherit
+ WGI_NULL_INPUT_STREAM
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (f: FILE)
+ do
+ file := f
+ end
+
+ file: FILE
+
+feature -- Input
+
+ read_character
+ -- Read the next character in input stream.
+ -- Make the result available in `last_character'
+ do
+ file.read_character
+ end
+
+ read_string (nb: INTEGER)
+ -- Read the next `nb' characters and
+ -- make the string result available in `last_string'
+ do
+ file.read_stream (nb)
+ end
+
+feature -- Access
+
+ last_string: STRING_8
+ -- Last string read.
+ --
+ -- Note: this query *might* return the same object.
+ -- Therefore a clone should be used if the result
+ -- is to be kept beyond the next call to this feature.
+ -- However `last_string' is not shared between file objects.)
+ do
+ Result := file.last_string
+ end
+
+ last_character: CHARACTER_8
+ -- Last item read.
+ do
+ Result := file.last_character
+ end
+
+feature -- Status report
+
+ is_open_read: BOOLEAN
+ -- Can items be read from input stream?
+ do
+ Result := file.is_open_read
+ end
+
+ end_of_input: BOOLEAN
+ -- Has the end of input stream been reached?
+ do
+ Result := file.end_of_file
+ end
+
+
+invariant
+
+
+note
+ copyright: "2011-2012, 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
diff --git a/library/server/ewsgi/connectors/null/src/wgi_null_input_stream.e b/library/server/ewsgi/connectors/null/src/wgi_null_input_stream.e
index 75fdbd0c..93461b24 100644
--- a/library/server/ewsgi/connectors/null/src/wgi_null_input_stream.e
+++ b/library/server/ewsgi/connectors/null/src/wgi_null_input_stream.e
@@ -5,31 +5,12 @@ note
date: "$Date$"
revision: "$Revision$"
-class
+deferred class
WGI_NULL_INPUT_STREAM
inherit
WGI_INPUT_STREAM
- undefine
- read_to_string
- end
- CONSOLE
- rename
- make as console_make,
- read_stream as read_string,
- end_of_file as end_of_input
- end
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make
- do
- make_open_stdin ("stdin")
- end
note
copyright: "2011-2011, Eiffel Software and others"
diff --git a/library/server/ewsgi/connectors/null/src/wgi_null_string_input_stream.e b/library/server/ewsgi/connectors/null/src/wgi_null_string_input_stream.e
new file mode 100644
index 00000000..09df2d2e
--- /dev/null
+++ b/library/server/ewsgi/connectors/null/src/wgi_null_string_input_stream.e
@@ -0,0 +1,86 @@
+note
+ description: "Summary description for WGI_NULL_STRING_INPUT_STREAM."
+ legal: "See notice at end of class."
+ status: "See notice at end of class."
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ WGI_NULL_STRING_INPUT_STREAM
+
+inherit
+ WGI_NULL_INPUT_STREAM
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (s: READABLE_STRING_8)
+ do
+ body := s
+ index := 1
+ count := s.count
+ last_string := ""
+ end
+
+ body: READABLE_STRING_8
+
+ index: INTEGER
+
+ count: INTEGER
+
+feature -- Input
+
+ read_character
+ -- Read the next character in input stream.
+ -- Make the result available in `last_character'
+ do
+ last_character := body[index]
+ index := index + 1
+ end
+
+ read_string (nb: INTEGER)
+ -- Read the next `nb' characters and
+ -- make the string result available in `last_string'
+ local
+ e: INTEGER
+ do
+ e := (index + nb).min (count)
+ last_string := body.substring (index, e)
+ index := e + 1
+ end
+
+feature -- Access
+
+ last_string: STRING_8
+
+ last_character: CHARACTER_8
+
+feature -- Status report
+
+ is_open_read: BOOLEAN
+ -- Can items be read from input stream?
+ do
+ Result := True
+ end
+
+ end_of_input: BOOLEAN
+ -- Has the end of input stream been reached?
+ do
+ Result := index > count
+ end
+
+invariant
+
+note
+ copyright: "2011-2012, 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
diff --git a/library/server/wsf/src/mime/wsf_application_x_www_form_urlencoded_handler.e b/library/server/wsf/src/mime/wsf_application_x_www_form_urlencoded_handler.e
index d8d9bcb8..325e1151 100644
--- a/library/server/wsf/src/mime/wsf_application_x_www_form_urlencoded_handler.e
+++ b/library/server/wsf/src/mime/wsf_application_x_www_form_urlencoded_handler.e
@@ -14,14 +14,14 @@ inherit
feature -- Status report
- valid_content_type (a_content_type: READABLE_STRING_8): BOOLEAN
+ valid_content_type (a_content_type: HTTP_CONTENT_TYPE): BOOLEAN
do
- Result := a_content_type.same_string ({HTTP_MIME_TYPES}.application_x_www_form_encoded)
+ Result := a_content_type.same_type_and_subtype ({HTTP_MIME_TYPES}.application_x_www_form_encoded)
end
feature -- Execution
- handle (a_content_type: READABLE_STRING_8; req: WSF_REQUEST;
+ handle (a_content_type: HTTP_CONTENT_TYPE; req: WSF_REQUEST;
a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8])
local
l_content: READABLE_STRING_8
diff --git a/library/server/wsf/src/mime/wsf_mime_handler.e b/library/server/wsf/src/mime/wsf_mime_handler.e
index c1125f4a..af3b2470 100644
--- a/library/server/wsf/src/mime/wsf_mime_handler.e
+++ b/library/server/wsf/src/mime/wsf_mime_handler.e
@@ -9,13 +9,13 @@ deferred class
feature -- Status report
- valid_content_type (a_content_type: READABLE_STRING_8): BOOLEAN
+ valid_content_type (a_content_type: HTTP_CONTENT_TYPE): BOOLEAN
deferred
end
feature -- Execution
- handle (a_content_type: READABLE_STRING_8; req: WSF_REQUEST;
+ handle (a_content_type: HTTP_CONTENT_TYPE; req: WSF_REQUEST;
a_vars: TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8])
-- Handle MIME content from request `req', eventually fill the `a_vars' (not yet available from `req')
-- and if `a_raw_data' is attached, store any read data inside `a_raw_data'
diff --git a/library/server/wsf/src/mime/wsf_multipart_form_data_handler.e b/library/server/wsf/src/mime/wsf_multipart_form_data_handler.e
index 21a18dac..9861208f 100644
--- a/library/server/wsf/src/mime/wsf_multipart_form_data_handler.e
+++ b/library/server/wsf/src/mime/wsf_multipart_form_data_handler.e
@@ -17,33 +17,21 @@ create
feature {NONE} -- Initialization
- make (a_err_handler: like error_handler)
+ make
-- Instantiate Current
do
- error_handler := a_err_handler
end
-feature -- Error handling
-
- has_error: BOOLEAN
- do
- Result := error_handler.has_error
- end
-
- error_handler: ERROR_HANDLER
- -- Error handler
- -- By default initialized to new handler
-
feature -- Status report
- valid_content_type (a_content_type: READABLE_STRING_8): BOOLEAN
+ valid_content_type (a_content_type: HTTP_CONTENT_TYPE): BOOLEAN
do
- Result := a_content_type.starts_with ({HTTP_MIME_TYPES}.multipart_form_data)
+ Result := a_content_type.same_type_and_subtype ({HTTP_MIME_TYPES}.multipart_form_data)
end
feature -- Execution
- handle (a_content_type: READABLE_STRING_8; req: WSF_REQUEST;
+ handle (a_content_type: HTTP_CONTENT_TYPE; req: WSF_REQUEST;
a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8])
local
s: like full_input_data
@@ -58,24 +46,23 @@ feature -- Execution
feature {NONE} -- Implementation: Form analyzer
- analyze_multipart_form (req: WSF_REQUEST; t: READABLE_STRING_8; s: READABLE_STRING_8; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32])
+ analyze_multipart_form (req: WSF_REQUEST; a_content_type: HTTP_CONTENT_TYPE; s: READABLE_STRING_8; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32])
-- Analyze multipart form content
--| FIXME[2011-06-21]: integrate eMIME parser library
require
- t_attached: t /= Void
+ a_content_type_valid: a_content_type /= Void and not a_content_type.has_error
s_attached: s /= Void
vars_attached: vars /= Void
local
p,i,next_b: INTEGER
l_boundary_prefix: STRING
- l_boundary: STRING
l_boundary_len: INTEGER
+ l_boundary: detachable READABLE_STRING_8
m: STRING
is_crlf: BOOLEAN
do
- p := t.substring_index ("boundary=", 1)
- if p > 0 then
- l_boundary := t.substring (p + 9, t.count)
+ l_boundary := a_content_type.parameter ("boundary")
+ if l_boundary /= Void then
p := s.substring_index (l_boundary, 1)
if p > 1 then
l_boundary_prefix := s.substring (1, p - 1)
@@ -116,7 +103,7 @@ feature {NONE} -- Implementation: Form analyzer
m := s.substring (i - 1, s.count)
m.right_adjust
if not l_boundary_prefix.same_string (m) then
- error_handler.add_custom_error (0, "Invalid form data", "Invalid ending for form data from input")
+ req.error_handler.add_custom_error (0, "Invalid form data", "Invalid ending for form data from input")
end
i := next_b
end
@@ -235,10 +222,10 @@ feature {NONE} -- Implementation: Form analyzer
add_string_value_to_table (l_name, l_content, vars)
end
else
- error_handler.add_custom_error (0, "unamed multipart entry", Void)
+ req.error_handler.add_custom_error (0, "unamed multipart entry", Void)
end
else
- error_handler.add_custom_error (0, "missformed multipart entry", Void)
+ req.error_handler.add_custom_error (0, "missformed multipart entry", Void)
end
end
diff --git a/library/server/wsf/src/support/wsf_header.e b/library/server/wsf/src/support/wsf_header.e
index d7336deb..41a96d06 100644
--- a/library/server/wsf/src/support/wsf_header.e
+++ b/library/server/wsf/src/support/wsf_header.e
@@ -22,15 +22,15 @@ note
class
WSF_HEADER
-obsolete "Use HTTP_HEADER [2011-nov-25]"
-
inherit
HTTP_HEADER
create
make,
- make_with_count
-
+ make_with_count,
+ make_from_array,
+ make_from_header,
+ make_from_raw_header_data
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e
index b2b4a4f5..fe2be820 100644
--- a/library/server/wsf/src/wsf_request.e
+++ b/library/server/wsf/src/wsf_request.e
@@ -77,6 +77,14 @@ feature {NONE} -- Initialization
content_length_value := 0
end
+ -- Content-Type
+ s8 := wgi_request.content_type
+ if s8 /= Void then
+ content_type := s8
+ else
+ content_type := Void
+ end
+
--| PATH_INFO
path_info := url_encoder.decoded_string (wgi_request.path_info)
@@ -396,7 +404,7 @@ feature -- Access: CGI meta parameters - 1.1
content_length_value: NATURAL_64
-- Integer value related to `content_length"
- content_type: detachable READABLE_STRING_8
+ content_type: detachable HTTP_CONTENT_TYPE
-- If the wgi_request includes a message-body, CONTENT_TYPE is set to
-- the Internet Media Type [9] of the attached entity if the type
-- was provided via a "Content-type" field in the wgi_request header,
@@ -436,9 +444,6 @@ feature -- Access: CGI meta parameters - 1.1
-- determine the correct datatype, or it MAY omit this
-- metavariable when communicating the wgi_request information to the
-- script.
- do
- Result := wgi_request.content_type
- end
gateway_interface: READABLE_STRING_8
-- This metavariable is set to the dialect of CGI being used by
@@ -1145,7 +1150,7 @@ feature -- Access: MIME handler
hdls.force (a_handler)
end
- mime_handler (a_content_type: READABLE_STRING_8): detachable WSF_MIME_HANDLER
+ mime_handler (a_content_type: HTTP_CONTENT_TYPE): detachable WSF_MIME_HANDLER
-- Mime handler associated with `a_content_type'
do
if attached mime_handlers as hdls then
@@ -1169,7 +1174,7 @@ feature {NONE} -- Implementation: MIME handler
init_mime_handlers
do
- register_mime_handler (create {WSF_MULTIPART_FORM_DATA_HANDLER}.make (error_handler))
+ register_mime_handler (create {WSF_MULTIPART_FORM_DATA_HANDLER}.make)
register_mime_handler (create {WSF_APPLICATION_X_WWW_FORM_URLENCODED_HANDLER})
end
@@ -1566,7 +1571,7 @@ feature {NONE} -- Implementation: utilities
invariant
empty_string_unchanged: empty_string.is_empty
-
+ wgi_request.content_type /= Void implies content_type /= Void
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
diff --git a/library/server/wsf/tests/src/test_wsf_request_mime_handler.e b/library/server/wsf/tests/src/test_wsf_request_mime_handler.e
new file mode 100644
index 00000000..f9a88668
--- /dev/null
+++ b/library/server/wsf/tests/src/test_wsf_request_mime_handler.e
@@ -0,0 +1,118 @@
+note
+ description: "[
+ Eiffel tests that can be executed by testing tool.
+ ]"
+ author: "EiffelStudio test wizard"
+ date: "$Date$"
+ revision: "$Revision$"
+ testing: "type/manual"
+
+class
+ TEST_WSF_REQUEST_MIME_HANDLER
+
+inherit
+ EQA_TEST_SET
+
+ WSF_SERVICE
+ undefine
+ default_create
+ end
+
+feature {NONE} -- Events
+
+ port_number: INTEGER
+ base_url: detachable STRING
+
+feature -- Execution
+
+ execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ do
+ --| do nothing
+ end
+
+feature -- Tests
+
+ test_mime_handler
+ local
+ req: WSF_REQUEST
+ b: STRING_8
+ h: WSF_HEADER
+ ct: HTTP_CONTENT_TYPE
+ m: ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]
+ do
+ m := <<
+ ["REQUEST_METHOD", "GET"],
+ ["QUERY_STRING", ""],
+ ["REQUEST_URI", "/auto/test/foo"],
+ ["SCRIPT_NAME", "/auto/test/test.ews"],
+ ["PATH_INFO", "/foo"]
+ >>
+
+ create ct.make_from_content_type_header ({HTTP_MIME_TYPES}.multipart_form_data)
+ ct.set_parameter ("boundary", "__=_the_boundary_1332296477_1804289383_=__")
+ create h.make
+ h.put_content_type (ct)
+
+ b := "[
+--__=_the_boundary_1332296477_1804289383_=__
+Content-Disposition: form-data; name="user_name"
+
+EWFdemo
+--__=_the_boundary_1332296477_1804289383_=__
+Content-Disposition: form-data; name="password"
+
+EWFpassword
+--__=_the_boundary_1332296477_1804289383_=__--
+]"
+
+ h.put_content_length (b.count)
+
+ --| Case #1
+ req := new_request (m, h.string, b)
+ assert ("found user_name", attached req.form_parameter ("user_name") as u and then u.same_string ("EWFdemo"))
+ assert ("found password", attached req.form_parameter ("password") as u and then u.same_string ("EWFpassword"))
+ end
+
+feature {NONE} -- Implementation
+
+ new_request (a_meta: ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]; h: READABLE_STRING_8; s: READABLE_STRING_8): WSF_REQUEST_NULL
+ local
+ wgi_req: WGI_REQUEST
+ l_header: WSF_HEADER
+ lst: ARRAYED_LIST [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]
+ vn: STRING_8
+ do
+ create lst.make (10)
+ across
+ a_meta as c
+ loop
+ lst.extend (c.item)
+ end
+
+ create l_header.make_from_raw_header_data (h)
+ across
+ l_header.to_name_value_iterable as c
+ loop
+ --| for Any Abc-Def-Ghi add (or replace) the HTTP_ABC_DEF_GHI variable to `env'
+ vn := c.item.name.as_upper
+
+ vn.replace_substring_all ("-", "_")
+ if
+ vn.starts_with ("CONTENT_") and then
+ (vn.same_string_general ({WGI_META_NAMES}.content_type) or vn.same_string_general ({WGI_META_NAMES}.content_length))
+ then
+ --| Keep this name
+ else
+ vn.prepend ("HTTP_")
+ end
+ lst.extend ([vn, c.item.value])
+-- lst.extend (c.item)
+ end
+
+ create {WGI_REQUEST_NULL} wgi_req.make_with_body (lst, s)
+ create Result.make_from_wgi (wgi_req)
+ end
+
+end
+
+
diff --git a/library/server/wsf/tests/src/test_wsf_request_script_url.e b/library/server/wsf/tests/src/test_wsf_request_script_url.e
index 11928265..5a97ca86 100644
--- a/library/server/wsf/tests/src/test_wsf_request_script_url.e
+++ b/library/server/wsf/tests/src/test_wsf_request_script_url.e
@@ -81,7 +81,7 @@ feature {NONE} -- Implementation
local
wgi_req: WGI_REQUEST
do
- create {WGI_REQUEST_NULL} wgi_req.make (a_meta)
+ create {WGI_REQUEST_NULL} wgi_req.make_with_file (a_meta, io.input)
create Result.make_from_wgi (wgi_req)
end
diff --git a/library/server/wsf/tests/src/wgi_request_null.e b/library/server/wsf/tests/src/wgi_request_null.e
index c823fc09..3313d87d 100644
--- a/library/server/wsf/tests/src/wgi_request_null.e
+++ b/library/server/wsf/tests/src/wgi_request_null.e
@@ -14,19 +14,20 @@ inherit
end
create
- make
+ make_with_file,
+ make_with_body
feature {NONE} -- Initialization
- make (a_meta: ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
+ make_with_file (a_meta: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]; f: FILE)
local
ht: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
- i: WGI_NULL_INPUT_STREAM
+ i: WGI_NULL_FILE_INPUT_STREAM
c: WGI_NULL_CONNECTOR
do
create c.make
- create i.make
- create ht.make (a_meta.count)
+ create i.make (f)
+ create ht.make (10)
across
a_meta as curs
loop
@@ -35,6 +36,22 @@ feature {NONE} -- Initialization
wgi_request_from_table_make (ht, i, c)
end
+ make_with_body (a_meta: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]; s: READABLE_STRING_8)
+ local
+ ht: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
+ i: WGI_NULL_STRING_INPUT_STREAM
+ c: WGI_NULL_CONNECTOR
+ do
+ create c.make
+ create i.make (s)
+ create ht.make (10)
+ across
+ a_meta as curs
+ loop
+ ht.force (curs.item.value, curs.item.name)
+ end
+ wgi_request_from_table_make (ht, i, c)
+ end
note
copyright: "2011-2011, Eiffel Software and others"
diff --git a/library/server/wsf/tests/tests-safe.ecf b/library/server/wsf/tests/tests-safe.ecf
index df2c4883..2f52e285 100644
--- a/library/server/wsf/tests/tests-safe.ecf
+++ b/library/server/wsf/tests/tests-safe.ecf
@@ -18,6 +18,7 @@
+