Made WGI_CHUNKED_INPUT_STREAM inherits from WGI_INPUT_STREAM

Merged REQUEST.input and REQUEST.chunked_input
  Now REQUEST.input handles directly the chunked transfer encoding, or the non chunked.
Kept REQUEST.is_chunked_input since it matters that Content-Length is 0 even if there are input (chunked) data.
This commit is contained in:
Jocelyn Fiat
2012-04-13 16:33:49 +02:00
parent e6a727ee42
commit 0bd2d16c12
5 changed files with 171 additions and 112 deletions

View File

@@ -77,8 +77,7 @@ feature -- Access: Input
input: WGI_INPUT_STREAM
-- Server input channel
require
is_not_chunked_input: not is_chunked_input
--| Could also be Chunked input, but this is transparent
deferred
end
@@ -87,13 +86,6 @@ feature -- Access: Input
deferred
end
chunked_input: detachable WGI_CHUNKED_INPUT_STREAM
-- Chunked server input channel
require
is_chunked_input: is_chunked_input
deferred
end
feature -- Access: CGI meta variables
meta_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_8

View File

@@ -1,12 +1,14 @@
note
description: "Summary description for {WGI_CHUNKED_INPUT_STREAM}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
WGI_CHUNKED_INPUT_STREAM
inherit
WGI_INPUT_STREAM
create
make
@@ -14,90 +16,177 @@ feature {NONE} -- Implementation
make (an_input: like input)
do
create last_string.make_empty
create last_chunk.make_empty
last_chunk_size := 0
index := 0
chunk_lower := 0
chunk_upper := 0
create tmp_hex_chunk_size.make_empty
input := an_input
end
feature -- Input
data: STRING_8
local
d: like internal_data
read_character
-- Read the next character in input stream.
-- Make the result available in `last_character'
do
d := internal_data
if d = Void then
d := fetched_data
internal_data := d
index := index + 1
if index > chunk_upper then
read_chunk
if last_chunk = Void then
read_trailer
end
end
Result := d
last_character := last_chunk.item (index)
end
read_string (nb: INTEGER)
-- Read the next `nb' characters and
-- make the string result available in `last_string'
local
i: like index
do
last_string.wipe_out
if last_chunk_size = 0 then
read_chunk
end
from
index := index + 1
i := index
until
i - index + 1 = nb or last_chunk_size = 0
loop
if i + nb - 1 <= chunk_upper then
last_string.append (last_chunk.substring (i, i + nb - 1))
i := i + nb - 1
else
-- Need to read new chunk
-- first get all available data from current chunk
if i <= chunk_upper then
last_string.append (last_chunk.substring (i, chunk_upper))
i := chunk_upper
end
-- then continue
read_chunk
end
end
if last_chunk_size = 0 then
read_trailer
end
index := i
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.)
last_character: CHARACTER_8
-- Last item read.
feature -- Status report
is_open_read: BOOLEAN
-- Can items be read from input stream?
do
Result := input.is_open_read
end
end_of_input: BOOLEAN
-- Has the end of input stream been reached?
do
Result := input.end_of_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
index, chunk_lower, chunk_upper: INTEGER
last_chunk_size: INTEGER
last_chunk: STRING_8
-- 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
-- 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
-- read_trailer
Result := s
end
reset_chunk
do
last_chunk := Void
last_chunk_size := 0
end
-- Result := s
-- end
read_chunk
do
reset_chunk
chunk_lower := chunk_upper + 1
last_chunk.wipe_out
last_chunk_size := 0
read_chunk_size
if last_chunk_size > 0 then
chunk_upper := chunk_upper + last_chunk_size
read_chunk_data
end
ensure
attached last_chunk as l_last_chunk implies l_last_chunk.count = chunk_upper - chunk_lower
end
read_chunk_data
require
last_chunk.is_empty
last_chunk_size > 0
local
l_input: like input
@@ -105,12 +194,6 @@ feature {NONE} -- Parser
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

View File

@@ -27,9 +27,18 @@ feature {NONE} -- Initialization
input := a_input
set_meta_variables (a_vars)
update_path_info
if attached http_transfer_encoding as l_transfer_encoding and then l_transfer_encoding.same_string ("chunked") then
update_input
end
update_input
-- Update input, depending on Transfer-Encoding value.
do
if
attached http_transfer_encoding as l_transfer_encoding and then
l_transfer_encoding.same_string (once "chunked")
then
is_chunked_input := True
create chunked_input.make (a_input)
create {WGI_CHUNKED_INPUT_STREAM} input.make (input)
end
end
@@ -40,9 +49,7 @@ feature -- Access: Input
input: WGI_INPUT_STREAM
-- Server input channel
chunked_input: detachable WGI_CHUNKED_INPUT_STREAM
-- Chunked server input channel
--| Could be a chunked input as well
feature -- EWSGI access

View File

@@ -11,44 +11,30 @@ feature {NONE} -- Implementation
full_input_data (req: WSF_REQUEST): READABLE_STRING_8
do
if req.is_chunked_input then
if attached req.chunked_input as l_chunked_input then
Result := l_chunked_input.data
else
check has_chunked_input: False end
Result := ""
end
else
Result := read_input_data (req.input, req.content_length_value)
end
Result := read_input_data (req.input)
end
read_input_data (a_input: WGI_INPUT_STREAM; nb: NATURAL_64): STRING_8
read_input_data (a_input: WGI_INPUT_STREAM): STRING_8
-- All data from input form
local
nb32: INTEGER
n64: NATURAL_64
n: INTEGER
t: STRING
do
from
n64 := nb
nb32 := n64.to_integer_32
create Result.make (nb32)
n := nb32
if n > 1_024 then
n := 1_024
end
n := 1_024
create Result.make (n)
until
n64 <= 0
n = 0
loop
a_input.read_string (n)
t := a_input.last_string
Result.append_string (t)
if t.count < n then
n64 := 0
if t.count = 0 then
n := 0
else
n64 := n64 - t.count.as_natural_64
if t.count < n then
n := 0
end
Result.append_string (t)
end
end
end

View File

@@ -157,26 +157,17 @@ feature -- Access: Input
input: WGI_INPUT_STREAM
-- Server input channel
require
is_not_chunked_input: not is_chunked_input
do
Result := wgi_request.input
end
is_chunked_input: BOOLEAN
-- Is request using chunked transfer-encoding?
-- If True, the Content-Length has no meaning
do
Result := wgi_request.is_chunked_input
end
chunked_input: detachable WGI_CHUNKED_INPUT_STREAM
-- Server input channel
require
is_chunked_input: is_chunked_input
do
Result := wgi_request.chunked_input
end
feature -- Helper
is_request_method (m: READABLE_STRING_8): BOOLEAN