Updating EWSGI specification classes

This commit is contained in:
Jocelyn Fiat
2012-03-19 15:06:50 +01:00
parent fea0f115a0
commit 3432e2d8b2
10 changed files with 413 additions and 526 deletions

View File

@@ -18,5 +18,7 @@
<cluster name="specification_request" location="specification\request" recursive="true"/>
<cluster name="specification_response" location="specification\response" 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>
</system>

View File

@@ -18,5 +18,7 @@
<cluster name="specification_request" location="specification\request" recursive="true"/>
<cluster name="specification_response" location="specification\response" 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>
</system>

View File

@@ -1,5 +1,8 @@
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."
status: "See notice at end of class."
date: "$Date$"
@@ -8,23 +11,22 @@ note
deferred class
WGI_SERVICE
feature {NONE} -- Execution
feature {WGI_CONNECTOR} -- Execution
execute (req: WGI_REQUEST; res: WGI_RESPONSE)
-- Execute the request
-- See `req.input' for input stream
-- `req.environment' for the Gateway environment
-- and `res' for the output buffer
-- `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
res_committed: res.message_committed
end
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)"
source: "[
Eiffel Software
@@ -33,4 +35,5 @@ note
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -4,12 +4,212 @@ note
date: "$Date$"
revision: "$Revision$"
deferred
class
WGI_CHUNKED_INPUT_STREAM
note
copyright: "2011-2012, Eiffel Software and others"
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

View File

@@ -2,6 +2,7 @@ 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$"
@@ -10,25 +11,154 @@ note
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
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
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
end
feature -- Basic operation
last_appended_count: INTEGER
-- Count of characters actually read by last `append_to_string' call.
read_stream (n: INTEGER)
require
n_positive: n > 0
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
ensure
at_max_n: last_string.count <= n
end
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)"
source: "[
Eiffel Software

View File

@@ -2,6 +2,7 @@ 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$"
@@ -10,18 +11,54 @@ note
deferred class
WGI_OUTPUT_STREAM
feature -- Core operation
feature -- Output
put_string (s: STRING_8)
-- Write `s' into the output stream
put_string (a_string: READABLE_STRING_8)
-- Write `a_string' to output stream.
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
end
flush
-- Flush the output stream
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
@@ -33,25 +70,28 @@ feature -- Status writing
deferred
end
feature -- Basic operation
feature -- Status report
put_substring (s: STRING; start_index, end_index: INTEGER)
-- Write `s[start_index:end_index]' into the output stream
is_open_write: BOOLEAN
-- Can items be written to output stream?
deferred
end
feature -- Basic operations
flush
-- Flush buffered data to disk.
require
s_not_empty: s /= Void and then not s.is_empty
do
put_string (s.substring (start_index, end_index))
is_open_write: is_open_write
deferred
end
put_header_line (s: STRING)
-- Send `s' to http client as header line
do
put_string (s)
put_string ("%R%N")
end
feature -- Constant
crlf: STRING = "%R%N"
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)"
source: "[
Eiffel Software

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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