diff --git a/ext/server/nino b/ext/server/nino index de778025..4a87d582 160000 --- a/ext/server/nino +++ b/ext/server/nino @@ -1 +1 @@ -Subproject commit de77802546317cb7561c7172e777ff9bcce50393 +Subproject commit 4a87d5822bdc86082ee4fbaef12b886c60fd3c33 diff --git a/library/error/license.lic b/library/error/license.lic index c929225f..cf2d1ed9 100644 --- a/library/error/license.lic +++ b/library/error/license.lic @@ -1 +1,10 @@ -reference:forum2 +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, 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 + ]" diff --git a/library/protocol/http/license.lic b/library/protocol/http/license.lic new file mode 100644 index 00000000..cf2d1ed9 --- /dev/null +++ b/library/protocol/http/license.lic @@ -0,0 +1,10 @@ +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, 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 + ]" diff --git a/library/server/ewsgi/connectors/cgi/license.lic b/library/server/ewsgi/connectors/cgi/license.lic index c929225f..cf2d1ed9 100644 --- a/library/server/ewsgi/connectors/cgi/license.lic +++ b/library/server/ewsgi/connectors/cgi/license.lic @@ -1 +1,10 @@ -reference:forum2 +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, 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 + ]" diff --git a/library/server/ewsgi/connectors/cgi/src/gw_cgi_connector.e b/library/server/ewsgi/connectors/cgi/src/gw_cgi_connector.e index d229eee7..9d85012b 100644 --- a/library/server/ewsgi/connectors/cgi/src/gw_cgi_connector.e +++ b/library/server/ewsgi/connectors/cgi/src/gw_cgi_connector.e @@ -24,7 +24,7 @@ feature -- Execution end note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/cgi/src/gw_cgi_output_stream.e b/library/server/ewsgi/connectors/cgi/src/gw_cgi_output_stream.e index 7a05d8ca..072caa99 100644 --- a/library/server/ewsgi/connectors/cgi/src/gw_cgi_output_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/gw_cgi_output_stream.e @@ -10,6 +10,9 @@ class inherit GW_OUTPUT_STREAM + undefine + flush + end CONSOLE rename diff --git a/library/server/ewsgi/connectors/libfcgi/license.lic b/library/server/ewsgi/connectors/libfcgi/license.lic index c929225f..cf2d1ed9 100644 --- a/library/server/ewsgi/connectors/libfcgi/license.lic +++ b/library/server/ewsgi/connectors/libfcgi/license.lic @@ -1 +1,10 @@ -reference:forum2 +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, 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 + ]" diff --git a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_connector.e b/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_connector.e index 91def76e..aa2a8a52 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_connector.e +++ b/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_connector.e @@ -68,7 +68,7 @@ invariant fcgi_attached: fcgi /= Void note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_input_stream.e b/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_input_stream.e index 75db59d7..5f757c0a 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_input_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_input_stream.e @@ -53,7 +53,7 @@ feature {NONE} -- Implementation -- Bridge to FCGI world note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software @@ -62,5 +62,4 @@ note Website http://www.eiffel.com Customer support http://support.eiffel.com ]" - end diff --git a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_output_stream.e b/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_output_stream.e index 331bb763..a26b4b18 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_output_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_output_stream.e @@ -31,10 +31,6 @@ feature -- Basic operation fcgi.put_string (s) end - flush - do - end - feature {NONE} -- Implementation fcgi: FCGI @@ -44,7 +40,7 @@ invariant fcgi_attached: fcgi /= Void note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/nino/license.lic b/library/server/ewsgi/connectors/nino/license.lic index c929225f..cf2d1ed9 100644 --- a/library/server/ewsgi/connectors/nino/license.lic +++ b/library/server/ewsgi/connectors/nino/license.lic @@ -1 +1,10 @@ -reference:forum2 +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, 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 + ]" diff --git a/library/server/ewsgi/connectors/nino/src/gw_nino_connector.e b/library/server/ewsgi/connectors/nino/src/gw_nino_connector.e index c14bcc8a..3d7ea435 100644 --- a/library/server/ewsgi/connectors/nino/src/gw_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/gw_nino_connector.e @@ -81,7 +81,7 @@ feature -- Server end note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/nino/src/gw_nino_input_stream.e b/library/server/ewsgi/connectors/nino/src/gw_nino_input_stream.e index a5f97038..8a02f0d3 100644 --- a/library/server/ewsgi/connectors/nino/src/gw_nino_input_stream.e +++ b/library/server/ewsgi/connectors/nino/src/gw_nino_input_stream.e @@ -22,7 +22,7 @@ feature {NONE} -- Initialization set_nino_input (a_nino_input) end -feature {GW_NINO_APPLICATION} -- Nino +feature {GW_NINO_CONNECTOR, GW_APPLICATION} -- Nino set_nino_input (i: like nino_input) do @@ -48,7 +48,7 @@ feature -- Access -- Last string read ;note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/connectors/nino/src/gw_nino_output_stream.e b/library/server/ewsgi/connectors/nino/src/gw_nino_output_stream.e index ff4b3e75..045d07ce 100644 --- a/library/server/ewsgi/connectors/nino/src/gw_nino_output_stream.e +++ b/library/server/ewsgi/connectors/nino/src/gw_nino_output_stream.e @@ -21,7 +21,7 @@ feature {NONE} -- Initialization set_nino_output (a_nino_output) end -feature {GW_NINO_APPLICATION} -- Nino +feature {GW_NINO_CONNECTOR, GW_APPLICATION} -- Nino set_nino_output (o: like nino_output) do @@ -41,11 +41,6 @@ feature -- Basic operation nino_output.put_string (s) end - flush - -- Flush the output stream - do - end - note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" @@ -56,5 +51,4 @@ note Website http://www.eiffel.com Customer support http://support.eiffel.com ]" - end diff --git a/library/server/ewsgi/ewsgi-full.ecf b/library/server/ewsgi/ewsgi-full.ecf new file mode 100644 index 00000000..e27b6aaa --- /dev/null +++ b/library/server/ewsgi/ewsgi-full.ecf @@ -0,0 +1,23 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + + diff --git a/library/server/ewsgi/examples/hello_world/src/hello_world.e b/library/server/ewsgi/examples/hello_world/src/hello_world.e index 59649b48..a9add13c 100644 --- a/library/server/ewsgi/examples/hello_world/src/hello_world.e +++ b/library/server/ewsgi/examples/hello_world/src/hello_world.e @@ -55,4 +55,14 @@ feature -- Execution end end +note + copyright: "2011-2011, 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/src/gw_application.e b/library/server/ewsgi/src/gw_application.e index 28cdf494..b9e895f9 100644 --- a/library/server/ewsgi/src/gw_application.e +++ b/library/server/ewsgi/src/gw_application.e @@ -8,22 +8,56 @@ note deferred class GW_APPLICATION -feature -- Execution +feature -- Process request process (env: GW_ENVIRONMENT; a_input: GW_INPUT_STREAM; a_output: GW_OUTPUT_STREAM) -- Process request with environment `env', and i/o streams `a_input' and `a_output' + local + rescued: BOOLEAN + ctx: detachable GW_REQUEST_CONTEXT do - execute (new_request_context (env, a_input, a_output)) + if not rescued then + pre_execute (env) + ctx := new_request_context (env, a_input, a_output) + execute (ctx) + post_execute (ctx) + else + rescue_execute (ctx, (create {EXCEPTION_MANAGER}).last_exception) + end end +feature {NONE} -- Execution + execute (ctx: GW_REQUEST_CONTEXT) -- Execute the request deferred end + pre_execute (env: GW_ENVIRONMENT) + -- Operation processed before `execute' + require + env_attached: env /= Void + do + end + + post_execute (ctx: detachable GW_REQUEST_CONTEXT) + -- Operation processed after `execute', or after `rescue_execute' + do + end + + rescue_execute (ctx: detachable GW_REQUEST_CONTEXT; a_exception: detachable EXCEPTION) + -- Operation processed on rescue of `execute' + do + post_execute (ctx) + end + feature -- Factory new_request_context (env: GW_ENVIRONMENT; a_input: GW_INPUT_STREAM; a_output: GW_OUTPUT_STREAM): GW_REQUEST_CONTEXT + -- New Gateway Context based on `env' `a_input' and `a_output' + --| note: you can redefine this function to create your own + --| descendant of GW_REQUEST_CONTEXT , or even to reuse/recycle existing + --| instance of GW_REQUEST_CONTEXT deferred end diff --git a/library/server/ewsgi/src/gw_error.e b/library/server/ewsgi/src/gw_error.e index 3cc1caf8..61823e9e 100644 --- a/library/server/ewsgi/src/gw_error.e +++ b/library/server/ewsgi/src/gw_error.e @@ -54,7 +54,7 @@ feature -- Visitor end note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/ewsgi/src/implementation/gw_request_context_imp.e b/library/server/ewsgi/src/implementation/gw_request_context_imp.e index cdd83630..56f8f1c0 100644 --- a/library/server/ewsgi/src/implementation/gw_request_context_imp.e +++ b/library/server/ewsgi/src/implementation/gw_request_context_imp.e @@ -45,7 +45,6 @@ feature {NONE} -- Initialization -- Specific initialization local p: INTEGER - dt: DATE_TIME env: like environment do env := environment diff --git a/library/server/ewsgi/src/response/gw_header.e b/library/server/ewsgi/src/response/gw_header.e new file mode 100644 index 00000000..156b6165 --- /dev/null +++ b/library/server/ewsgi/src/response/gw_header.e @@ -0,0 +1,407 @@ +note + description: "Summary description for {GW_HEADER}." + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +class + GW_HEADER + +inherit + HTTP_STATUS_CODE_MESSAGES + +create + make + +feature {NONE} -- Initialization + + make + -- Initialize current + do + create {ARRAYED_LIST [STRING]} headers.make (3) + http_version := "HTTP/1.1" + end + +feature -- Recycle + + recycle + do + status_code := 0 + status_message := Void + http_version := "HTTP/1.1" + headers.wipe_out + end + +feature -- Access + + headers: LIST [STRING] + -- Header's lines + + send_to (a_output: GW_OUTPUT_STREAM) + -- Send Current string representation to `a_output' + do + a_output.put_string (string) + --| TO OPTIMIZE + end + + string: STRING + -- String representation of the headers + local + l_headers: like headers + h: STRING + do + create Result.make (32) + create h.make (16) + h.append_string (http_version) + h.append_character (' ') + h.append_integer (status_code) + h.append_character (' ') + if attached status_message as l_status_message then + h.append_string (l_status_message) + end + append_line_to (h, Result) + + l_headers := headers + if l_headers.is_empty then + put_content_type_text_html + else + from + l_headers.start + until + l_headers.after + loop + append_line_to (l_headers.item, Result) + l_headers.forth + end + end + append_end_of_line_to (Result) + end + +feature -- Header change: general + + add_header (h: STRING) + do + headers.force (h) + end + + put_header (h: STRING) + -- Add header `h' or replace existing header of same header name + do + force_header_by_name (header_name (h), h) + end + + add_header_key_value (k,v: STRING) + -- Add header `k:v', or replace existing header of same header name/key + do + add_header (k + colon_space + v) + end + + put_header_key_value (k,v: STRING) + -- Add header `k:v', or replace existing header of same header name/key + do + put_header (k + colon_space + v) + end + +feature -- Content related header + + put_content_type (t: STRING) + do + put_header_key_value (name_content_type, t) + end + + add_content_type (t: STRING) + -- same as `put_content_type', but allow multiple definition of "Content-Type" + do + add_header_key_value (name_content_type, t) + end + + put_content_type_with_name (t: STRING; n: STRING) + do + put_header_key_value (name_content_type, t + "; name=%"" + n + "%"") + end + + add_content_type_with_name (t: STRING; n: STRING) + -- same as `put_content_type_with_name', but allow multiple definition of "Content-Type" + do + add_header_key_value (name_content_type, t + "; name=%"" + n + "%"") + end + + put_content_type_text_css do put_content_type ("text/css") end + put_content_type_text_csv do put_content_type ("text/csv") end + put_content_type_text_html do put_content_type ("text/html") end + put_content_type_text_javascript do put_content_type ("text/javascript") end + put_content_type_text_json do put_content_type ("text/json") end + put_content_type_text_plain do put_content_type ("text/plain") end + put_content_type_text_xml do put_content_type ("text/xml") end + + put_content_type_application_json do put_content_type ("application/json") end + put_content_type_application_javascript do put_content_type ("application/javascript") end + put_content_type_application_zip do put_content_type ("application/zip") end + + put_content_type_image_gif do put_content_type ("image/gif") end + put_content_type_image_png do put_content_type ("image/png") end + put_content_type_image_jpg do put_content_type ("image/jpg") end + put_content_type_image_svg_xml do put_content_type ("image/svg+xml") end + + put_content_type_message_http do put_content_type ("message/http") end + + put_content_type_multipart_mixed do put_content_type ("multipart/mixed") end + put_content_type_multipart_alternative do put_content_type ("multipart/alternative") end + put_content_type_multipart_related do put_content_type ("multipart/related") end + put_content_type_multipart_form_data do put_content_type ("multipart/form-data") end + put_content_type_multipart_signed do put_content_type ("multipart/signed") end + put_content_type_multipart_encrypted do put_content_type ("multipart/encrypted") end + + + put_content_length (n: INTEGER) + do + put_header_key_value (name_content_length, n.out) + end + + put_content_transfer_encoding (a_mechanism: STRING) + -- Put "Content-Transfer-Encoding" header with for instance "binary" + --| encoding := "Content-Transfer-Encoding" ":" mechanism + --| + --| mechanism := "7bit" ; case-insensitive + --| / "quoted-printable" + --| / "base64" + --| / "8bit" + --| / "binary" + --| / x-token + + do + put_header_key_value ("Content-Transfer-Encoding", a_mechanism) + end + + put_content_disposition (a_type: STRING; a_params: detachable STRING) + -- Put "Content-Disposition" header + --| See RFC2183 + --| disposition := "Content-Disposition" ":" + --| disposition-type + --| *(";" disposition-parm) + --| disposition-type := "inline" + --| / "attachment" + --| / extension-token + --| ; values are not case-sensitive + --| disposition-parm := filename-parm + --| / creation-date-parm + --| / modification-date-parm + --| / read-date-parm + --| / size-parm + --| / parameter + --| filename-parm := "filename" "=" value + --| creation-date-parm := "creation-date" "=" quoted-date-time + --| modification-date-parm := "modification-date" "=" quoted-date-time + --| read-date-parm := "read-date" "=" quoted-date-time + --| size-parm := "size" "=" 1*DIGIT + --| quoted-date-time := quoted-string + --| ; contents MUST be an RFC 822 `date-time' + --| ; numeric timezones (+HHMM or -HHMM) MUST be used + do + if a_params /= Void then + put_header_key_value ("Content-Disposition", a_type + "; " + a_params) + else + put_header_key_value ("Content-Disposition", a_type) + end + end + +feature -- Status, ... + + status_code: INTEGER + -- Status + + status_message: detachable STRING + -- Optional reason + + http_version: STRING + -- HTTP version + + put_status (a_code: INTEGER) + do + status_code := a_code + status_message := http_status_code_message (a_code) + end + +feature -- Others + + put_expires (n: INTEGER) + do + put_header_key_value ("Expires", n.out) + end + + put_cache_control (s: STRING) + -- `s' could be for instance "no-cache, must-revalidate" + do + put_header_key_value ("Cache-Control", s) + end + + put_pragma (s: STRING) + do + put_header_key_value ("Pragma", s) + end + + put_pragma_no_cache + do + put_pragma ("no-cache") + end + +feature -- Redirection + + put_redirection (a_location: STRING; a_code: INTEGER) + do + if a_code > 0 then + put_status (a_code) + else + put_status (302) -- Found + end + put_header_key_value ("Location", a_location) + end + + put_refresh (a_location: STRING; a_timeout: INTEGER; a_code: INTEGER) + do + if a_code > 0 then + put_status (a_code) + else + put_status (200) -- Ok + end + put_header_key_value ("Refresh", a_timeout.out + "; url=" + a_location) + end + +feature -- Cookie + + put_cookie (key, value: STRING_8; expiration, path, domain, secure: detachable STRING_8) + -- Set a cookie on the client's machine + -- with key 'key' and value 'value'. + require + make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty) + local + s: STRING + do + s := "Set-Cookie:" + key + "=" + value + if expiration /= Void then + s.append (";expires=" + expiration) + end + if path /= Void then + s.append (";path=" + path) + end + if domain /= Void then + s.append (";domain=" + domain) + end + if secure /= Void then + s.append (";secure=" + secure) + end + add_header (s) + end + +feature -- Status report + + has_header_named (a_name: STRING): BOOLEAN + -- Has header item for `n'? + local + c: like headers.new_cursor + n: INTEGER + do + from + n := a_name.count + c := headers.new_cursor + until + c.after or Result + loop + Result := c.item.starts_with (a_name) and then c.item [n + 1] = ':' + c.forth + end + end + + has_content_length: BOOLEAN + -- Has header "content_length" + do + Result := has_header_named (name_content_length) + end + +feature {NONE} -- Implementation: Header + + force_header_by_name (n: detachable STRING; h: STRING) + -- 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) + local + l_headers: like headers + do + if n /= Void then + from + l_headers := headers + l_headers.start + until + l_headers.after or l_headers.item.starts_with (n) + loop + l_headers.forth + end + if not l_headers.after then + l_headers.replace (h) + else + add_header (h) + end + else + add_header (h) + end + end + + header_name (h: STRING): detachable STRING + -- If any, header's name with colon + --| ex: for "Foo-bar: something", this will return "Foo-bar:" + local + i,n: INTEGER + c: CHARACTER + do + from + i := 1 + n := h.count + create Result.make (10) + until + i > n or c = ':' or Result = Void + loop + c := h[i] + inspect c + when ':' then + Result.extend (c) + when '-', 'a' .. 'z', 'A' .. 'Z' then + Result.extend (c) + else + Result := Void + end + i := i + 1 + end + end + +feature {NONE} -- Implementation + + append_line_to (s, h: STRING) + do + h.append_string (s) + append_end_of_line_to (h) + end + + append_end_of_line_to (h: like string) + do + h.append_character ('%R') + h.append_character ('%N') + end + +feature {NONE} -- Constants + + colon_space: STRING = ": " + name_content_length: STRING = "Content-Length" + name_content_type: STRING = "Content-Type" + +note + copyright: "2011-2011, 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/src/stream/gw_output_stream.e b/library/server/ewsgi/src/stream/gw_output_stream.e index cb87ee46..0ed8d0af 100644 --- a/library/server/ewsgi/src/stream/gw_output_stream.e +++ b/library/server/ewsgi/src/stream/gw_output_stream.e @@ -10,7 +10,7 @@ note deferred class GW_OUTPUT_STREAM -feature -- Basic operation +feature -- Core operation put_string (s: STRING_8) -- Write `s' into the output stream @@ -21,7 +21,55 @@ feature -- Basic operation flush -- Flush the output stream - deferred + do + end + +feature -- Basic operation + + 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 (1024) + put_string (f.last_string) + end + f.close + end + end + + put_header (a_status: INTEGER; a_headers: ARRAY [TUPLE [key: STRING; value: STRING]]) + -- Send headers with status `a_status', and headers from `a_headers' + local + h: GW_HEADER + i,n: INTEGER + do + create h.make + h.put_status (a_status) + from + i := a_headers.lower + n := a_headers.upper + until + i > n + loop + h.put_header_key_value (a_headers[i].key, a_headers[i].value) + i := i + 1 + end + put_string (h.string) + end + + put_header_line (s: STRING) + -- Send `s' to http client as header line + do + put_string (s) + put_string ("%R%N") end note diff --git a/library/text/encoder/license.lic b/library/text/encoder/license.lic index c929225f..cf2d1ed9 100644 --- a/library/text/encoder/license.lic +++ b/library/text/encoder/license.lic @@ -1 +1,10 @@ -reference:forum2 +${NOTE_KEYWORD} + copyright: "2011-${YEAR}, 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 + ]"