Updating EWSGI specification classes
This commit is contained in:
@@ -18,5 +18,7 @@
|
|||||||
<cluster name="specification_request" location="specification\request" recursive="true"/>
|
<cluster name="specification_request" location="specification\request" recursive="true"/>
|
||||||
<cluster name="specification_response" location="specification\response" recursive="true"/>
|
<cluster name="specification_response" location="specification\response" recursive="true"/>
|
||||||
<cluster name="specification_connector" location="specification\connector" recursive="true"/>
|
<cluster name="specification_connector" location="specification\connector" recursive="true"/>
|
||||||
|
<cluster name="specification_service" location="specification\service" recursive="true"/>
|
||||||
|
<cluster name="specification_stream" location="specification\stream" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -18,5 +18,7 @@
|
|||||||
<cluster name="specification_request" location="specification\request" recursive="true"/>
|
<cluster name="specification_request" location="specification\request" recursive="true"/>
|
||||||
<cluster name="specification_response" location="specification\response" recursive="true"/>
|
<cluster name="specification_response" location="specification\response" recursive="true"/>
|
||||||
<cluster name="specification_connector" location="specification\connector" recursive="true"/>
|
<cluster name="specification_connector" location="specification\connector" recursive="true"/>
|
||||||
|
<cluster name="specification_service" location="specification\service" recursive="true"/>
|
||||||
|
<cluster name="specification_stream" location="specification\stream" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
note
|
note
|
||||||
description: "Summary description for {WGI_SERVICE}."
|
description: "[
|
||||||
|
WGI_SERVICE
|
||||||
|
]"
|
||||||
|
specification: "EWSGI specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification"
|
||||||
legal: "See notice at end of class."
|
legal: "See notice at end of class."
|
||||||
status: "See notice at end of class."
|
status: "See notice at end of class."
|
||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
@@ -8,23 +11,22 @@ note
|
|||||||
deferred class
|
deferred class
|
||||||
WGI_SERVICE
|
WGI_SERVICE
|
||||||
|
|
||||||
feature {NONE} -- Execution
|
feature {WGI_CONNECTOR} -- Execution
|
||||||
|
|
||||||
execute (req: WGI_REQUEST; res: WGI_RESPONSE)
|
execute (req: WGI_REQUEST; res: WGI_RESPONSE)
|
||||||
-- Execute the request
|
-- Execute the request
|
||||||
-- See `req.input' for input stream
|
-- See `req.input' for input stream
|
||||||
-- `req.environment' for the Gateway environment
|
-- `req.meta_variables' for the CGI meta variable
|
||||||
-- and `res' for the output buffer
|
-- and `res' for output buffer
|
||||||
require
|
require
|
||||||
res_status_unset: not res.status_is_set
|
res_status_unset: not res.status_is_set
|
||||||
deferred
|
deferred
|
||||||
ensure
|
ensure
|
||||||
res_status_set: res.status_is_set
|
res_status_set: res.status_is_set
|
||||||
res_committed: res.message_committed
|
|
||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2011, Eiffel Software and others"
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
@@ -33,4 +35,5 @@ note
|
|||||||
Website http://www.eiffel.com
|
Website http://www.eiffel.com
|
||||||
Customer support http://support.eiffel.com
|
Customer support http://support.eiffel.com
|
||||||
]"
|
]"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,12 +4,212 @@ note
|
|||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
deferred
|
|
||||||
class
|
class
|
||||||
WGI_CHUNKED_INPUT_STREAM
|
WGI_CHUNKED_INPUT_STREAM
|
||||||
|
|
||||||
note
|
create
|
||||||
copyright: "2011-2012, Eiffel Software and others"
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
make (an_input: like input)
|
||||||
|
do
|
||||||
|
create tmp_hex_chunk_size.make_empty
|
||||||
|
input := an_input
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Input
|
||||||
|
|
||||||
|
data: STRING_8
|
||||||
|
local
|
||||||
|
d: like internal_data
|
||||||
|
do
|
||||||
|
d := internal_data
|
||||||
|
if d = Void then
|
||||||
|
d := fetched_data
|
||||||
|
internal_data := d
|
||||||
|
end
|
||||||
|
Result := d
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Parser
|
||||||
|
|
||||||
|
internal_data: detachable STRING_8
|
||||||
|
|
||||||
|
tmp_hex_chunk_size: STRING_8
|
||||||
|
last_chunk_size: INTEGER
|
||||||
|
last_chunk: detachable STRING_8
|
||||||
|
|
||||||
|
fetched_data: STRING_8
|
||||||
|
-- Read all the data in a chunked stream.
|
||||||
|
-- Make the result available in `last_chunked'.
|
||||||
|
-- Chunked-Body = *chunk
|
||||||
|
-- last-chunk
|
||||||
|
-- trailer
|
||||||
|
-- CRLF
|
||||||
|
-- chunk = chunk-size [ chunk-extension ] CRLF
|
||||||
|
-- chunk-data CRLF
|
||||||
|
-- chunk-size = 1*HEX
|
||||||
|
-- last-chunk = 1*("0") [ chunk-extension ] CRLF
|
||||||
|
-- chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
|
||||||
|
-- chunk-ext-name = token
|
||||||
|
-- chunk-ext-val = token | quoted-string
|
||||||
|
-- chunk-data = chunk-size(OCTET)
|
||||||
|
-- trailer = *(entity-header CRLF)
|
||||||
|
local
|
||||||
|
eoc: BOOLEAN
|
||||||
|
s: STRING_8
|
||||||
|
do
|
||||||
|
from
|
||||||
|
create s.make (1024)
|
||||||
|
until
|
||||||
|
eoc
|
||||||
|
loop
|
||||||
|
read_chunk
|
||||||
|
if attached last_chunk as l_last_chunk then
|
||||||
|
s.append (l_last_chunk)
|
||||||
|
else
|
||||||
|
eoc := True
|
||||||
|
end
|
||||||
|
if last_chunk_size = 0 then
|
||||||
|
eoc := True
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
read_trailer
|
||||||
|
|
||||||
|
Result := s
|
||||||
|
end
|
||||||
|
|
||||||
|
reset_chunk
|
||||||
|
do
|
||||||
|
last_chunk := Void
|
||||||
|
last_chunk_size := 0
|
||||||
|
end
|
||||||
|
|
||||||
|
read_chunk
|
||||||
|
do
|
||||||
|
reset_chunk
|
||||||
|
read_chunk_size
|
||||||
|
if last_chunk_size > 0 then
|
||||||
|
read_chunk_data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
read_chunk_data
|
||||||
|
require
|
||||||
|
last_chunk_size > 0
|
||||||
|
local
|
||||||
|
l_input: like input
|
||||||
|
do
|
||||||
|
l_input := input
|
||||||
|
l_input.read_string (last_chunk_size)
|
||||||
|
last_chunk := l_input.last_string
|
||||||
|
|
||||||
|
-- read CRLF
|
||||||
|
l_input.read_character
|
||||||
|
if l_input.last_character = '%R' then
|
||||||
|
l_input.read_character
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
last_chunk_attached: attached last_chunk as el_last_chunk
|
||||||
|
last_chunk_size_ok: el_last_chunk.count = last_chunk_size
|
||||||
|
end
|
||||||
|
|
||||||
|
read_chunk_size
|
||||||
|
require
|
||||||
|
tmp_hex_chunk_size_is_empty: tmp_hex_chunk_size.is_empty
|
||||||
|
local
|
||||||
|
eol : BOOLEAN
|
||||||
|
c: CHARACTER
|
||||||
|
hex : HEXADECIMAL_STRING_TO_INTEGER_CONVERTER
|
||||||
|
l_input: like input
|
||||||
|
do
|
||||||
|
l_input := input
|
||||||
|
from
|
||||||
|
l_input.read_character
|
||||||
|
until
|
||||||
|
eol
|
||||||
|
loop
|
||||||
|
c := l_input.last_character
|
||||||
|
inspect c
|
||||||
|
when '%R' then
|
||||||
|
-- We are in the end of the line, we need to read the next character to start the next line.
|
||||||
|
eol := True
|
||||||
|
l_input.read_character
|
||||||
|
when ';' then
|
||||||
|
-- We are in an extension chunk data
|
||||||
|
read_extension_chunk
|
||||||
|
else
|
||||||
|
tmp_hex_chunk_size.append_character (c)
|
||||||
|
l_input.read_character
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if tmp_hex_chunk_size.same_string ("0") then
|
||||||
|
last_chunk_size := 0
|
||||||
|
else
|
||||||
|
create hex.make
|
||||||
|
hex.parse_string_with_type (tmp_hex_chunk_size, hex.type_integer)
|
||||||
|
if hex.parse_successful then
|
||||||
|
last_chunk_size := hex.parsed_integer
|
||||||
|
else
|
||||||
|
last_chunk_size := 0 -- ERROR ...
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tmp_hex_chunk_size.wipe_out
|
||||||
|
end
|
||||||
|
|
||||||
|
read_extension_chunk
|
||||||
|
local
|
||||||
|
l_input: like input
|
||||||
|
do
|
||||||
|
l_input := input
|
||||||
|
debug
|
||||||
|
print (" Reading extension chunk ")
|
||||||
|
end
|
||||||
|
from
|
||||||
|
l_input.read_character
|
||||||
|
until
|
||||||
|
l_input.last_character = '%R'
|
||||||
|
loop
|
||||||
|
debug
|
||||||
|
print (l_input.last_character)
|
||||||
|
end
|
||||||
|
l_input.read_character
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
read_trailer
|
||||||
|
local
|
||||||
|
l_input: like input
|
||||||
|
do
|
||||||
|
l_input := input
|
||||||
|
if not l_input.end_of_input then
|
||||||
|
debug
|
||||||
|
print (" Reading trailer ")
|
||||||
|
end
|
||||||
|
from
|
||||||
|
l_input.read_character
|
||||||
|
until
|
||||||
|
l_input.last_character = '%R'
|
||||||
|
loop
|
||||||
|
debug
|
||||||
|
print (l_input.last_character)
|
||||||
|
end
|
||||||
|
l_input.read_character
|
||||||
|
end
|
||||||
|
-- read the LF
|
||||||
|
l_input.read_character
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
input: WGI_INPUT_STREAM
|
||||||
|
-- Input Stream
|
||||||
|
|
||||||
|
;note
|
||||||
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ note
|
|||||||
description : "[
|
description : "[
|
||||||
Objects that represents the input stream
|
Objects that represents the input stream
|
||||||
]"
|
]"
|
||||||
|
specification: "EWSGI/connector specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification"
|
||||||
legal: "See notice at end of class."
|
legal: "See notice at end of class."
|
||||||
status: "See notice at end of class."
|
status: "See notice at end of class."
|
||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
@@ -10,25 +11,154 @@ note
|
|||||||
deferred class
|
deferred class
|
||||||
WGI_INPUT_STREAM
|
WGI_INPUT_STREAM
|
||||||
|
|
||||||
|
feature -- Input
|
||||||
|
|
||||||
|
read_character
|
||||||
|
-- Read the next character in input stream.
|
||||||
|
-- Make the result available in `last_character'
|
||||||
|
require
|
||||||
|
is_open_read: is_open_read
|
||||||
|
not_end_of_input: not end_of_input
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
read_string (nb: INTEGER)
|
||||||
|
-- Read the next `nb' characters and
|
||||||
|
-- make the string result available in `last_string'
|
||||||
|
require
|
||||||
|
is_open_read: is_open_read
|
||||||
|
not_end_of_input: not end_of_input
|
||||||
|
nb_large_enough: nb > 0
|
||||||
|
deferred
|
||||||
|
ensure
|
||||||
|
last_string_count_small_enough: not end_of_input implies last_string.count <= nb
|
||||||
|
character_read: not end_of_input implies last_string.count > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
read_to_string (a_string: STRING; pos, nb: INTEGER): INTEGER
|
||||||
|
-- Fill `a_string', starting at position `pos', with
|
||||||
|
-- at most `nb' characters read from input stream.
|
||||||
|
-- Return the number of characters actually read.
|
||||||
|
-- (Note that even if at least `nb' characters are available
|
||||||
|
-- in the input stream, there is no guarantee that they
|
||||||
|
-- will all be read.)
|
||||||
|
require
|
||||||
|
is_open_read: is_open_read
|
||||||
|
not_end_of_input: not end_of_input
|
||||||
|
a_string_not_void: a_string /= Void
|
||||||
|
valid_position: a_string.valid_index (pos)
|
||||||
|
nb_large_enough: nb > 0
|
||||||
|
nb_small_enough: nb <= a_string.count - pos + 1
|
||||||
|
local
|
||||||
|
i, end_pos: INTEGER
|
||||||
|
do
|
||||||
|
end_pos := pos + nb - 1
|
||||||
|
from
|
||||||
|
i := pos
|
||||||
|
until
|
||||||
|
i > end_pos
|
||||||
|
loop
|
||||||
|
read_character
|
||||||
|
if not end_of_input then
|
||||||
|
a_string.put (last_character, i)
|
||||||
|
i := i + 1
|
||||||
|
else
|
||||||
|
Result := i - pos - nb
|
||||||
|
-- Jump out of the loop.
|
||||||
|
i := end_pos + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Result := Result + i - pos
|
||||||
|
ensure
|
||||||
|
nb_char_read_large_enough: Result >= 0
|
||||||
|
nb_char_read_small_enough: Result <= nb
|
||||||
|
character_read: not end_of_input implies Result > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
append_to_string (a_string: STRING; nb: INTEGER)
|
||||||
|
-- Append at most `nb' characters read from input stream
|
||||||
|
-- to `a_string'
|
||||||
|
-- Set `last_appended_count' to the number of characters actually read.
|
||||||
|
-- (Note that even if at least `nb' characters are available
|
||||||
|
-- in the input stream, there is no guarantee that they
|
||||||
|
-- will all be read.)
|
||||||
|
require
|
||||||
|
is_open_read: is_open_read
|
||||||
|
not_end_of_input: not end_of_input
|
||||||
|
a_string_not_void: a_string /= Void
|
||||||
|
nb_large_enough: nb > 0
|
||||||
|
local
|
||||||
|
i, end_pos: INTEGER
|
||||||
|
l_count: INTEGER
|
||||||
|
do
|
||||||
|
from
|
||||||
|
i := a_string.count + 1
|
||||||
|
end_pos := i + nb - 1
|
||||||
|
a_string.grow (end_pos)
|
||||||
|
until
|
||||||
|
i > end_pos
|
||||||
|
loop
|
||||||
|
read_character
|
||||||
|
if not end_of_input then
|
||||||
|
a_string.extend (last_character)
|
||||||
|
i := i + 1
|
||||||
|
else
|
||||||
|
l_count := i - nb
|
||||||
|
-- Jump out of the loop.
|
||||||
|
i := end_pos + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
last_appended_count := l_count + i
|
||||||
|
ensure
|
||||||
|
nb_char_read_large_enough: last_appended_count >= 0
|
||||||
|
nb_char_read_small_enough: last_appended_count <= nb
|
||||||
|
character_read: not end_of_input implies last_appended_count > 0
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
last_string: STRING_8
|
last_string: STRING_8
|
||||||
-- Last read string from stream
|
-- 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.)
|
||||||
|
require
|
||||||
|
is_open_read: is_open_read
|
||||||
|
not_end_of_input: not end_of_input
|
||||||
|
deferred
|
||||||
|
ensure
|
||||||
|
last_string_not_void: Result /= Void
|
||||||
|
end
|
||||||
|
|
||||||
|
last_character: CHARACTER_8
|
||||||
|
-- Last item read.
|
||||||
|
require
|
||||||
|
is_open_read: is_open_read
|
||||||
|
not_end_of_input: not end_of_input
|
||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Basic operation
|
last_appended_count: INTEGER
|
||||||
|
-- Count of characters actually read by last `append_to_string' call.
|
||||||
|
|
||||||
read_stream (n: INTEGER)
|
feature -- Status report
|
||||||
require
|
|
||||||
n_positive: n > 0
|
is_open_read: BOOLEAN
|
||||||
|
-- Can items be read from input stream?
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
end_of_input: BOOLEAN
|
||||||
|
-- Has the end of input stream been reached?
|
||||||
|
require
|
||||||
|
is_open_read: is_open_read
|
||||||
deferred
|
deferred
|
||||||
ensure
|
|
||||||
at_max_n: last_string.count <= n
|
|
||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2011, Eiffel Software and others"
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ note
|
|||||||
description : "[
|
description : "[
|
||||||
Objects that represents the output stream
|
Objects that represents the output stream
|
||||||
]"
|
]"
|
||||||
|
specification: "EWSGI/connector specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification"
|
||||||
legal: "See notice at end of class."
|
legal: "See notice at end of class."
|
||||||
status: "See notice at end of class."
|
status: "See notice at end of class."
|
||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
@@ -10,18 +11,54 @@ note
|
|||||||
deferred class
|
deferred class
|
||||||
WGI_OUTPUT_STREAM
|
WGI_OUTPUT_STREAM
|
||||||
|
|
||||||
feature -- Core operation
|
feature -- Output
|
||||||
|
|
||||||
put_string (s: STRING_8)
|
put_string (a_string: READABLE_STRING_8)
|
||||||
-- Write `s' into the output stream
|
-- Write `a_string' to output stream.
|
||||||
require
|
require
|
||||||
s_not_empty: s /= Void and then not s.is_empty
|
is_open_write: is_open_write
|
||||||
|
a_string_not_void: a_string /= Void
|
||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
flush
|
put_substring (a_string: READABLE_STRING_8; s, e: INTEGER)
|
||||||
-- Flush the output stream
|
-- Write substring of `a_string' between indexes
|
||||||
|
-- `s' and `e' to output stream.
|
||||||
|
--| Could be redefined for optimization
|
||||||
|
require
|
||||||
|
is_open_write: is_open_write
|
||||||
|
a_string_not_void: a_string /= Void
|
||||||
|
s_large_enough: s >= 1
|
||||||
|
e_small_enough: e <= a_string.count
|
||||||
|
valid_interval: s <= e + 1
|
||||||
do
|
do
|
||||||
|
if s <= e then
|
||||||
|
put_string (a_string.substring (s, e))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
put_character_8 (c: CHARACTER_8)
|
||||||
|
-- Write `c' to output stream.
|
||||||
|
--| Could be redefined for optimization
|
||||||
|
require
|
||||||
|
is_open_write: is_open_write
|
||||||
|
do
|
||||||
|
put_string (c.out)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Specific output
|
||||||
|
|
||||||
|
put_header_line (s: READABLE_STRING_8)
|
||||||
|
-- Send `s' to http client as header line
|
||||||
|
do
|
||||||
|
put_string (s)
|
||||||
|
put_crlf
|
||||||
|
end
|
||||||
|
|
||||||
|
put_crlf
|
||||||
|
-- Send "%R%N" string
|
||||||
|
do
|
||||||
|
put_string (crlf)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Status writing
|
feature -- Status writing
|
||||||
@@ -33,25 +70,28 @@ feature -- Status writing
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Basic operation
|
feature -- Status report
|
||||||
|
|
||||||
put_substring (s: STRING; start_index, end_index: INTEGER)
|
is_open_write: BOOLEAN
|
||||||
-- Write `s[start_index:end_index]' into the output stream
|
-- Can items be written to output stream?
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
flush
|
||||||
|
-- Flush buffered data to disk.
|
||||||
require
|
require
|
||||||
s_not_empty: s /= Void and then not s.is_empty
|
is_open_write: is_open_write
|
||||||
do
|
deferred
|
||||||
put_string (s.substring (start_index, end_index))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
put_header_line (s: STRING)
|
feature -- Constant
|
||||||
-- Send `s' to http client as header line
|
|
||||||
do
|
crlf: STRING = "%R%N"
|
||||||
put_string (s)
|
|
||||||
put_string ("%R%N")
|
|
||||||
end
|
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2011, Eiffel Software and others"
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -1,221 +0,0 @@
|
|||||||
note
|
|
||||||
description: "Summary description for {WGI_CHUNKED_INPUT_STREAM}."
|
|
||||||
author: ""
|
|
||||||
date: "$Date$"
|
|
||||||
revision: "$Revision$"
|
|
||||||
|
|
||||||
class
|
|
||||||
WGI_CHUNKED_INPUT_STREAM
|
|
||||||
|
|
||||||
create
|
|
||||||
make
|
|
||||||
|
|
||||||
feature {NONE} -- Implementation
|
|
||||||
|
|
||||||
make (an_input: like input)
|
|
||||||
do
|
|
||||||
create tmp_hex_chunk_size.make_empty
|
|
||||||
input := an_input
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Input
|
|
||||||
|
|
||||||
data: STRING_8
|
|
||||||
local
|
|
||||||
d: like internal_data
|
|
||||||
do
|
|
||||||
d := internal_data
|
|
||||||
if d = Void then
|
|
||||||
d := fetched_data
|
|
||||||
internal_data := d
|
|
||||||
end
|
|
||||||
Result := d
|
|
||||||
end
|
|
||||||
|
|
||||||
feature {NONE} -- Parser
|
|
||||||
|
|
||||||
internal_data: detachable STRING_8
|
|
||||||
|
|
||||||
tmp_hex_chunk_size: STRING_8
|
|
||||||
last_chunk_size: INTEGER
|
|
||||||
last_chunk: detachable STRING_8
|
|
||||||
|
|
||||||
fetched_data: STRING_8
|
|
||||||
-- Read all the data in a chunked stream.
|
|
||||||
-- Make the result available in `last_chunked'.
|
|
||||||
-- Chunked-Body = *chunk
|
|
||||||
-- last-chunk
|
|
||||||
-- trailer
|
|
||||||
-- CRLF
|
|
||||||
-- chunk = chunk-size [ chunk-extension ] CRLF
|
|
||||||
-- chunk-data CRLF
|
|
||||||
-- chunk-size = 1*HEX
|
|
||||||
-- last-chunk = 1*("0") [ chunk-extension ] CRLF
|
|
||||||
-- chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
|
|
||||||
-- chunk-ext-name = token
|
|
||||||
-- chunk-ext-val = token | quoted-string
|
|
||||||
-- chunk-data = chunk-size(OCTET)
|
|
||||||
-- trailer = *(entity-header CRLF)
|
|
||||||
local
|
|
||||||
eoc: BOOLEAN
|
|
||||||
s: STRING_8
|
|
||||||
do
|
|
||||||
from
|
|
||||||
create s.make (1024)
|
|
||||||
until
|
|
||||||
eoc
|
|
||||||
loop
|
|
||||||
read_chunk
|
|
||||||
if attached last_chunk as l_last_chunk then
|
|
||||||
s.append (l_last_chunk)
|
|
||||||
else
|
|
||||||
eoc := True
|
|
||||||
end
|
|
||||||
if last_chunk_size = 0 then
|
|
||||||
eoc := True
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
read_trailer
|
|
||||||
|
|
||||||
Result := s
|
|
||||||
end
|
|
||||||
|
|
||||||
reset_chunk
|
|
||||||
do
|
|
||||||
last_chunk := Void
|
|
||||||
last_chunk_size := 0
|
|
||||||
end
|
|
||||||
|
|
||||||
read_chunk
|
|
||||||
do
|
|
||||||
reset_chunk
|
|
||||||
read_chunk_size
|
|
||||||
if last_chunk_size > 0 then
|
|
||||||
read_chunk_data
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
read_chunk_data
|
|
||||||
require
|
|
||||||
last_chunk_size > 0
|
|
||||||
local
|
|
||||||
l_input: like input
|
|
||||||
do
|
|
||||||
l_input := input
|
|
||||||
l_input.read_string (last_chunk_size)
|
|
||||||
last_chunk := l_input.last_string
|
|
||||||
|
|
||||||
-- read CRLF
|
|
||||||
l_input.read_character
|
|
||||||
if l_input.last_character = '%R' then
|
|
||||||
l_input.read_character
|
|
||||||
end
|
|
||||||
ensure
|
|
||||||
last_chunk_attached: attached last_chunk as el_last_chunk
|
|
||||||
last_chunk_size_ok: el_last_chunk.count = last_chunk_size
|
|
||||||
end
|
|
||||||
|
|
||||||
read_chunk_size
|
|
||||||
require
|
|
||||||
tmp_hex_chunk_size_is_empty: tmp_hex_chunk_size.is_empty
|
|
||||||
local
|
|
||||||
eol : BOOLEAN
|
|
||||||
c: CHARACTER
|
|
||||||
hex : HEXADECIMAL_STRING_TO_INTEGER_CONVERTER
|
|
||||||
l_input: like input
|
|
||||||
do
|
|
||||||
l_input := input
|
|
||||||
from
|
|
||||||
l_input.read_character
|
|
||||||
until
|
|
||||||
eol
|
|
||||||
loop
|
|
||||||
c := l_input.last_character
|
|
||||||
inspect c
|
|
||||||
when '%R' then
|
|
||||||
-- We are in the end of the line, we need to read the next character to start the next line.
|
|
||||||
eol := True
|
|
||||||
l_input.read_character
|
|
||||||
when ';' then
|
|
||||||
-- We are in an extension chunk data
|
|
||||||
read_extension_chunk
|
|
||||||
else
|
|
||||||
tmp_hex_chunk_size.append_character (c)
|
|
||||||
l_input.read_character
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if tmp_hex_chunk_size.same_string ("0") then
|
|
||||||
last_chunk_size := 0
|
|
||||||
else
|
|
||||||
create hex.make
|
|
||||||
hex.parse_string_with_type (tmp_hex_chunk_size, hex.type_integer)
|
|
||||||
if hex.parse_successful then
|
|
||||||
last_chunk_size := hex.parsed_integer
|
|
||||||
else
|
|
||||||
last_chunk_size := 0 -- ERROR ...
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tmp_hex_chunk_size.wipe_out
|
|
||||||
end
|
|
||||||
|
|
||||||
read_extension_chunk
|
|
||||||
local
|
|
||||||
l_input: like input
|
|
||||||
do
|
|
||||||
l_input := input
|
|
||||||
debug
|
|
||||||
print (" Reading extension chunk ")
|
|
||||||
end
|
|
||||||
from
|
|
||||||
l_input.read_character
|
|
||||||
until
|
|
||||||
l_input.last_character = '%R'
|
|
||||||
loop
|
|
||||||
debug
|
|
||||||
print (l_input.last_character)
|
|
||||||
end
|
|
||||||
l_input.read_character
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
read_trailer
|
|
||||||
local
|
|
||||||
l_input: like input
|
|
||||||
do
|
|
||||||
l_input := input
|
|
||||||
if not l_input.end_of_input then
|
|
||||||
debug
|
|
||||||
print (" Reading trailer ")
|
|
||||||
end
|
|
||||||
from
|
|
||||||
l_input.read_character
|
|
||||||
until
|
|
||||||
l_input.last_character = '%R'
|
|
||||||
loop
|
|
||||||
debug
|
|
||||||
print (l_input.last_character)
|
|
||||||
end
|
|
||||||
l_input.read_character
|
|
||||||
end
|
|
||||||
-- read the LF
|
|
||||||
l_input.read_character
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
feature {NONE} -- Implementation
|
|
||||||
|
|
||||||
input: WGI_INPUT_STREAM
|
|
||||||
-- Input Stream
|
|
||||||
|
|
||||||
;note
|
|
||||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
note
|
|
||||||
description : "[
|
|
||||||
Objects that represents the input stream
|
|
||||||
]"
|
|
||||||
specification: "EWSGI/connector specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification"
|
|
||||||
legal: "See notice at end of class."
|
|
||||||
status: "See notice at end of class."
|
|
||||||
date: "$Date$"
|
|
||||||
revision: "$Revision$"
|
|
||||||
|
|
||||||
deferred class
|
|
||||||
WGI_INPUT_STREAM
|
|
||||||
|
|
||||||
feature -- Input
|
|
||||||
|
|
||||||
read_character
|
|
||||||
-- Read the next character in input stream.
|
|
||||||
-- Make the result available in `last_character'
|
|
||||||
require
|
|
||||||
is_open_read: is_open_read
|
|
||||||
not_end_of_input: not end_of_input
|
|
||||||
deferred
|
|
||||||
end
|
|
||||||
|
|
||||||
read_string (nb: INTEGER)
|
|
||||||
-- Read the next `nb' characters and
|
|
||||||
-- make the string result available in `last_string'
|
|
||||||
require
|
|
||||||
is_open_read: is_open_read
|
|
||||||
not_end_of_input: not end_of_input
|
|
||||||
nb_large_enough: nb > 0
|
|
||||||
deferred
|
|
||||||
ensure
|
|
||||||
last_string_count_small_enough: not end_of_input implies last_string.count <= nb
|
|
||||||
character_read: not end_of_input implies last_string.count > 0
|
|
||||||
end
|
|
||||||
|
|
||||||
read_to_string (a_string: STRING; pos, nb: INTEGER): INTEGER
|
|
||||||
-- Fill `a_string', starting at position `pos', with
|
|
||||||
-- at most `nb' characters read from input stream.
|
|
||||||
-- Return the number of characters actually read.
|
|
||||||
-- (Note that even if at least `nb' characters are available
|
|
||||||
-- in the input stream, there is no guarantee that they
|
|
||||||
-- will all be read.)
|
|
||||||
require
|
|
||||||
is_open_read: is_open_read
|
|
||||||
not_end_of_input: not end_of_input
|
|
||||||
a_string_not_void: a_string /= Void
|
|
||||||
valid_position: a_string.valid_index (pos)
|
|
||||||
nb_large_enough: nb > 0
|
|
||||||
nb_small_enough: nb <= a_string.count - pos + 1
|
|
||||||
local
|
|
||||||
i, end_pos: INTEGER
|
|
||||||
do
|
|
||||||
end_pos := pos + nb - 1
|
|
||||||
from
|
|
||||||
i := pos
|
|
||||||
until
|
|
||||||
i > end_pos
|
|
||||||
loop
|
|
||||||
read_character
|
|
||||||
if not end_of_input then
|
|
||||||
a_string.put (last_character, i)
|
|
||||||
i := i + 1
|
|
||||||
else
|
|
||||||
Result := i - pos - nb
|
|
||||||
-- Jump out of the loop.
|
|
||||||
i := end_pos + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Result := Result + i - pos
|
|
||||||
ensure
|
|
||||||
nb_char_read_large_enough: Result >= 0
|
|
||||||
nb_char_read_small_enough: Result <= nb
|
|
||||||
character_read: not end_of_input implies Result > 0
|
|
||||||
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.)
|
|
||||||
require
|
|
||||||
is_open_read: is_open_read
|
|
||||||
not_end_of_input: not end_of_input
|
|
||||||
deferred
|
|
||||||
ensure
|
|
||||||
last_string_not_void: Result /= Void
|
|
||||||
end
|
|
||||||
|
|
||||||
last_character: CHARACTER_8
|
|
||||||
-- Last item read.
|
|
||||||
require
|
|
||||||
is_open_read: is_open_read
|
|
||||||
not_end_of_input: not end_of_input
|
|
||||||
deferred
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Status report
|
|
||||||
|
|
||||||
is_open_read: BOOLEAN
|
|
||||||
-- Can items be read from input stream?
|
|
||||||
deferred
|
|
||||||
end
|
|
||||||
|
|
||||||
end_of_input: BOOLEAN
|
|
||||||
-- Has the end of input stream been reached?
|
|
||||||
require
|
|
||||||
is_open_read: is_open_read
|
|
||||||
deferred
|
|
||||||
end
|
|
||||||
|
|
||||||
note
|
|
||||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
note
|
|
||||||
description : "[
|
|
||||||
Objects that represents the output stream
|
|
||||||
]"
|
|
||||||
specification: "EWSGI/connector specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification"
|
|
||||||
legal: "See notice at end of class."
|
|
||||||
status: "See notice at end of class."
|
|
||||||
date: "$Date$"
|
|
||||||
revision: "$Revision$"
|
|
||||||
|
|
||||||
deferred class
|
|
||||||
WGI_OUTPUT_STREAM
|
|
||||||
|
|
||||||
feature -- Output
|
|
||||||
|
|
||||||
put_string (a_string: READABLE_STRING_8)
|
|
||||||
-- Write `a_string' to output stream.
|
|
||||||
require
|
|
||||||
is_open_write: is_open_write
|
|
||||||
a_string_not_void: a_string /= Void
|
|
||||||
deferred
|
|
||||||
end
|
|
||||||
|
|
||||||
put_substring (a_string: READABLE_STRING_8; s, e: INTEGER)
|
|
||||||
-- Write substring of `a_string' between indexes
|
|
||||||
-- `s' and `e' to output stream.
|
|
||||||
--| Could be redefined for optimization
|
|
||||||
require
|
|
||||||
is_open_write: is_open_write
|
|
||||||
a_string_not_void: a_string /= Void
|
|
||||||
s_large_enough: s >= 1
|
|
||||||
e_small_enough: e <= a_string.count
|
|
||||||
valid_interval: s <= e + 1
|
|
||||||
do
|
|
||||||
if s <= e then
|
|
||||||
put_string (a_string.substring (s, e))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
put_character_8 (c: CHARACTER_8)
|
|
||||||
-- Write `c' to output stream.
|
|
||||||
--| Could be redefined for optimization
|
|
||||||
require
|
|
||||||
is_open_write: is_open_write
|
|
||||||
do
|
|
||||||
put_string (c.out)
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Specific output
|
|
||||||
|
|
||||||
put_header_line (s: READABLE_STRING_8)
|
|
||||||
-- Send `s' to http client as header line
|
|
||||||
do
|
|
||||||
put_string (s)
|
|
||||||
put_crlf
|
|
||||||
end
|
|
||||||
|
|
||||||
put_crlf
|
|
||||||
-- Send "%R%N" string
|
|
||||||
do
|
|
||||||
put_string (crlf)
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Status writing
|
|
||||||
|
|
||||||
put_status_line (a_code: INTEGER)
|
|
||||||
-- Put status code line for `a_code'
|
|
||||||
--| Note this is a default implementation, and could be redefined
|
|
||||||
--| for instance in relation to NPH CGI script
|
|
||||||
deferred
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Status report
|
|
||||||
|
|
||||||
is_open_write: BOOLEAN
|
|
||||||
-- Can items be written to output stream?
|
|
||||||
deferred
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Basic operations
|
|
||||||
|
|
||||||
flush
|
|
||||||
-- Flush buffered data to disk.
|
|
||||||
require
|
|
||||||
is_open_write: is_open_write
|
|
||||||
deferred
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Constant
|
|
||||||
|
|
||||||
crlf: STRING = "%R%N"
|
|
||||||
|
|
||||||
note
|
|
||||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
note
|
|
||||||
description: "[
|
|
||||||
WGI_SERVICE
|
|
||||||
]"
|
|
||||||
specification: "EWSGI specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification"
|
|
||||||
legal: "See notice at end of class."
|
|
||||||
status: "See notice at end of class."
|
|
||||||
date: "$Date$"
|
|
||||||
revision: "$Revision$"
|
|
||||||
|
|
||||||
deferred class
|
|
||||||
WGI_SERVICE
|
|
||||||
|
|
||||||
feature {WGI_CONNECTOR} -- Execution
|
|
||||||
|
|
||||||
execute (req: WGI_REQUEST; res: WGI_RESPONSE)
|
|
||||||
-- Execute the request
|
|
||||||
-- See `req.input' for input stream
|
|
||||||
-- `req.meta_variables' for the CGI meta variable
|
|
||||||
-- and `res' for output buffer
|
|
||||||
require
|
|
||||||
res_status_unset: not res.status_is_set
|
|
||||||
deferred
|
|
||||||
ensure
|
|
||||||
res_status_set: res.status_is_set
|
|
||||||
end
|
|
||||||
|
|
||||||
note
|
|
||||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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