From 13b09adc8c0462f5e84081f9078fa9efda8f384e Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Mon, 14 Nov 2011 14:17:41 +0100 Subject: [PATCH] Changed the WGI_INPUT_STREAM and WGI_OUTPUT_STREAM interfaces main changes for existing code `read_stream' is renamed `read_string' --- examples/restbucks/restbucks-safe.ecf | 13 ++- .../restbucks/src/resource/order_handler.e | 4 +- examples/restbucks/src/restbucks_server.e | 2 +- ext/server/nino | 2 +- .../connectors/cgi/src/wgi_cgi_input_stream.e | 7 +- .../cgi/src/wgi_cgi_output_stream.e | 3 - .../ewsgi/connectors/libfcgi/libfcgi-safe.ecf | 6 +- .../libfcgi/src/wgi_libfcgi_input_stream.e | 36 +++++- .../libfcgi/src/wgi_libfcgi_output_stream.e | 15 +++ .../connectors/nino/src/wgi_nino_connector.e | 6 +- .../connectors/nino/src/wgi_nino_handler.e | 12 +- .../nino/src/wgi_nino_input_stream.e | 65 ++++++++--- .../nino/src/wgi_nino_output_stream.e | 39 +++++-- .../ewsgi/src/helper/wgi_request_from_table.e | 2 +- library/server/ewsgi/src/wgi_input_stream.e | 101 ++++++++++++++-- library/server/ewsgi/src/wgi_output_stream.e | 109 +++++++++++------- .../libfcgi/implementation/windows/fcgi_imp.e | 5 + library/server/wsf/src/wsf_request.e | 18 +-- tests/compile_all.ini | 2 + 19 files changed, 334 insertions(+), 113 deletions(-) diff --git a/examples/restbucks/restbucks-safe.ecf b/examples/restbucks/restbucks-safe.ecf index 0be35898..2119f341 100644 --- a/examples/restbucks/restbucks-safe.ecf +++ b/examples/restbucks/restbucks-safe.ecf @@ -1,5 +1,5 @@ - + @@ -7,20 +7,21 @@ /\.git$ /\.svn$ - - - - - + + + + diff --git a/examples/restbucks/src/resource/order_handler.e b/examples/restbucks/src/resource/order_handler.e index baf3547e..af7adbb6 100644 --- a/examples/restbucks/src/resource/order_handler.e +++ b/examples/restbucks/src/resource/order_handler.e @@ -111,7 +111,7 @@ feature -- HTTP Methods l_post: STRING l_order : detachable ORDER do - req.input.read_stream (req.content_length_value.as_integer_32) + req.input.read_string (req.content_length_value.as_integer_32) l_post := req.input.last_string l_order := extract_order_request(l_post) if l_order /= Void and then db_access.orders.has_key (l_order.id) then @@ -229,7 +229,7 @@ feature -- HTTP Methods local l_post: STRING do - req.input.read_stream (req.content_length_value.as_integer_32) + req.input.read_string (req.content_length_value.as_integer_32) l_post := req.input.last_string if attached extract_order_request (l_post) as l_order then save_order (l_order) diff --git a/examples/restbucks/src/restbucks_server.e b/examples/restbucks/src/restbucks_server.e index b58986a7..cc6cc3d4 100644 --- a/examples/restbucks/src/restbucks_server.e +++ b/examples/restbucks/src/restbucks_server.e @@ -53,7 +53,7 @@ feature -- Execution l_api_doc : STRING do if req.content_length_value > 0 then - req.input.read_stream (req.content_length_value.as_integer_32) + req.input.read_string (req.content_length_value.as_integer_32) end create h.make h.put_status ({HTTP_STATUS_CODE}.method_not_allowed) diff --git a/ext/server/nino b/ext/server/nino index abd67c8c..9f2abab6 160000 --- a/ext/server/nino +++ b/ext/server/nino @@ -1 +1 @@ -Subproject commit abd67c8caac84e488f831af17b39ea30cca86ba8 +Subproject commit 9f2abab670a426a3cf114e81919c4763c2a7a6b6 diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e index 5659f599..faa595d5 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e @@ -10,10 +10,15 @@ class inherit WGI_INPUT_STREAM + undefine + read_to_string + end CONSOLE rename - make as console_make + make as console_make, + read_stream as read_string, + end_of_file as end_of_input end create diff --git a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e index 1a714b21..b29f6ab9 100644 --- a/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e @@ -10,9 +10,6 @@ class inherit WGI_OUTPUT_STREAM - undefine - flush - end CONSOLE rename diff --git a/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf b/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf index fbc3d0ac..1dd35651 100644 --- a/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf +++ b/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf @@ -10,9 +10,9 @@ - - - + + + diff --git a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e index 5fc258cf..3ae08d2b 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e @@ -32,9 +32,38 @@ feature {NONE} -- Initialization create last_string.make_empty end -feature -- Basic operation +feature -- Status report - read_stream (nb_char: INTEGER) + 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 := fcgi.fcgi_end_of_input + end + +feature -- Input + + read_character + -- Read the next character in input stream. + -- Make the result available in `last_character'. + local + s: STRING + do + create s.make (1) + fcgi.fill_string_from_stdin (s, 1) + if s.count >= 1 then + last_character := s.item (1) + else + last_character := '%U' + end + end + + read_string (nb_char: INTEGER) -- Read a string of at most `nb_char' bound characters -- or until end of file. -- Make result available in `last_string'. @@ -47,6 +76,9 @@ feature -- Access last_string: STRING -- Last string read + last_character: CHARACTER_8 + -- Last item read + feature {NONE} -- Implementation fcgi: FCGI; diff --git a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e index 45c6c9b3..ce1d31ef 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e @@ -28,6 +28,14 @@ feature {NONE} -- Initialization fcgi := a_fcgi end +feature -- Status report + + is_open_write: BOOLEAN + -- Can items be written to output stream? + do + Result := True + end + feature -- Status writing put_status_line (a_code: INTEGER) @@ -56,6 +64,13 @@ feature -- Basic operation fcgi.put_string (s) end +feature -- Basic operations + + flush + -- Flush buffered data to disk. + do + end + feature {NONE} -- Implementation fcgi: FCGI diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e index 36b346c2..d12df62e 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e @@ -104,15 +104,15 @@ feature -- Server server.setup (l_http_handler) end - process_request (env: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM) + process_request (env: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_socket: TCP_STREAM_SOCKET) local req: WGI_REQUEST_FROM_TABLE res: detachable WGI_RESPONSE_STREAM_BUFFER rescued: BOOLEAN do if not rescued then - create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_input)) - create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_output)) + create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_socket)) + create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket)) req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text) application.execute (req, res) else diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e index 628e9388..3a5fe1df 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e @@ -58,7 +58,7 @@ feature -- Element change feature -- Request processing - process_request (a_handler: HTTP_CONNECTION_HANDLER; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM) + process_request (a_handler: HTTP_CONNECTION_HANDLER; a_socket: TCP_STREAM_SOCKET) -- Process request ... local env, vars: HASH_TABLE [STRING, STRING] @@ -161,14 +161,20 @@ feature -- Request processing end end - callback.process_request (env, a_handler.request_header, a_input, a_output) + callback.process_request (env, a_handler.request_header, a_socket) end add_environment_variable (a_value: detachable STRING; a_var_name: STRING; env: HASH_TABLE [STRING, STRING]) -- Add variable `a_var_name => a_value' to `env' do if a_value /= Void then - env.force (a_value, a_var_name) + if env.has_key (a_var_name) and then attached env.found_item as l_existing_value then + --| Check http://www.ietf.org/rfc/rfc3875 4.1.18 + check find_proper_rewrite_for_same_header: False end + env.force (l_existing_value + " " + a_value, a_var_name) + else + env.force (a_value, a_var_name) + end end end diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e index 95fb8cbd..48493327 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e @@ -16,36 +16,71 @@ create feature {NONE} -- Initialization - make (a_nino_input: like nino_input) + make (a_source: like source) do create last_string.make_empty - set_nino_input (a_nino_input) + set_source (a_source) end feature {WGI_NINO_CONNECTOR, WGI_APPLICATION} -- Nino - set_nino_input (i: like nino_input) + set_source (i: like source) do - nino_input := i + source := i end - nino_input: HTTP_INPUT_STREAM + source: TCP_STREAM_SOCKET -feature -- Basic operation +feature -- Input - read_stream (nb_char: INTEGER) - -- Read a string of at most `nb_char' bound characters - -- or until end of file. - -- Make result available in `last_string'. + read_character + -- Read the next character in input stream. + -- Make the result available in `last_character'. + local + s: detachable STRING do - nino_input.read_stream (nb_char) - last_string := nino_input.last_string + if source.socket_ok then + source.read_character + last_character := source.last_character + else + last_character := '%U' + end end -feature -- Access + read_string (nb: INTEGER) + do + last_string.wipe_out + if source.socket_ok then + source.read_stream_thread_aware (nb) + last_string.append_string (source.last_string) + end + end - last_string: STRING - -- Last string read +feature -- Access + + last_string: STRING_8 + -- Last string read + -- (Note: this query always 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 input objects.) + + last_character: CHARACTER_8 + -- Last item read + +feature -- Status report + + is_open_read: BOOLEAN + -- Can items be read from input stream? + do + Result := source.is_open_read + end + + end_of_input: BOOLEAN + -- Has the end of input stream been reached? + do + Result := source.ready_for_reading + end ;note copyright: "2011-2011, Eiffel Software and others" diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e index fd13d180..559f7380 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e @@ -10,6 +10,9 @@ class inherit WGI_OUTPUT_STREAM + redefine + put_character_8 + end HTTP_STATUS_CODE_MESSAGES export @@ -21,19 +24,19 @@ create feature {NONE} -- Initialization - make (a_nino_output: like nino_output) + make (a_target: like target) do - set_nino_output (a_nino_output) + set_target (a_target) end feature {WGI_NINO_CONNECTOR, WGI_APPLICATION} -- Nino - set_nino_output (o: like nino_output) + set_target (o: like target) do - nino_output := o + target := o end - nino_output: HTTP_OUTPUT_STREAM + target: TCP_STREAM_SOCKET feature -- Status writing @@ -55,15 +58,31 @@ feature -- Status writing put_header_line (s) end -feature -- Basic operation +feature -- Output put_string (s: STRING_8) -- Send `s' to http client do - debug ("nino") - print (s) - end - nino_output.put_string (s) + target.put_string (s) + end + + put_character_8 (c: CHARACTER_8) + do + target.put_character (c) + end + +feature -- Status report + + is_open_write: BOOLEAN + -- Can items be written to output stream? + do + Result := target.is_open_write + end + +feature -- Basic operations + + flush + do end note diff --git a/library/server/ewsgi/src/helper/wgi_request_from_table.e b/library/server/ewsgi/src/helper/wgi_request_from_table.e index a39b1c12..8055c7b2 100644 --- a/library/server/ewsgi/src/helper/wgi_request_from_table.e +++ b/library/server/ewsgi/src/helper/wgi_request_from_table.e @@ -336,7 +336,7 @@ feature {NONE} -- I/O: implementation read_input (nb: INTEGER) -- Read `nb' bytes from `input' do - input.read_stream (nb) + input.read_string (nb) end last_input_string: STRING diff --git a/library/server/ewsgi/src/wgi_input_stream.e b/library/server/ewsgi/src/wgi_input_stream.e index bde896d6..91a2a988 100644 --- a/library/server/ewsgi/src/wgi_input_stream.e +++ b/library/server/ewsgi/src/wgi_input_stream.e @@ -11,21 +11,108 @@ 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 + ensure + same_last_string_reference: last_string = old last_string + end + + read_string (nb: INTEGER) + 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 + same_last_string_reference: last_string = old last_string + 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 + same_last_string_reference: last_string = old last_string + end + feature -- Access last_string: STRING_8 - -- Last read string from stream + -- Last string read + -- (Note: this query always 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 +feature -- Status report - read_stream (n: INTEGER) - 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 - ensure - at_max_n: last_string.count <= n end note diff --git a/library/server/ewsgi/src/wgi_output_stream.e b/library/server/ewsgi/src/wgi_output_stream.e index fe1b677d..35be6389 100644 --- a/library/server/ewsgi/src/wgi_output_stream.e +++ b/library/server/ewsgi/src/wgi_output_stream.e @@ -11,18 +11,70 @@ 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: 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: STRING; 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 + + put_file_content (fn: STRING) + -- Send the content of file `fn' + require + string_not_empty: not fn.is_empty + is_readable: (create {RAW_FILE}.make (fn)).is_readable + local + f: RAW_FILE + do + create f.make (fn) + check f.exists and then f.is_readable end + + f.open_read + from + until + f.exhausted + loop + f.read_stream (4096) + put_string (f.last_string) + end + f.close + end + +feature -- Specific output + + put_header_line (s: STRING) + -- Send `s' to http client as header line + do + put_string (s) + put_string ("%R%N") end feature -- Status writing @@ -34,41 +86,20 @@ 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 - --| Could be redefined for optimization + 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)) - end - - put_file_content (fn: STRING) - -- Send the content of file `fn' - local - f: RAW_FILE - do - create f.make (fn) - if f.exists and then f.is_readable then - f.open_read - from - until - f.exhausted - loop - f.read_stream (4096) - put_string (f.last_string) - end - f.close - end - end - - put_header_line (s: STRING) - -- Send `s' to http client as header line - do - put_string (s) - put_string ("%R%N") + is_open_write: is_open_write + deferred end note diff --git a/library/server/libfcgi/implementation/windows/fcgi_imp.e b/library/server/libfcgi/implementation/windows/fcgi_imp.e index 8c35d3f5..9e49a25c 100644 --- a/library/server/libfcgi/implementation/windows/fcgi_imp.e +++ b/library/server/libfcgi/implementation/windows/fcgi_imp.e @@ -28,6 +28,11 @@ feature -- Access Result := fcgi.environ end + fcgi_end_of_input: BOOLEAN + do + Result := fcgi.feof (fcgi.stdin) = 0 + end + -- updated_environ_variables: HASH_TABLE [STRING, STRING] -- local ---- n, l_size, diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index c1e61c6b..9878c73a 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -1495,8 +1495,8 @@ feature {NONE} -- Internal value until n <= 0 loop - read_input (n) - t := last_input_string + input.read_string (n) + t := input.last_string Result.append_string (t) if t.count < n then n := 0 @@ -1514,20 +1514,6 @@ feature {NONE} -- Internal value internal_cookies_table: detachable like cookies_table -- cached value for `cookies' -feature {NONE} -- I/O: implementation - - read_input (nb: INTEGER) - -- Read `nb' bytes from `input' - do - input.read_stream (nb) - end - - last_input_string: STRING - -- Last string read from `input' - do - Result := input.last_string - end - feature {NONE} -- Implementation report_bad_request_error (a_message: detachable STRING) diff --git a/tests/compile_all.ini b/tests/compile_all.ini index f15d0884..2246980d 100644 --- a/tests/compile_all.ini +++ b/tests/compile_all.ini @@ -6,4 +6,6 @@ [$COMPILE_ALL_BASEDIR/ext] [$COMPILE_ALL_BASEDIR\ext] +[regexp=(\\|\/)crypto$] +