diff --git a/CHANGELOGS.txt b/CHANGELOGS.txt new file mode 100644 index 00000000..30faa5c0 --- /dev/null +++ b/CHANGELOGS.txt @@ -0,0 +1,9 @@ +History for Eiffel-Web-Framework + +[2011-09-07] Jocelyn + * library "router": now routing depends on uri (or uri template) and request methods + * Nino connector: Fixed issue where HTTP_ prefix were missing for header meta variable. + +[2011-09-07] Jocelyn + * changelog: starting to write down changelogs file + diff --git a/doc/wiki b/doc/wiki index a2a1f892..820bd7bd 160000 --- a/doc/wiki +++ b/doc/wiki @@ -1 +1 @@ -Subproject commit a2a1f89299a9fd1ff3078052e4c7917c329d27ed +Subproject commit 820bd7bd6fab591691ff5c0560452c2783c8549e diff --git a/examples/hello_routed_world/hello-safe.ecf b/examples/hello_routed_world/hello-safe.ecf index ceaf6e38..ec8e1532 100644 --- a/examples/hello_routed_world/hello-safe.ecf +++ b/examples/hello_routed_world/hello-safe.ecf @@ -8,16 +8,17 @@ /\.svn$ - + + + - - diff --git a/examples/hello_routed_world/src/framework/routed_application_helper.e b/examples/hello_routed_world/src/framework/routed_application_helper.e index a0430b11..92349a8b 100644 --- a/examples/hello_routed_world/src/framework/routed_application_helper.e +++ b/examples/hello_routed_world/src/framework/routed_application_helper.e @@ -17,11 +17,11 @@ inherit feature -- Helper - execute_content_type_not_allowed (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER; a_content_types: detachable ARRAY [STRING]; a_uri_formats: detachable ARRAY [STRING]) + execute_content_type_not_allowed (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_content_types: detachable ARRAY [STRING]; a_uri_formats: detachable ARRAY [STRING]) local s, uri_s: detachable STRING i, n: INTEGER - h: GW_HEADER + h: EWF_HEADER do create h.make h.put_status ({HTTP_STATUS_CODE}.unsupported_media_type) @@ -60,6 +60,8 @@ feature -- Helper i := i + 1 end end + res.set_status_code ({HTTP_STATUS_CODE}.unsupported_media_type) + res.write_headers_string (h.string) if s /= Void then res.write_string ("Unsupported request content-type, Accept: " + s + "%N") end @@ -68,7 +70,7 @@ feature -- Helper end end - execute_method_not_allowed (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER; a_methods: ARRAY [STRING]) + execute_method_not_allowed (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_methods: ARRAY [STRING]) local s: STRING i, n: INTEGER @@ -114,7 +116,7 @@ feature -- Context helper end end - content_type_to_request_format (a_content_type: detachable STRING): detachable STRING + content_type_to_request_format (a_content_type: detachable READABLE_STRING_8): detachable STRING -- `a_content_type' converted into a request format name do if a_content_type /= Void then diff --git a/examples/hello_routed_world/src/hello_routed_world.e b/examples/hello_routed_world/src/hello_routed_world.e index 2ee1f52a..d643869d 100644 --- a/examples/hello_routed_world/src/hello_routed_world.e +++ b/examples/hello_routed_world/src/hello_routed_world.e @@ -14,7 +14,7 @@ inherit ROUTED_APPLICATION_HELPER - DEFAULT_EWSGI_APPLICATION + DEFAULT_WGI_APPLICATION create make @@ -30,6 +30,11 @@ feature {NONE} -- Initialization create_router do + debug + create {REQUEST_URI_ROUTER} router.make (5) + create {REQUEST_URI_TEMPLATE_ROUTER} router.make (5) + end + -- create {REQUEST_URI_ROUTER} router.make (5) create {REQUEST_URI_TEMPLATE_ROUTER} router.make (5) end @@ -48,13 +53,19 @@ feature {NONE} -- Initialization create ra.make (agent handle_anonymous_hello) router.map ("/hello", ra) router.map ("/hello.{format}", ra) + + router.map_agent_with_request_methods ("/method/any", agent handle_method_any, Void) + router.map_agent_with_request_methods ("/method/guess", agent handle_method_get_or_post, <<"GET", "POST">>) + router.map_agent_with_request_methods ("/method/custom", agent handle_method_get, <<"GET">>) + router.map_agent_with_request_methods ("/method/custom", agent handle_method_post, <<"POST">>) + end feature -- Execution - execute_default (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) local - h: GW_HEADER + h: EWF_HEADER l_url: STRING e: EXECUTION_ENVIRONMENT n: INTEGER @@ -65,7 +76,7 @@ feature -- Execution n := 3 h.put_refresh (l_url, 5, 200) res.set_status_code (200) - res.write_string (h.string) + res.write_headers_string (h.string) from create e until @@ -97,7 +108,7 @@ feature -- Execution res.flush end - execute_home (ctx: REQUEST_HANDLER_CONTEXT; req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute_home (ctx: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) do res.write_header (200, <<["Content-Type", "text/html"]>>) res.write_string ("Hello World ?!%N") @@ -111,17 +122,17 @@ feature -- Execution res.write_string ("
  • /hello/Joce
  • %N") res.write_string ("%N") - if attached req.environment_variable ("REQUEST_COUNT") as rqc then + if attached req.parameter ("REQUEST_COUNT") as rqc then res.write_string ("request #"+ rqc + "%N") end res.write_string ("%N") end - execute_hello (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER; a_name: detachable STRING_32; ctx: REQUEST_HANDLER_CONTEXT) + execute_hello (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_name: detachable READABLE_STRING_32; ctx: REQUEST_HANDLER_CONTEXT) local l_response_content_type: detachable STRING msg: STRING - h: GW_HEADER + h: EWF_HEADER content_type_supported: ARRAY [STRING] do if a_name /= Void then @@ -152,7 +163,7 @@ feature -- Execution h.put_content_type (l_response_content_type) h.put_content_length (msg.count) res.set_status_code (200) - res.write_string (h.string) + res.write_headers_string (h.string) -- res.write_header (200, << -- ["Content-Type", l_response_content_type], -- ["Content-Length", msg.count.out @@ -161,16 +172,39 @@ feature -- Execution end end - handle_hello (ctx: REQUEST_HANDLER_CONTEXT; req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + handle_hello (ctx: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) do execute_hello (req, res, Void, ctx) end - handle_anonymous_hello (ctx: REQUEST_HANDLER_CONTEXT; req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + handle_anonymous_hello (ctx: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) do execute_hello (req, res, ctx.parameter ("name"), ctx) end + handle_method_any (ctx: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do + execute_hello (req, res, req.request_method, ctx) + end + + handle_method_get (ctx: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do + execute_hello (req, res, "GET", ctx) + end + + + handle_method_post (ctx: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do + execute_hello (req, res, "POST", ctx) + end + + handle_method_get_or_post (ctx: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do + execute_hello (req, res, "GET or POST", ctx) + end + + + note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/error/src/error_handler.e b/library/error/src/error_handler.e index 1a124b49..9234990a 100644 --- a/library/error/src/error_handler.e +++ b/library/error/src/error_handler.e @@ -8,6 +8,11 @@ note class ERROR_HANDLER +inherit + ANY + + DEBUG_OUTPUT + create make @@ -35,6 +40,18 @@ feature -- Status errors: LIST [ERROR] -- Errors container +feature -- Status report + + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + if has_error then + Result := count.out + " errors" + else + Result := "no error" + end + end + feature -- Basic operation add_error (a_error: ERROR) @@ -52,6 +69,12 @@ feature -- Basic operation add_error (e) end + append (a_err_handler: ERROR_HANDLER) + -- Append errors from `a_err_handler' + do + errors.append (a_err_handler.errors) + end + feature -- Access as_single_error: detachable ERROR @@ -61,6 +84,20 @@ feature -- Access elseif count > 0 then Result := errors.first end + ensure + has_error_implies_result_attached: has_error implies Result /= Void + end + + as_string_representation: STRING + require + has_error + do + if attached as_single_error as e then + Result := e.string_representation + else + check has_error: False end + Result := "Error occured" + end end feature -- Element changes diff --git a/library/protocol/uri_template/src/uri_template.e b/library/protocol/uri_template/src/uri_template.e index 0f6e3d4c..ddc9d0c6 100644 --- a/library/protocol/uri_template/src/uri_template.e +++ b/library/protocol/uri_template/src/uri_template.e @@ -163,7 +163,7 @@ feature -- Match exp: URI_TEMPLATE_EXPRESSION vn, s,t: STRING vv: STRING - l_vars, l_path_vars, l_query_vars: HASH_TABLE [STRING, STRING] + l_vars, l_path_vars, l_query_vars: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] l_uri_count: INTEGER tpl_count: INTEGER l_next_literal_separator: detachable STRING @@ -358,7 +358,7 @@ feature {NONE} -- Implementation end end - import_path_style_parameters_into (a_content: STRING; res: HASH_TABLE [STRING, STRING]) + import_path_style_parameters_into (a_content: STRING; res: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL]) require a_content_attached: a_content /= Void res_attached: res /= Void @@ -366,7 +366,7 @@ feature {NONE} -- Implementation import_custom_style_parameters_into (a_content, ';', res) end - import_form_style_parameters_into (a_content: STRING; res: HASH_TABLE [STRING, STRING]) + import_form_style_parameters_into (a_content: STRING; res: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL]) require a_content_attached: a_content /= Void res_attached: res /= Void @@ -374,7 +374,7 @@ feature {NONE} -- Implementation import_custom_style_parameters_into (a_content, '&', res) end - import_custom_style_parameters_into (a_content: STRING; a_separator: CHARACTER; res: HASH_TABLE [STRING, STRING]) + import_custom_style_parameters_into (a_content: STRING; a_separator: CHARACTER; res: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL]) require a_content_attached: a_content /= Void res_attached: res /= Void diff --git a/library/protocol/uri_template/src/uri_template_match_result.e b/library/protocol/uri_template/src/uri_template_match_result.e index 5c2e4f59..92ea6681 100644 --- a/library/protocol/uri_template/src/uri_template_match_result.e +++ b/library/protocol/uri_template/src/uri_template_match_result.e @@ -27,27 +27,27 @@ feature {NONE} -- Initialization feature -- Access - path_variables: HASH_TABLE [STRING, STRING] + path_variables: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] -- Variables being part of the path segments - query_variables: HASH_TABLE [STRING, STRING] + query_variables: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] -- Variables being part of the query segments (i.e: after the ?) feature -- Query - path_variable (n: STRING): detachable STRING + path_variable (n: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- Value related to query variable name `n' do Result := path_variables.item (n) end - query_variable (n: STRING): detachable STRING + query_variable (n: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- Value related to path variable name `n' do Result := query_variables.item (n) end - variable (n: STRING): detachable STRING + variable (n: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- Value related to variable name `n' do Result := query_variable (n) @@ -58,7 +58,7 @@ feature -- Query feature -- Query: url-decoded - url_decoded_query_variable (n: STRING): detachable STRING_32 + url_decoded_query_variable (n: READABLE_STRING_GENERAL): detachable STRING_32 -- Unencoded value related to variable name `n' do if attached query_variable (n) as v then @@ -66,15 +66,15 @@ feature -- Query: url-decoded end end - url_decoded_path_variable (n: STRING): detachable STRING_32 + url_decoded_path_variable (n: READABLE_STRING_GENERAL): detachable STRING_32 -- Unencoded value related to variable name `n' do if attached path_variable (n) as v then Result := url_decoded_string (v) end - end + end - url_decoded_variable (n: STRING): detachable STRING_32 + url_decoded_variable (n: READABLE_STRING_GENERAL): detachable STRING_32 -- Unencoded value related to variable name `n' do if attached variable (n) as v then diff --git a/library/server/ewsgi/connectors/cgi/src/gw_cgi_connector.e b/library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e similarity index 56% rename from library/server/ewsgi/connectors/cgi/src/gw_cgi_connector.e rename to library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e index d4768af1..3a665d43 100644 --- a/library/server/ewsgi/connectors/cgi/src/gw_cgi_connector.e +++ b/library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e @@ -1,14 +1,14 @@ note - description: "Summary description for {GW_CGI_CONNECTOR}." + description: "Summary description for {EWF_CGI_CONNECTOR}." author: "" date: "$Date$" revision: "$Revision$" class - GW_CGI_CONNECTOR + EWF_CGI_CONNECTOR inherit - EWSGI_CONNECTOR + WGI_CONNECTOR create make @@ -17,10 +17,12 @@ feature -- Execution launch local - env: EWSGI_ENVIRONMENT_VARIABLES + req: WGI_REQUEST_FROM_TABLE + res: WGI_RESPONSE_STREAM_BUFFER do - create env.make_with_variables ((create {EXECUTION_ENVIRONMENT}).starting_environment_variables) - application.process (env, create {GW_CGI_INPUT_STREAM}.make, create {GW_CGI_OUTPUT_STREAM}.make) + create req.make ((create {EXECUTION_ENVIRONMENT}).starting_environment_variables, create {EWF_CGI_INPUT_STREAM}.make) + create res.make (create {EWF_CGI_OUTPUT_STREAM}.make) + application.process (req, res) end note diff --git a/library/server/ewsgi/connectors/cgi/src/gw_cgi_input_stream.e b/library/server/ewsgi/connectors/cgi/src/ewf_cgi_input_stream.e similarity index 86% rename from library/server/ewsgi/connectors/cgi/src/gw_cgi_input_stream.e rename to library/server/ewsgi/connectors/cgi/src/ewf_cgi_input_stream.e index 0351cde3..7d09236b 100644 --- a/library/server/ewsgi/connectors/cgi/src/gw_cgi_input_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/ewf_cgi_input_stream.e @@ -1,15 +1,15 @@ note - description: "Summary description for GW_CGI_INPUT_STREAM." + description: "Summary description for EWF_CGI_INPUT_STREAM." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - GW_CGI_INPUT_STREAM + EWF_CGI_INPUT_STREAM inherit - EWSGI_INPUT_STREAM + WGI_INPUT_STREAM CONSOLE rename diff --git a/library/server/ewsgi/connectors/cgi/src/gw_cgi_output_stream.e b/library/server/ewsgi/connectors/cgi/src/ewf_cgi_output_stream.e similarity index 92% rename from library/server/ewsgi/connectors/cgi/src/gw_cgi_output_stream.e rename to library/server/ewsgi/connectors/cgi/src/ewf_cgi_output_stream.e index b506736f..f586a548 100644 --- a/library/server/ewsgi/connectors/cgi/src/gw_cgi_output_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/ewf_cgi_output_stream.e @@ -1,15 +1,15 @@ note - description: "Summary description for GW_CGI_OUTPUT_STREAM." + description: "Summary description for EWF_CGI_OUTPUT_STREAM." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - GW_CGI_OUTPUT_STREAM + EWF_CGI_OUTPUT_STREAM inherit - EWSGI_OUTPUT_STREAM + WGI_OUTPUT_STREAM undefine flush end diff --git a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_connector.e b/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e similarity index 73% rename from library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_connector.e rename to library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e index 401b2794..7354ad6d 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_connector.e +++ b/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e @@ -1,15 +1,15 @@ note - description: "Summary description for {GW_LIBFCGI_CONNECTOR}." + description: "Summary description for {EWF_LIBFCGI_CONNECTOR}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - GW_LIBFCGI_CONNECTOR + EWF_LIBFCGI_CONNECTOR inherit - EWSGI_CONNECTOR + WGI_CONNECTOR redefine initialize end @@ -22,8 +22,8 @@ feature {NONE} -- Initialization initialize do create fcgi.make - create {GW_LIBFCGI_INPUT_STREAM} input.make (fcgi) - create {GW_LIBFCGI_OUTPUT_STREAM} output.make (fcgi) + create {EWF_LIBFCGI_INPUT_STREAM} input.make (fcgi) + create {EWF_LIBFCGI_OUTPUT_STREAM} output.make (fcgi) end feature -- Server @@ -46,18 +46,20 @@ feature -- Execution process_fcgi_request (vars: HASH_TABLE [STRING, STRING]; a_input: like input; a_output: like output) local - gw_env: EWSGI_ENVIRONMENT_VARIABLES + req: WGI_REQUEST_FROM_TABLE + res: WGI_RESPONSE_STREAM_BUFFER do - create gw_env.make_with_variables (vars) - application.process (gw_env, a_input, a_output) + create req.make (vars, a_input) + create res.make (a_output) + application.process (req, res) end feature -- Input/Output - input: EWSGI_INPUT_STREAM + input: WGI_INPUT_STREAM -- Input from client (from httpd server via FCGI) - output: EWSGI_OUTPUT_STREAM + output: WGI_OUTPUT_STREAM -- Output to client (via httpd server/fcgi) feature {NONE} -- Implementation diff --git a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_input_stream.e b/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_input_stream.e similarity index 91% rename from library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_input_stream.e rename to library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_input_stream.e index 918b28c6..494ff28e 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_input_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_input_stream.e @@ -1,15 +1,15 @@ note - description: "Summary description for GW_LIBFCGI_INPUT_STREAM." + description: "Summary description for EWF_LIBFCGI_INPUT_STREAM." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - GW_LIBFCGI_INPUT_STREAM + EWF_LIBFCGI_INPUT_STREAM inherit - EWSGI_INPUT_STREAM + WGI_INPUT_STREAM STRING_HANDLER diff --git a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_output_stream.e b/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_output_stream.e similarity index 92% rename from library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_output_stream.e rename to library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_output_stream.e index 2b9b4a0e..9a5c5a7c 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/gw_libfcgi_output_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_output_stream.e @@ -1,15 +1,15 @@ note - description: "Summary description for {GW_LIBFCGI_OUTPUT_STREAM}." + description: "Summary description for {EWF_LIBFCGI_OUTPUT_STREAM}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - GW_LIBFCGI_OUTPUT_STREAM + EWF_LIBFCGI_OUTPUT_STREAM inherit - EWSGI_OUTPUT_STREAM + WGI_OUTPUT_STREAM HTTP_STATUS_CODE_MESSAGES export diff --git a/library/server/ewsgi/connectors/nino/src/gw_nino_connector.e b/library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e similarity index 74% rename from library/server/ewsgi/connectors/nino/src/gw_nino_connector.e rename to library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e index 010ba4a2..67af8814 100644 --- a/library/server/ewsgi/connectors/nino/src/gw_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e @@ -1,14 +1,14 @@ note - description: "Summary description for {GW_NINO_CONNECTOR}." + description: "Summary description for {EWF_NINO_CONNECTOR}." author: "" date: "$Date$" revision: "$Revision$" class - GW_NINO_CONNECTOR + EWF_NINO_CONNECTOR inherit - EWSGI_CONNECTOR + WGI_CONNECTOR redefine initialize end @@ -62,7 +62,7 @@ feature -- Server local l_http_handler : HTTP_HANDLER do - create {GW_NINO_HANDLER} l_http_handler.make_with_callback (server, "NINO_HANDLER", Current) + create {EWF_NINO_HANDLER} l_http_handler.make_with_callback (server, "NINO_HANDLER", Current) debug ("nino") if attached base as l_base then print ("Base=" + l_base + "%N") @@ -73,11 +73,13 @@ feature -- Server process_request (env: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM) local - gw_env: EWSGI_ENVIRONMENT_VARIABLES + req: WGI_REQUEST_FROM_TABLE + res: WGI_RESPONSE_STREAM_BUFFER do - create gw_env.make_with_variables (env) - gw_env.set_variable ("RAW_HEADER_DATA", a_headers_text) - application.process (gw_env, create {GW_NINO_INPUT_STREAM}.make (a_input), create {GW_NINO_OUTPUT_STREAM}.make (a_output)) + create req.make (env, create {EWF_NINO_INPUT_STREAM}.make (a_input)) + create res.make (create {EWF_NINO_OUTPUT_STREAM}.make (a_output)) + req.set_meta_variable ("RAW_HEADER_DATA", a_headers_text) + application.execute (req, res) end note diff --git a/library/server/ewsgi/connectors/nino/src/gw_nino_handler.e b/library/server/ewsgi/connectors/nino/src/ewf_nino_handler.e similarity index 97% rename from library/server/ewsgi/connectors/nino/src/gw_nino_handler.e rename to library/server/ewsgi/connectors/nino/src/ewf_nino_handler.e index a230d76d..909611ac 100644 --- a/library/server/ewsgi/connectors/nino/src/gw_nino_handler.e +++ b/library/server/ewsgi/connectors/nino/src/ewf_nino_handler.e @@ -5,7 +5,7 @@ note revision : "$Revision$" class - GW_NINO_HANDLER + EWF_NINO_HANDLER inherit HTTP_CONNECTION_HANDLER @@ -23,7 +23,7 @@ feature {NONE} -- Initialization callback := a_callback end - callback: GW_NINO_CONNECTOR + callback: EWF_NINO_CONNECTOR feature -- Access @@ -64,7 +64,7 @@ feature -- Request processing until a_headers_map.after loop - vn := a_headers_map.key_for_iteration.as_upper + vn := "HTTP_" + a_headers_map.key_for_iteration.as_upper vn.replace_substring_all ("-", "_") add_environment_variable (a_headers_map.item_for_iteration, vn, env) a_headers_map.forth diff --git a/library/server/ewsgi/connectors/nino/src/gw_nino_input_stream.e b/library/server/ewsgi/connectors/nino/src/ewf_nino_input_stream.e similarity index 87% rename from library/server/ewsgi/connectors/nino/src/gw_nino_input_stream.e rename to library/server/ewsgi/connectors/nino/src/ewf_nino_input_stream.e index c44723f1..9cc0d4ec 100644 --- a/library/server/ewsgi/connectors/nino/src/gw_nino_input_stream.e +++ b/library/server/ewsgi/connectors/nino/src/ewf_nino_input_stream.e @@ -1,15 +1,15 @@ note - description: "Summary description for {GW_NINO_INPUT_STREAM}." + description: "Summary description for {EWF_NINO_INPUT_STREAM}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - GW_NINO_INPUT_STREAM + EWF_NINO_INPUT_STREAM inherit - EWSGI_INPUT_STREAM + WGI_INPUT_STREAM create make @@ -22,7 +22,7 @@ feature {NONE} -- Initialization set_nino_input (a_nino_input) end -feature {GW_NINO_CONNECTOR, EWSGI_APPLICATION} -- Nino +feature {EWF_NINO_CONNECTOR, WGI_APPLICATION} -- Nino set_nino_input (i: like nino_input) do diff --git a/library/server/ewsgi/connectors/nino/src/gw_nino_output_stream.e b/library/server/ewsgi/connectors/nino/src/ewf_nino_output_stream.e similarity index 90% rename from library/server/ewsgi/connectors/nino/src/gw_nino_output_stream.e rename to library/server/ewsgi/connectors/nino/src/ewf_nino_output_stream.e index 792e3db5..b3b9488d 100644 --- a/library/server/ewsgi/connectors/nino/src/gw_nino_output_stream.e +++ b/library/server/ewsgi/connectors/nino/src/ewf_nino_output_stream.e @@ -1,15 +1,15 @@ note - description: "Summary description for {GW_NINO_OUTPUT_STREAM}." + description: "Summary description for {EWF_NINO_OUTPUT_STREAM}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - GW_NINO_OUTPUT_STREAM + EWF_NINO_OUTPUT_STREAM inherit - EWSGI_OUTPUT_STREAM + WGI_OUTPUT_STREAM HTTP_STATUS_CODE_MESSAGES export @@ -26,7 +26,7 @@ feature {NONE} -- Initialization set_nino_output (a_nino_output) end -feature {GW_NINO_CONNECTOR, EWSGI_APPLICATION} -- Nino +feature {EWF_NINO_CONNECTOR, WGI_APPLICATION} -- Nino set_nino_output (o: like nino_output) do diff --git a/library/server/ewsgi/default/cgi/default_ewsgi_application.e b/library/server/ewsgi/default/cgi/default_wgi_application.e similarity index 78% rename from library/server/ewsgi/default/cgi/default_ewsgi_application.e rename to library/server/ewsgi/default/cgi/default_wgi_application.e index a4860978..e42f84ae 100644 --- a/library/server/ewsgi/default/cgi/default_ewsgi_application.e +++ b/library/server/ewsgi/default/cgi/default_wgi_application.e @@ -1,19 +1,19 @@ note - description: "Summary description for {DEFAULT_EWSGI_APPLICATION}." + description: "Summary description for {DEFAULT_WGI_APPLICATION}." date: "$Date$" revision: "$Revision$" deferred class - DEFAULT_EWSGI_APPLICATION + DEFAULT_WGI_APPLICATION inherit - EWSGI_APPLICATION + WGI_APPLICATION feature {NONE} -- Initialization make_and_launch local - cgi: GW_CGI_CONNECTOR + cgi: EWF_CGI_CONNECTOR do create cgi.make (Current) cgi.launch diff --git a/library/server/ewsgi/default/nino/default_ewsgi_application.e b/library/server/ewsgi/default/nino/default_wgi_application.e similarity index 63% rename from library/server/ewsgi/default/nino/default_ewsgi_application.e rename to library/server/ewsgi/default/nino/default_wgi_application.e index b7dabb28..f396a0fb 100644 --- a/library/server/ewsgi/default/nino/default_ewsgi_application.e +++ b/library/server/ewsgi/default/nino/default_wgi_application.e @@ -1,24 +1,30 @@ note - description: "Summary description for {DEFAULT_EWSGI_APPLICATION}." + description: "Summary description for {DEFAULT_WGI_APPLICATION}." date: "$Date$" revision: "$Revision$" deferred class - DEFAULT_EWSGI_APPLICATION + DEFAULT_WGI_APPLICATION inherit - EWSGI_APPLICATION + WGI_APPLICATION feature {NONE} -- Initialization make_and_launch + local + app: NINO_APPLICATION do - print ("Example: start a Nino web server on port " + port_number.out + ", %Nand reply Hello World for any request such as http://localhost:8123/%N") - (create {NINO_APPLICATION}.make_custom (agent execute, "")).listen (port_number) + port_number := 8123 + print ("Example: start a Nino web server on port " + port_number.out + ", %Nand reply Hello World for any request such as http://localhost:" + port_number.out + "/%N") + create app.make_custom (agent execute, "") + app.listen (port_number) end - port_number: INTEGER = 80 + port_number: INTEGER +invariant + port_number_valid: port_number > 0 note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/default/nino/nino_application.e b/library/server/ewsgi/default/nino/nino_application.e index 90ab66b7..278fc990 100644 --- a/library/server/ewsgi/default/nino/nino_application.e +++ b/library/server/ewsgi/default/nino/nino_application.e @@ -12,22 +12,22 @@ create feature {NONE} -- Implementation - make (a_callback: like {EWSGI_AGENT_APPLICATION}.callback) + make (a_callback: like {WGI_AGENT_APPLICATION}.callback) -- Initialize `Current'. do make_custom (a_callback, Void) end - make_custom (a_callback: like {EWSGI_AGENT_APPLICATION}.callback; a_base_url: detachable STRING) + make_custom (a_callback: like {WGI_AGENT_APPLICATION}.callback; a_base_url: detachable STRING) -- Initialize `Current'. local - app: EWSGI_AGENT_APPLICATION + app: WGI_AGENT_APPLICATION do create app.make (a_callback) create connector.make_with_base (app, a_base_url) end - connector: GW_NINO_CONNECTOR + connector: EWF_NINO_CONNECTOR -- Web server connector feature -- Status settings diff --git a/library/server/ewsgi/ewsgi-safe.ecf b/library/server/ewsgi/ewsgi-safe.ecf index c8014c95..f4127fbf 100644 --- a/library/server/ewsgi/ewsgi-safe.ecf +++ b/library/server/ewsgi/ewsgi-safe.ecf @@ -15,5 +15,7 @@ + + diff --git a/library/server/ewsgi/ewsgi.ecf b/library/server/ewsgi/ewsgi.ecf index 9cdcba23..94a0499c 100644 --- a/library/server/ewsgi/ewsgi.ecf +++ b/library/server/ewsgi/ewsgi.ecf @@ -15,5 +15,7 @@ + + 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 957c10a0..522c0b48 100644 --- a/library/server/ewsgi/examples/hello_world/src/hello_world.e +++ b/library/server/ewsgi/examples/hello_world/src/hello_world.e @@ -18,7 +18,7 @@ feature {NONE} -- Initialization (create {NINO_APPLICATION}.make_custom (agent execute, "")).listen (port_number) end - execute (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) do res.write_header (200, <<["Content-Type", "text/plain"]>>) res.write_string ("Hello World!%N") diff --git a/library/server/ewsgi/examples/hello_world_with_response/hello-safe.ecf b/library/server/ewsgi/examples/hello_world_with_response/hello-safe.ecf index ee350071..f388706e 100644 --- a/library/server/ewsgi/examples/hello_world_with_response/hello-safe.ecf +++ b/library/server/ewsgi/examples/hello_world_with_response/hello-safe.ecf @@ -7,6 +7,7 @@ /\.svn$ @@ -14,15 +15,14 @@ - + - + - diff --git a/library/server/ewsgi/examples/hello_world_with_response/src/hello_world.e b/library/server/ewsgi/examples/hello_world_with_response/src/hello_world.e index 5d574f5c..910a9f5d 100644 --- a/library/server/ewsgi/examples/hello_world_with_response/src/hello_world.e +++ b/library/server/ewsgi/examples/hello_world_with_response/src/hello_world.e @@ -8,18 +8,30 @@ class HELLO_WORLD inherit - EWSGI_RESPONSE_APPLICATION + WGI_RESPONSE_APPLICATION - DEFAULT_EWSGI_APPLICATION + DEFAULT_WGI_APPLICATION create make_and_launch feature -- Response - response (request: EWSGI_REQUEST): EWSGI_RESPONSE + response (request: WGI_REQUEST): WGI_RESPONSE do - create {HELLO_WORLD_RESPONSE} Result.make + if request.path_info.starts_with ("/streaming/") then + Result := streaming_response (request) + else + create Result.make + Result.set_status (200) + Result.set_header ("Content-Type", "text/html; charset=utf-8") + Result.set_message_body ("Hello World") + end + end + + streaming_response (request: WGI_REQUEST): WGI_RESPONSE + do + create {HELLO_WORLD_RESPONSE} Result.make Result.set_status (200) Result.set_header ("Content-Type", "text/html; charset=utf-8") end diff --git a/library/server/ewsgi/examples/hello_world_with_response/src/hello_world_response.e b/library/server/ewsgi/examples/hello_world_with_response/src/hello_world_response.e index 56d64da8..09fde7f2 100644 --- a/library/server/ewsgi/examples/hello_world_with_response/src/hello_world_response.e +++ b/library/server/ewsgi/examples/hello_world_with_response/src/hello_world_response.e @@ -6,7 +6,7 @@ note class HELLO_WORLD_RESPONSE inherit - EWSGI_RESPONSE + WGI_RESPONSE redefine make, read_block @@ -31,23 +31,26 @@ feature {NONE} -- Entity body local i: INTEGER do - if current_hello >= 100000 then + if current_hello >= 10000 then end_of_blocks := True else if current_hello = 0 then - current_block := "%N" + current_block := "%N" + current_block.append ("Welcome
    In progress
    ") end from i := 0 until - i = 10000 + i = 1000 loop current_block.append ("Hello World ("+ current_hello.out +","+ i.out +")
    %N") i := i + 1 end current_hello := current_hello + i - if current_hello = 100000 then - current_block.append ("Bye bye..
    ") + current_block.append ("
    In progress - "+ (100 * current_hello // 10000).out +"%%
    ") + if current_hello = 10000 then + current_block.append ("Bye bye..
    Completed - GO TO BOTTOM
    ") + end_of_blocks := True end end end diff --git a/library/server/ewsgi/specification/connector/ewsgi_connector.e b/library/server/ewsgi/specification/connector/wgi_connector.e similarity index 86% rename from library/server/ewsgi/specification/connector/ewsgi_connector.e rename to library/server/ewsgi/specification/connector/wgi_connector.e index ef2a666c..cfd400d3 100644 --- a/library/server/ewsgi/specification/connector/ewsgi_connector.e +++ b/library/server/ewsgi/specification/connector/wgi_connector.e @@ -1,11 +1,11 @@ note - description: "Summary description for {EWSGI_CONNECTOR}." + description: "Summary description for {WGI_CONNECTOR}." author: "" date: "$Date$" revision: "$Revision$" deferred class - EWSGI_CONNECTOR + WGI_CONNECTOR feature {NONE} -- Initialization @@ -22,7 +22,7 @@ feature {NONE} -- Initialization feature {NONE} -- Access - application: EWSGI_APPLICATION + application: WGI_APPLICATION -- Gateway Application feature -- Server diff --git a/library/server/ewsgi/specification/request/ewsgi_request.e b/library/server/ewsgi/specification/request/ewsgi_request.e deleted file mode 100644 index d2190078..00000000 --- a/library/server/ewsgi/specification/request/ewsgi_request.e +++ /dev/null @@ -1,165 +0,0 @@ -note - description: "[ - Server request context of the httpd request - - You can create your own descendant of this class to - add/remove specific value or processing - ]" - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -deferred class - EWSGI_REQUEST - -feature -- Access: Input - - input: EWSGI_INPUT_STREAM - -- Server input channel - deferred - end - -feature -- Access: extra values - - request_time: detachable DATE_TIME - -- Request time (UTC) - deferred - end - -feature -- Access: environment variables - - environment: EWSGI_ENVIRONMENT - -- Environment variables - deferred - end - - environment_variable (a_name: STRING): detachable STRING - -- Environment variable related to `a_name' - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - -feature -- Access: execution variables - - execution_variables: EWSGI_VARIABLES [STRING_32] - -- Execution variables set by the application - deferred - end - - execution_variable (a_name: STRING): detachable STRING_32 - -- Execution variable related to `a_name' - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - -feature -- URL Parameters - - parameters: EWSGI_VARIABLES [STRING_32] - -- Variables extracted from QUERY_STRING - deferred - end - - parameter (a_name: STRING): detachable STRING_32 - -- Parameter for name `n'. - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - -feature -- Form fields and related - - form_fields: EWSGI_VARIABLES [STRING_32] - -- Variables sent by POST request - deferred - end - - form_field (a_name: STRING): detachable STRING_32 - -- Field for name `a_name'. - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - - uploaded_files: HASH_TABLE [EWSGI_UPLOADED_FILE_DATA, STRING] - -- Table of uploaded files information - --| name: original path from the user - --| type: content type - --| tmp_name: path to temp file that resides on server - --| tmp_base_name: basename of `tmp_name' - --| error: if /= 0 , there was an error : TODO ... - --| size: size of the file given by the http request - deferred - end - -feature -- Cookies - - cookies_variables: HASH_TABLE [STRING, STRING] - -- Expanded cookies variable - deferred - end - - cookies_variable (a_name: STRING): detachable STRING - -- Field for name `a_name'. - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - - cookies: HASH_TABLE [EWSGI_COOKIE, STRING] - -- Cookies Information - deferred - end - -feature -- Access: global variable - - variables: HASH_TABLE [STRING_32, STRING_32] - -- Table containing all the various variables - -- Warning: this is computed each time, if you change the content of other containers - -- this won't update this Result's content, unless you query it again - deferred - end - - variable (a_name: STRING_8): detachable STRING_32 - -- Variable named `a_name' from any of the variables container - -- and following a specific order - -- execution, environment, get, post, cookies - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - -feature -- Uploaded File Handling - - is_uploaded_file (a_filename: STRING): BOOLEAN - -- Is `a_filename' a file uploaded via HTTP POST - deferred - end - -feature -- URL Utility - - absolute_script_url (a_path: STRING): STRING - -- Absolute Url for the script if any, extended by `a_path' - deferred - end - - script_url (a_path: STRING): STRING - -- Url relative to script name if any, extended by `a_path' - require - a_path_attached: a_path /= Void - deferred - 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/specification/request/ewsgi_variables.e b/library/server/ewsgi/specification/request/ewsgi_variables.e deleted file mode 100644 index 048270e7..00000000 --- a/library/server/ewsgi/specification/request/ewsgi_variables.e +++ /dev/null @@ -1,80 +0,0 @@ -note - description : "[ - Interface to access the variable stored in a container - ]" - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -deferred class - EWSGI_VARIABLES [G -> STRING_GENERAL] - -inherit - ITERABLE [G] - -feature -- Status report - - has_variable (a_name: STRING): BOOLEAN - -- Has variable associated with `a_name' - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - deferred - end - -feature -- Access - - variable (a_name: STRING): detachable G - -- Value for variable associated with `a_name' - -- If not found, return Void - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - deferred - end - - variable_or_default (a_name: STRING; a_default: G; use_default_when_empty: BOOLEAN): G - -- Value for variable `a_name' - -- If not found, return `a_default' - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - do - if attached variable (a_name) as s then - if use_default_when_empty and then s.is_empty then - Result := a_default - else - Result := s - end - else - Result := a_default - end - end - -feature {EWSGI_REQUEST, EWSGI_APPLICATION, EWSGI_CONNECTOR} -- Element change - - set_variable (a_name: STRING; a_value: G) - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - deferred - ensure - variable_set: has_variable (a_name) and then variable (a_name) ~ a_value - end - - unset_variable (a_name: STRING) - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - deferred - ensure - variable_unset: not has_variable (a_name) - 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/specification/request/ewsgi_cookie.e b/library/server/ewsgi/specification/request/obsolete/wgi_cookie.e similarity index 99% rename from library/server/ewsgi/specification/request/ewsgi_cookie.e rename to library/server/ewsgi/specification/request/obsolete/wgi_cookie.e index 262ef4b6..d76edbbc 100644 --- a/library/server/ewsgi/specification/request/ewsgi_cookie.e +++ b/library/server/ewsgi/specification/request/obsolete/wgi_cookie.e @@ -8,7 +8,7 @@ note revision: "$Revision$" class - EWSGI_COOKIE + WGI_COOKIE create make diff --git a/library/server/ewsgi/src/request/ewsgi_variables.e b/library/server/ewsgi/specification/request/obsolete/wgi_variables.e similarity index 94% rename from library/server/ewsgi/src/request/ewsgi_variables.e rename to library/server/ewsgi/specification/request/obsolete/wgi_variables.e index 048270e7..f3da8079 100644 --- a/library/server/ewsgi/src/request/ewsgi_variables.e +++ b/library/server/ewsgi/specification/request/obsolete/wgi_variables.e @@ -8,7 +8,7 @@ note revision: "$Revision$" deferred class - EWSGI_VARIABLES [G -> STRING_GENERAL] + WGI_VARIABLES [G -> STRING_GENERAL] inherit ITERABLE [G] @@ -49,7 +49,7 @@ feature -- Access end end -feature {EWSGI_REQUEST, EWSGI_APPLICATION, EWSGI_CONNECTOR} -- Element change +feature {WGI_REQUEST, WGI_APPLICATION, WGI_CONNECTOR} -- Element change set_variable (a_name: STRING; a_value: G) require diff --git a/library/server/ewsgi/specification/request/ewsgi_environment_names.e b/library/server/ewsgi/specification/request/wgi_meta_names.e similarity index 95% rename from library/server/ewsgi/specification/request/ewsgi_environment_names.e rename to library/server/ewsgi/specification/request/wgi_meta_names.e index 46860b5d..8b10840e 100644 --- a/library/server/ewsgi/specification/request/ewsgi_environment_names.e +++ b/library/server/ewsgi/specification/request/wgi_meta_names.e @@ -1,12 +1,12 @@ note - description: "Summary description for {EWSGI_ENVIRONMENT_NAMES}." + description: "Summary description for {WGI_META_NAMES}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - EWSGI_ENVIRONMENT_NAMES + WGI_META_NAMES feature -- Access diff --git a/library/server/ewsgi/specification/request/ewsgi_environment.e b/library/server/ewsgi/specification/request/wgi_request.e similarity index 80% rename from library/server/ewsgi/specification/request/ewsgi_environment.e rename to library/server/ewsgi/specification/request/wgi_request.e index 07f6d11a..da041511 100644 --- a/library/server/ewsgi/specification/request/ewsgi_environment.e +++ b/library/server/ewsgi/specification/request/wgi_request.e @@ -1,7 +1,7 @@ note description: "[ - - Interface for a request environment + Server request context of the httpd request + It includes CGI interface and a few extra values that are usually valuable See http://www.ietf.org/rfc/rfc3875 @@ -70,18 +70,33 @@ note date: "$Date$" revision: "$Revision$" -deferred -class - EWSGI_ENVIRONMENT +deferred class + WGI_REQUEST -inherit - EWSGI_VARIABLES [STRING_8] +feature -- Access: Input - ITERABLE [STRING_8] + input: WGI_INPUT_STREAM + -- Server input channel + deferred + end -feature -- Access +feature -- Access: extra values - table: HASH_TABLE [STRING, STRING] + request_time: detachable DATE_TIME + -- Request time (UTC) + deferred + end + +feature -- Access: CGI meta variables + + meta_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + -- Environment variable related to `a_name' + require + a_name_valid: a_name /= Void and then not a_name.is_empty + deferred + end + + meta_variables: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] -- These variables are specific to requests made with HTTP. -- Interpretation of these variables may depend on the value of -- SERVER_PROTOCOL. @@ -111,17 +126,9 @@ feature -- Access deferred end -feature -- Access: table - - new_cursor: HASH_TABLE_ITERATION_CURSOR [STRING_8, STRING_8] - -- Fresh cursor associated with current structure - do - create Result.make (table) - end - feature -- Common Gateway Interface - 1.1 8 January 1996 - auth_type: detachable STRING + auth_type: detachable READABLE_STRING_32 -- This variable is specific to requests made via the "http" -- scheme. -- @@ -143,7 +150,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - content_length: detachable STRING + content_length: detachable READABLE_STRING_32 -- This metavariable is set to the size of the message-body -- entity attached to the request, if any, in decimal number of -- octets. If no data are attached, then this metavariable is @@ -158,12 +165,12 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - content_length_value: INTEGER + content_length_value: NATURAL_64 -- Integer value related to `content_length" deferred end - content_type: detachable STRING + content_type: detachable READABLE_STRING_32 -- If the request includes a message-body, CONTENT_TYPE is set to -- the Internet Media Type [9] of the attached entity if the type -- was provided via a "Content-type" field in the request header, @@ -206,7 +213,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - gateway_interface: STRING + gateway_interface: READABLE_STRING_32 -- This metavariable is set to the dialect of CGI being used by -- the server to communicate with the script. Syntax: -- @@ -239,7 +246,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - path_info: STRING assign update_path_info + path_info: READABLE_STRING_32 -- The PATH_INFO metavariable specifies a path to be interpreted -- by the CGI script. It identifies the resource or sub-resource -- to be returned by the CGI script, and it is derived from the @@ -270,7 +277,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - path_translated: detachable STRING + path_translated: detachable READABLE_STRING_32 -- PATH_TRANSLATED is derived by taking any path-info component -- of the request URI (see section 6.1.6), decoding it (see -- section 3.1), parsing it as a URI in its own right, and @@ -316,7 +323,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - query_string: STRING + query_string: READABLE_STRING_32 -- A URL-encoded string; the part of the Script-URI. (See -- section 3.2.) -- @@ -333,7 +340,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - remote_addr: STRING + remote_addr: READABLE_STRING_32 -- The IP address of the client sending the request to the -- server. This is not necessarily that of the user agent (such -- as if the request came through a proxy). @@ -348,7 +355,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - remote_host: detachable STRING + remote_host: detachable READABLE_STRING_32 -- The fully qualified domain name of the client sending the -- request to the server, if available, otherwise NULL. (See -- section 6.1.9.) Fully qualified domain names take the form as @@ -359,7 +366,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - remote_ident: detachable STRING + remote_ident: detachable READABLE_STRING_32 -- The identity information reported about the connection by a -- RFC 1413 [11] request to the remote agent, if available. -- Servers MAY choose not to support this feature, or not to @@ -375,7 +382,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - remote_user: detachable STRING + remote_user: detachable READABLE_STRING_32 -- If the request required authentication using the "Basic" -- mechanism (i.e., the AUTH_TYPE metavariable is set to -- "Basic"), then the value of the REMOTE_USER metavariable is @@ -391,7 +398,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - request_method: STRING + request_method: READABLE_STRING_32 -- The REQUEST_METHOD metavariable is set to the method with -- which the request was made, as described in section 5.1.1 of -- the HTTP/1.0 specification [3] and section 5.1.1 of the @@ -412,7 +419,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - script_name: STRING + script_name: READABLE_STRING_32 -- The SCRIPT_NAME metavariable is set to a URL path that could -- identify the CGI script (rather than the script's output). The -- syntax and semantics are identical to a decoded HTTP URL @@ -430,7 +437,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - server_name: STRING + server_name: READABLE_STRING_32 -- The SERVER_NAME metavariable is set to the name of the server, -- as derived from the part of the Script-URI (see section -- 3.2). @@ -456,7 +463,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - server_protocol: STRING + server_protocol: READABLE_STRING_32 -- The SERVER_PROTOCOL metavariable is set to the name and -- revision of the information protocol with which the request -- arrived. This is not necessarily the same as the protocol @@ -484,7 +491,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - server_software: STRING + server_software: READABLE_STRING_32 -- The SERVER_SOFTWARE metavariable is set to the name and -- version of the information server software answering the -- request (and running the gateway). @@ -499,42 +506,42 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 feature -- HTTP_* - http_accept: detachable STRING + http_accept: detachable READABLE_STRING_32 -- Contents of the Accept: header from the current request, if there is one. -- Example: 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' deferred end - http_accept_charset: detachable STRING + http_accept_charset: detachable READABLE_STRING_32 -- Contents of the Accept-Charset: header from the current request, if there is one. -- Example: 'iso-8859-1,*,utf-8'. deferred end - http_accept_encoding: detachable STRING + http_accept_encoding: detachable READABLE_STRING_32 -- Contents of the Accept-Encoding: header from the current request, if there is one. -- Example: 'gzip'. deferred end - http_accept_language: detachable STRING + http_accept_language: detachable READABLE_STRING_32 -- Contents of the Accept-Language: header from the current request, if there is one. -- Example: 'en'. deferred end - http_connection: detachable STRING + http_connection: detachable READABLE_STRING_32 -- Contents of the Connection: header from the current request, if there is one. -- Example: 'Keep-Alive'. deferred end - http_host: detachable STRING + http_host: detachable READABLE_STRING_32 -- Contents of the Host: header from the current request, if there is one. deferred end - http_referer: detachable STRING + http_referer: detachable READABLE_STRING_32 -- The address of the page (if any) which referred the user agent to the current page. -- This is set by the user agent. -- Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. @@ -542,7 +549,7 @@ feature -- HTTP_* deferred end - http_user_agent: detachable STRING + http_user_agent: detachable READABLE_STRING_32 -- Contents of the User-Agent: header from the current request, if there is one. -- This is a string denoting the user agent being which is accessing the page. -- A typical example is: Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586). @@ -551,46 +558,127 @@ feature -- HTTP_* deferred end - http_authorization: detachable STRING + http_authorization: detachable READABLE_STRING_32 -- Contents of the Authorization: header from the current request, if there is one. deferred end -feature -- Extra +feature -- Extra CGI environment variables - request_uri: STRING + request_uri: READABLE_STRING_32 -- The URI which was given in order to access this page; for instance, '/index.html'. deferred end - orig_path_info: detachable STRING + orig_path_info: detachable READABLE_STRING_32 -- Original version of `path_info' before processed by Current environment deferred end -feature {EWSGI_REQUEST} -- Element change +--feature -- Access: execution variables - set_orig_path_info (s: STRING) - -- Set ORIG_PATH_INFO to `s' +-- execution_variables: WGI_VARIABLES [STRING_32] +-- -- Execution variables set by the application +-- deferred +-- end + +-- execution_variable (a_name: STRING): detachable STRING_32 +-- -- Execution variable related to `a_name' +-- require +-- a_name_valid: a_name /= Void and then not a_name.is_empty +-- deferred +-- end + +feature -- Query string Parameters + + query_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] + -- Variables extracted from QUERY_STRING + deferred + end + + query_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + -- Parameter for name `n'. require - s_attached: s /= Void + a_name_valid: a_name /= Void and then not a_name.is_empty deferred - ensure - same_orig_path_info: orig_path_info ~ variable ({EWSGI_ENVIRONMENT_NAMES}.orig_path_info) end - unset_orig_path_info - -- Unset ORIG_PATH_INFO +feature -- Form fields and related + + form_data_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] + -- Variables sent by POST request deferred - ensure - unset: not has_variable ({EWSGI_ENVIRONMENT_NAMES}.orig_path_info) end - update_path_info (a_path_info: like path_info) - -- Updated PATH_INFO + form_data_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + -- Field for name `a_name'. + require + a_name_valid: a_name /= Void and then not a_name.is_empty + deferred + end + + uploaded_files: HASH_TABLE [WGI_UPLOADED_FILE_DATA, READABLE_STRING_GENERAL] + -- Table of uploaded files information + --| name: original path from the user + --| type: content type + --| tmp_name: path to temp file that resides on server + --| tmp_base_name: basename of `tmp_name' + --| error: if /= 0 , there was an error : TODO ... + --| size: size of the file given by the http request + deferred + end + +feature -- Cookies + + cookies: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] + -- Expanded cookies variable + deferred + end + + cookie (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + -- Field for name `a_name'. + require + a_name_valid: a_name /= Void and then not a_name.is_empty + deferred + end + +feature -- Access: global variable + + parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] + -- Table containing all the various variables + -- Warning: this is computed each time, if you change the content of other containers + -- this won't update this Result's content, unless you query it again + deferred + end + + parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + -- Variable named `a_name' from any of the variables container + -- and following a specific order + -- execution, environment, get, post, cookies + require + a_name_valid: a_name /= Void and then not a_name.is_empty + deferred + end + +feature -- Uploaded File Handling + + is_uploaded_file (a_filename: READABLE_STRING_GENERAL): BOOLEAN + -- Is `a_filename' a file uploaded via HTTP POST + deferred + end + +feature -- URL Utility + + absolute_script_url (a_path: STRING): STRING + -- Absolute Url for the script if any, extended by `a_path' + deferred + end + + script_url (a_path: STRING): STRING + -- Url relative to script name if any, extended by `a_path' + require + a_path_attached: a_path /= Void deferred - ensure - same_path_info: path_info ~ variable ({EWSGI_ENVIRONMENT_NAMES}.path_info) end invariant @@ -601,9 +689,12 @@ invariant query_string_attached: query_string /= Void remote_addr_attached: remote_addr /= Void - path_info_identical: path_info ~ variable ({EWSGI_ENVIRONMENT_NAMES}.path_info) + same_orig_path_info: orig_path_info ~ meta_variable ({WGI_META_NAMES}.orig_path_info) + same_path_info: path_info ~ meta_variable ({WGI_META_NAMES}.path_info) -;note + path_info_identical: path_info ~ meta_variable ({WGI_META_NAMES}.path_info) + +note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ diff --git a/library/server/ewsgi/specification/request/ewsgi_uploaded_file_data.e b/library/server/ewsgi/specification/request/wgi_uploaded_file_data.e similarity index 95% rename from library/server/ewsgi/specification/request/ewsgi_uploaded_file_data.e rename to library/server/ewsgi/specification/request/wgi_uploaded_file_data.e index a8f2ea36..339febae 100644 --- a/library/server/ewsgi/specification/request/ewsgi_uploaded_file_data.e +++ b/library/server/ewsgi/specification/request/wgi_uploaded_file_data.e @@ -1,11 +1,11 @@ note - description: "Summary description for {GW_UPLOADED_FILE}." + description: "Summary description for {WGI_UPLOADED_FILE_DATA}." author: "" date: "$Date$" revision: "$Revision$" class - EWSGI_UPLOADED_FILE_DATA + WGI_UPLOADED_FILE_DATA create make diff --git a/library/server/ewsgi/specification/response/ewsgi_response_buffer.e b/library/server/ewsgi/specification/response/wgi_response_buffer.e similarity index 83% rename from library/server/ewsgi/specification/response/ewsgi_response_buffer.e rename to library/server/ewsgi/specification/response/wgi_response_buffer.e index 3ce7a4b2..7cf4e9fa 100644 --- a/library/server/ewsgi/specification/response/ewsgi_response_buffer.e +++ b/library/server/ewsgi/specification/response/wgi_response_buffer.e @@ -1,13 +1,13 @@ note - description: "Summary description for {EWSGI_RESPONSE_BUFFER}." + description: "Summary description for {WGI_RESPONSE_BUFFER}." author: "" date: "$Date$" revision: "$Revision$" deferred class - EWSGI_RESPONSE_BUFFER + WGI_RESPONSE_BUFFER -feature {EWSGI_APPLICATION} -- Commit +feature {WGI_APPLICATION} -- Commit commit -- Commit the current response @@ -35,7 +35,7 @@ feature -- Status report deferred end -feature {NONE} -- Core output operation +feature {WGI_RESPONSE_BUFFER} -- Core output operation write (s: STRING) -- Send the string `s' @@ -67,13 +67,33 @@ feature -- Status setting deferred end -feature -- Output operation +feature -- Header output operation - flush - -- Flush if it makes sense + write_headers_string (a_headers: STRING) + require + status_set: status_is_set + header_not_committed: not header_committed deferred + ensure + status_set: status_is_set + header_committed: header_committed + message_writable: message_writable end + write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: STRING; value: STRING]]) + -- Send headers with status `a_status', and headers from `a_headers' + require + status_not_set: not status_is_set + header_not_committed: not header_committed + deferred + ensure + header_committed: header_committed + status_set: status_is_set + message_writable: message_writable + end + +feature -- Output operation + write_string (s: STRING) -- Send the string `s' require @@ -95,17 +115,9 @@ feature -- Output operation deferred end -feature -- Header output operation - - write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: STRING; value: STRING]]) - -- Send headers with status `a_status', and headers from `a_headers' - require - status_not_set: not status_is_set - header_not_committed: not header_committed + flush + -- Flush if it makes sense deferred - ensure - header_committed: header_committed - status_set: status_is_set end note diff --git a/library/server/ewsgi/specification/stream/ewsgi_input_stream.e b/library/server/ewsgi/specification/stream/wgi_input_stream.e similarity index 97% rename from library/server/ewsgi/specification/stream/ewsgi_input_stream.e rename to library/server/ewsgi/specification/stream/wgi_input_stream.e index 60b49623..940c2367 100644 --- a/library/server/ewsgi/specification/stream/ewsgi_input_stream.e +++ b/library/server/ewsgi/specification/stream/wgi_input_stream.e @@ -8,7 +8,7 @@ note revision: "$Revision$" deferred class - EWSGI_INPUT_STREAM + WGI_INPUT_STREAM feature -- Access diff --git a/library/server/ewsgi/specification/stream/ewsgi_output_stream.e b/library/server/ewsgi/specification/stream/wgi_output_stream.e similarity index 98% rename from library/server/ewsgi/specification/stream/ewsgi_output_stream.e rename to library/server/ewsgi/specification/stream/wgi_output_stream.e index 1f7c6fce..de11fcb1 100644 --- a/library/server/ewsgi/specification/stream/ewsgi_output_stream.e +++ b/library/server/ewsgi/specification/stream/wgi_output_stream.e @@ -8,7 +8,7 @@ note revision: "$Revision$" deferred class - EWSGI_OUTPUT_STREAM + WGI_OUTPUT_STREAM feature -- Core operation diff --git a/library/server/ewsgi/specification/ewsgi_application.e b/library/server/ewsgi/specification/wgi_application.e similarity index 85% rename from library/server/ewsgi/specification/ewsgi_application.e rename to library/server/ewsgi/specification/wgi_application.e index 244a832c..121dd7e5 100644 --- a/library/server/ewsgi/specification/ewsgi_application.e +++ b/library/server/ewsgi/specification/wgi_application.e @@ -1,16 +1,16 @@ note - description: "Summary description for {EWSGI_APPLICATION}." + description: "Summary description for {WGI_APPLICATION}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" deferred class - EWSGI_APPLICATION + WGI_APPLICATION feature {NONE} -- Execution - execute (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Execute the request -- See `req.input' for input stream -- `req.environment' for the Gateway environment diff --git a/library/server/ewsgi/src/application/ewsgi_agent_application.e b/library/server/ewsgi/src/application/wgi_agent_application.e similarity index 75% rename from library/server/ewsgi/src/application/ewsgi_agent_application.e rename to library/server/ewsgi/src/application/wgi_agent_application.e index 5b1a1deb..6a5785a8 100644 --- a/library/server/ewsgi/src/application/ewsgi_agent_application.e +++ b/library/server/ewsgi/src/application/wgi_agent_application.e @@ -1,14 +1,14 @@ note - description: "Summary description for {EWSGI_AGENT_APPLICATION}." + description: "Summary description for {WGI_AGENT_APPLICATION}." author: "" date: "$Date$" revision: "$Revision$" class - EWSGI_AGENT_APPLICATION + WGI_AGENT_APPLICATION inherit - EWSGI_APPLICATION + WGI_APPLICATION create make @@ -23,10 +23,10 @@ feature {NONE} -- Implementation feature {NONE} -- Implementation - callback: PROCEDURE [ANY, TUPLE [req: like new_request; res: like new_response]] + callback: PROCEDURE [ANY, TUPLE [req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]] -- Procedure called on `execute' - execute (req: like new_request; res: like new_response) + execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Execute the request do callback.call ([req, res]) diff --git a/library/server/ewsgi/src/application/ewsgi_application.e b/library/server/ewsgi/src/application/wgi_application.e similarity index 58% rename from library/server/ewsgi/src/application/ewsgi_application.e rename to library/server/ewsgi/src/application/wgi_application.e index 17044646..4c5a8d22 100644 --- a/library/server/ewsgi/src/application/ewsgi_application.e +++ b/library/server/ewsgi/src/application/wgi_application.e @@ -1,6 +1,6 @@ note description: "[ - EWSGI_APPLICATION + WGI_APPLICATION ]" specification: "EWSGI specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification" legal: "See notice at end of class." @@ -9,11 +9,11 @@ note revision: "$Revision$" deferred class - EWSGI_APPLICATION + WGI_APPLICATION -feature {NONE} -- Execution +feature -- Execution - execute (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Execute the request -- See `req.input' for input stream -- `req.environment' for the Gateway environment @@ -23,23 +23,19 @@ feature {NONE} -- Execution deferred ensure res_status_set: res.status_is_set - res_committed: res.message_committed +-- res_committed: res.message_committed end feature -- Process request - process (env: EWSGI_ENVIRONMENT; a_input: EWSGI_INPUT_STREAM; a_output: EWSGI_OUTPUT_STREAM) + process (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Process request with environment `env', and i/o streams `a_input' and `a_output' local rescued: BOOLEAN - req: detachable like new_request - res: detachable like new_response do if not rescued then request_count := request_count + 1 - pre_execute (env) - req := new_request (env, a_input) - res := new_response (req, a_output) + pre_execute (req) execute (req, res) post_execute (req, res) else @@ -57,24 +53,21 @@ feature -- Access feature {NONE} -- Execution - pre_execute (env: EWSGI_ENVIRONMENT) + pre_execute (req: WGI_REQUEST) -- Operation processed before `execute' - require - env_attached: env /= Void do end - post_execute (req: detachable EWSGI_REQUEST; res: detachable EWSGI_RESPONSE_BUFFER) + post_execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Operation processed after `execute', or after `rescue_execute' do end - rescue_execute (req: detachable EWSGI_REQUEST; res: detachable EWSGI_RESPONSE_BUFFER; a_exception: detachable EXCEPTION) + rescue_execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_exception: detachable EXCEPTION) -- Operation processed on rescue of `execute' do if - req /= Void and res /= Void - and a_exception /= Void and then attached a_exception.exception_trace as l_trace + a_exception /= Void and then attached a_exception.exception_trace as l_trace then res.write_header ({HTTP_STATUS_CODE}.internal_server_error, Void) res.write_string ("
    " + l_trace + "
    ") @@ -82,19 +75,6 @@ feature {NONE} -- Execution post_execute (req, res) end -feature {NONE} -- Factory - - new_request (env: EWSGI_ENVIRONMENT; a_input: EWSGI_INPUT_STREAM): EWSGI_REQUEST - do - create {EWSGI_REQUEST} Result.make (env, a_input) - Result.environment.set_variable (request_count.out, "REQUEST_COUNT") - end - - new_response (req: EWSGI_REQUEST; a_output: EWSGI_OUTPUT_STREAM): EWSGI_RESPONSE_BUFFER - do - create {EWSGI_RESPONSE_BUFFER} Result.make (a_output) - end - ;note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/src/connector/ewsgi_connector.e b/library/server/ewsgi/src/connector/wgi_connector.e similarity index 88% rename from library/server/ewsgi/src/connector/ewsgi_connector.e rename to library/server/ewsgi/src/connector/wgi_connector.e index 1207ee9d..eac74fbe 100644 --- a/library/server/ewsgi/src/connector/ewsgi_connector.e +++ b/library/server/ewsgi/src/connector/wgi_connector.e @@ -1,11 +1,11 @@ note - description: "Summary description for {EWSGI_CONNECTOR}." + description: "Summary description for {WGI_CONNECTOR}." specification: "EWSGI/connector specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification" date: "$Date$" revision: "$Revision$" deferred class - EWSGI_CONNECTOR + WGI_CONNECTOR feature {NONE} -- Initialization @@ -22,7 +22,7 @@ feature {NONE} -- Initialization feature {NONE} -- Access - application: EWSGI_APPLICATION + application: WGI_APPLICATION -- Gateway Application feature -- Server diff --git a/library/server/ewsgi/src/extra/ewf_buffered_response.e b/library/server/ewsgi/src/extra/ewf_buffered_response.e new file mode 100644 index 00000000..123dd75a --- /dev/null +++ b/library/server/ewsgi/src/extra/ewf_buffered_response.e @@ -0,0 +1,186 @@ +note + description: "Summary description for {EWF_BUFFERED_RESPONSE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + EWF_BUFFERED_RESPONSE + +inherit + WGI_RESPONSE_BUFFER + +create {WGI_APPLICATION} + make + +feature {NONE} -- Initialization + + make (a_res: like response_buffer; a_buffer_size: INTEGER) + do + response_buffer := a_res + buffer_capacity := a_buffer_size + create buffer.make (a_buffer_size) + end + + response_buffer: WGI_RESPONSE_BUFFER + + buffer: STRING_8 + + buffer_capacity: INTEGER + + buffer_count: INTEGER + +feature {NONE} -- Core output operation + + write (s: STRING) + -- Send the content of `s' + local + buf: like buffer + len_b, len_s: INTEGER + do + buf := buffer + len_s := s.count + len_b := buffer_count + if len_b + len_s >= buffer_capacity then + flush_buffer + if len_s >= buffer_capacity then + -- replace buffer by `s' + buffer := s + buffer_count := len_s + flush_buffer + -- restore buffer with `buf' + buffer := buf + else + buf.append (s) + buffer_count := len_s + end + else + buf.append (s) + buffer_count := len_b + len_s + end + end + +feature -- Output operation + + flush + do + flush_buffer + end + +feature {NONE} -- Implementation + + flush_buffer + require + buffer_count_match_buffer: buffer_count = buffer.count + do + response_buffer.write (buffer) + buffer_count := 0 + ensure + buffer_flushed: buffer_count = 0 and buffer.count = 0 + end + +feature {WGI_APPLICATION} -- Commit + + commit + do + flush_buffer + end + +feature -- Status report + + header_committed: BOOLEAN + -- Header committed? + + message_committed: BOOLEAN + -- Message committed? + + message_writable: BOOLEAN + -- Can message be written? + do + Result := status_is_set and header_committed + end + +feature -- Status setting + + status_is_set: BOOLEAN + -- Is status set? + do + Result := status_code /= 0 + end + + set_status_code (a_code: INTEGER) + -- Set response status code + -- Should be done before sending any data back to the client + do + status_code := a_code + response_buffer.set_status_code (a_code) + end + + status_code: INTEGER + -- Response status + +feature -- Header output operation + + write_headers_string (a_headers: STRING) + do + write (a_headers) + header_committed := True + end + + write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: STRING; value: STRING]]) + -- Send headers with status `a_status', and headers from `a_headers' + local + h: EWF_HEADER + i,n: INTEGER + do + set_status_code (a_status_code) + create h.make + h.put_status (a_status_code) + if a_headers /= Void then + 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 + end + write_headers_string (h.string) + end + +feature -- Output operation + + write_string (s: STRING) + -- Send the string `s' + do + write (s) + end + + write_substring (s: STRING; start_index, end_index: INTEGER) + -- Send the substring `start_index:end_index]' + --| Could be optimized according to the target output + do + flush_buffer + response_buffer.write_substring (s, start_index, end_index) + end + + write_file_content (fn: STRING) + -- Send the content of file `fn' + do + flush_buffer + response_buffer.write_file_content (fn) + 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/extra/gw_buffered_response.e b/library/server/ewsgi/src/extra/gw_buffered_response.e deleted file mode 100644 index 241d33cf..00000000 --- a/library/server/ewsgi/src/extra/gw_buffered_response.e +++ /dev/null @@ -1,105 +0,0 @@ -note - description: "Summary description for {GW_BUFFERED_RESPONSE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - GW_BUFFERED_RESPONSE - -inherit - EWSGI_RESPONSE_BUFFER - rename - make as buffer_make - redefine - write, - flush, - commit - end - -create {EWSGI_APPLICATION} - make - -feature {NONE} -- Initialization - - make (a_output: like output; a_buffer_size: INTEGER) - do - buffer_make (a_output) - buffer_capacity := a_buffer_size - create buffer.make (a_buffer_size) - end - - buffer: STRING_8 - - buffer_capacity: INTEGER - - buffer_count: INTEGER - -feature {NONE} -- Core output operation - - write (s: STRING) - -- Send the content of `s' - local - buf: like buffer - len_b, len_s: INTEGER - do - buf := buffer - len_s := s.count - len_b := buffer_count - if len_b + len_s >= buffer_capacity then - flush_buffer - if len_s >= buffer_capacity then - -- replace buffer by `s' - buffer := s - buffer_count := len_s - flush_buffer - -- restore buffer with `buf' - buffer := buf - else - buf.append (s) - buffer_count := len_s - end - else - buf.append (s) - buffer_count := len_b + len_s - end - end - -feature -- Output operation - - flush - do - flush_buffer - end - -feature {NONE} -- Implementation - - flush_buffer - require - buffer_count_match_buffer: buffer_count = buffer.count - do - output.put_string (buffer) - buffer_count := 0 - ensure - buffer_flushed: buffer_count = 0 and buffer.count = 0 - end - -feature {EWSGI_APPLICATION} -- Commit - - commit - do - flush_buffer - Precursor - 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/extra/in_memory/gw_in_memory_response.e b/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response.e similarity index 51% rename from library/server/ewsgi/src/extra/in_memory/gw_in_memory_response.e rename to library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response.e index c8a68231..d6688b0b 100644 --- a/library/server/ewsgi/src/extra/in_memory/gw_in_memory_response.e +++ b/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response.e @@ -1,38 +1,79 @@ note - description: "Summary description for {GW_IN_MEMORY_RESPONSE}." + description: "Summary description for {EWF_IN_MEMORY_RESPONSE}." date: "$Date$" revision: "$Revision$" class - GW_IN_MEMORY_RESPONSE + EWF_IN_MEMORY_RESPONSE inherit - EWSGI_RESPONSE_BUFFER - redefine - make, - commit, - write, - set_status_code, - write_header, - flush - end + WGI_RESPONSE_BUFFER -create {EWSGI_APPLICATION} +create {WGI_APPLICATION} make feature {NONE} -- Initialization - make (a_output: EWSGI_OUTPUT_STREAM) + make (res: WGI_RESPONSE_BUFFER) do - Precursor (a_output) + response_buffer := res create header.make create body.make (100) end - header: GW_HEADER + response_buffer: WGI_RESPONSE_BUFFER + + header: EWF_HEADER body: STRING_8 +feature {WGI_APPLICATION} -- Commit + + commit + local + r: like response_buffer + do + r := response_buffer + r.set_status_code (status_code) + r.write_headers_string (header.string) + header_committed := True + r.write_string (body) + r.flush + end + +feature -- Status report + + header_committed: BOOLEAN + -- Header committed? + + message_committed: BOOLEAN + -- Message committed? + + message_writable: BOOLEAN + -- Can message be written? + do + Result := status_is_set and header_committed + end + + +feature -- Status setting + + status_is_set: BOOLEAN + -- Is status set? + do + Result := status_code /= 0 + end + + set_status_code (a_code: INTEGER) + -- Set response status code + -- Should be done before sending any data back to the client + do + status_code := a_code + end + + status_code: INTEGER + -- Response status + feature {NONE} -- Status output write (s: STRING) @@ -41,28 +82,18 @@ feature {NONE} -- Status output body.append (s) end -feature -- Status setting +feature -- Header output operation - set_status_code (a_code: INTEGER) - -- Set response status code - -- Should be done before sending any data back to the client + write_headers_string (a_headers: STRING) do - status_code := a_code + write (a_headers) + header_committed := True end -feature -- Output operation - - flush - do - --| Do nothing ... this is in_memory response - end - -feature -- Header output operation - write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: STRING; value: STRING]]) -- Send headers with status `a_status', and headers from `a_headers' local - h: GW_HEADER + h: EWF_HEADER i,n: INTEGER do set_status_code (a_status_code) @@ -81,19 +112,30 @@ feature -- Header output operation header := h end -feature {EWSGI_APPLICATION} -- Commit +feature -- Output operation - commit - local - o: like output + write_string (s: STRING) + -- Send the string `s' do - o := output - o.put_status_line (status_code) - o.put_string (header.string) - header_committed := True - o.put_string (body) - o.flush - Precursor + write (s) + end + + write_substring (s: STRING; start_index, end_index: INTEGER) + -- Send the substring `start_index:end_index]' + --| Could be optimized according to the target output + do + write_string (s.substring (start_index, end_index)) + end + + write_file_content (fn: STRING) + -- Send the content of file `fn' + do + response_buffer.write_file_content (fn) + end + + flush + do + --| Do nothing ... this is in_memory response end ;note diff --git a/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response_application.e b/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response_application.e new file mode 100644 index 00000000..c1528e0c --- /dev/null +++ b/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response_application.e @@ -0,0 +1,59 @@ +note + description: "Summary description for {EWF_IN_MEMORY_RESPONSE_APPLICATION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + EWF_IN_MEMORY_RESPONSE_APPLICATION + +inherit + WGI_APPLICATION + rename + execute as app_execute + end + + +feature -- Execution + + app_execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + -- Execute the request + -- See `req.input' for input stream + -- `req.environment' for the Gateway environment + -- and `res' for output buffer + do + execute (req, new_response (req, res)) + end + +feature -- Execute + + execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + -- Execute the request + -- See `req.input' for input stream + -- `req.environment' for the Gateway environment + -- and `res' for output buffer + require + res_status_unset: not res.status_is_set + deferred + ensure + res_status_set: res.status_is_set + end + +feature {NONE} -- Implementation + + new_response (req: WGI_REQUEST; a_res: WGI_RESPONSE_BUFFER): EWF_IN_MEMORY_RESPONSE + do + create {EWF_IN_MEMORY_RESPONSE} Result.make (a_res) + 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/extra/in_memory/gw_in_memory_response_application.e b/library/server/ewsgi/src/extra/in_memory/gw_in_memory_response_application.e deleted file mode 100644 index c1fcab1d..00000000 --- a/library/server/ewsgi/src/extra/in_memory/gw_in_memory_response_application.e +++ /dev/null @@ -1,33 +0,0 @@ -note - description: "Summary description for {GW_IN_MEMORY_RESPONSE_APPLICATION}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - GW_IN_MEMORY_RESPONSE_APPLICATION - -inherit - EWSGI_APPLICATION - redefine - new_response - end - -feature -- Factory - - new_response (req: EWSGI_REQUEST; a_output: EWSGI_OUTPUT_STREAM): GW_IN_MEMORY_RESPONSE - do - create {GW_IN_MEMORY_RESPONSE} Result.make (a_output) - 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/extra/response_as_result/ewsgi_response.e b/library/server/ewsgi/src/extra/response_as_result/wgi_response.e similarity index 92% rename from library/server/ewsgi/src/extra/response_as_result/ewsgi_response.e rename to library/server/ewsgi/src/extra/response_as_result/wgi_response.e index 35aac77e..62cce845 100644 --- a/library/server/ewsgi/src/extra/response_as_result/ewsgi_response.e +++ b/library/server/ewsgi/src/extra/response_as_result/wgi_response.e @@ -8,7 +8,7 @@ note author: "Paul Cohen " status: "Draft" -class EWSGI_RESPONSE +class WGI_RESPONSE create make @@ -26,12 +26,12 @@ feature {NONE} -- Initialization create headers_table.make (10) end -feature {EWSGI_RESPONSE_APPLICATION} -- Response status +feature {WGI_RESPONSE_APPLICATION} -- Response status - transmit_to (res: EWSGI_RESPONSE_BUFFER) + transmit_to (res: WGI_RESPONSE_BUFFER) do res.set_status_code (status) - res.write_string (headers) + res.write_headers_string (headers) from read_block res.write_string (last_block) @@ -64,7 +64,7 @@ feature {EWSGI_RESPONSE_APPLICATION} -- Response status ready_to_transmit end -feature {EWSGI_RESPONSE_APPLICATION} -- Message start line and status +feature {WGI_RESPONSE_APPLICATION} -- Message start line and status status: INTEGER -- HTTP status code @@ -88,7 +88,7 @@ feature {EWSGI_RESPONSE_APPLICATION} -- Message start line and status end end -feature {EWSGI_RESPONSE_APPLICATION} -- Message headers +feature {WGI_RESPONSE_APPLICATION} -- Message headers headers: STRING -- HTTP message headers including trailing empty line. @@ -119,7 +119,7 @@ feature {EWSGI_RESPONSE_APPLICATION} -- Message headers headers_table.has (key) and headers_table @ key = value end -feature {EWSGI_RESPONSE_APPLICATION} -- Message body +feature {WGI_RESPONSE_APPLICATION} -- Message body read_block -- Read a message body block. @@ -131,7 +131,8 @@ feature {EWSGI_RESPONSE_APPLICATION} -- Message body -- -- TBD! end ensure - not is_buffered implies last_block.count <= max_block_size +--Commented, since it is far from obvious to ensure that: +-- not is_buffered implies last_block.count <= max_block_size end last_block: STRING diff --git a/library/server/ewsgi/src/extra/response_as_result/ewsgi_response_application.e b/library/server/ewsgi/src/extra/response_as_result/wgi_response_application.e similarity index 81% rename from library/server/ewsgi/src/extra/response_as_result/ewsgi_response_application.e rename to library/server/ewsgi/src/extra/response_as_result/wgi_response_application.e index 5c717e37..aad8bf91 100644 --- a/library/server/ewsgi/src/extra/response_as_result/ewsgi_response_application.e +++ b/library/server/ewsgi/src/extra/response_as_result/wgi_response_application.e @@ -1,23 +1,22 @@ note - description: "Summary description for {EWSGI_RESPONSE_APPLICATION} " + description: "Summary description for {WGI_RESPONSE_APPLICATION} " legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" deferred class - EWSGI_RESPONSE_APPLICATION + WGI_RESPONSE_APPLICATION feature -- Execution - execute (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Execute the request -- See `req.input' for input stream -- `req.environment' for the Gateway environment -- and `res.output' for output stream local - rs: EWSGI_RESPONSE - s: STRING + rs: WGI_RESPONSE do rs := response (req) if rs.ready_to_transmit then @@ -25,7 +24,7 @@ feature -- Execution else -- Report internal server error. -- Response not ready to transmit! - -- Implementor of EWSGI_APPLICATION has not done his job! + -- Implementor of WGI_APPLICATION has not done his job! create rs.make rs.set_status (500) rs.set_header ("Content-Type", "text/plain") @@ -36,7 +35,7 @@ feature -- Execution feature -- Response - response (request: EWSGI_REQUEST): EWSGI_RESPONSE + response (request: WGI_REQUEST): WGI_RESPONSE -- HTTP response for given 'request'. deferred ensure diff --git a/library/server/ewsgi/src/request/ewsgi_cookie.e b/library/server/ewsgi/src/request/ewsgi_cookie.e deleted file mode 100644 index 262ef4b6..00000000 --- a/library/server/ewsgi/src/request/ewsgi_cookie.e +++ /dev/null @@ -1,76 +0,0 @@ -note - description: "[ - Contains all information of a rfc2109 cookie that was read from the request header - ]" - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -class - EWSGI_COOKIE - -create - make - -convert - value: {READABLE_STRING_8, STRING_8, READABLE_STRING_GENERAL, STRING_GENERAL} - -feature {NONE} -- Initialization - - make (a_name: STRING; a_value: STRING) - -- Creates current. - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - a_value_not_empty: a_value /= Void and then not a_value.is_empty - do - name := a_name - value := a_value - ensure - a_name_set: name = a_name - a_value_set: value = a_value - end - -feature -- Access - - name: STRING - -- Required. The name of the state information ("cookie") is NAME, - -- and its value is VALUE. NAMEs that begin with $ are reserved for - -- other uses and must not be used by applications. - - value: STRING - -- The VALUE is opaque to the user agent and may be anything the - -- origin server chooses to send, possibly in a server-selected - -- printable ASCII encoding. "Opaque" implies that the content is of - -- interest and relevance only to the origin server. The content - -- may, in fact, be readable by anyone that examines the Set-Cookie - -- header. - -feature -- Query - - variables: detachable HASH_TABLE [STRING, STRING] - -- Potential variable contained in the encoded cookie's value. - -feature -- Status report - - value_is_string (s: READABLE_STRING_GENERAL): BOOLEAN - -- Is `value' same string as `s' - do - Result := s.same_string (value) - end - -invariant - name_attached: name /= Void - value_attached: value /= Void - -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/request/ewsgi_environment.e b/library/server/ewsgi/src/request/ewsgi_environment.e deleted file mode 100644 index cb19ebe2..00000000 --- a/library/server/ewsgi/src/request/ewsgi_environment.e +++ /dev/null @@ -1,617 +0,0 @@ -note - description: "[ - - Interface for a request environment - It includes CGI interface and a few extra values that are usually valuable - - See http://www.ietf.org/rfc/rfc3875 - - 2.2. Basic Rules - - The following rules are used throughout this specification to - describe basic parsing constructs. - - alpha = lowalpha | hialpha - lowalpha = a | b | c | d | e | f | g | h | - i | j | k | l | m | n | o | p | - q | r | s | t | u | v | w | x | - y | z - hialpha = A | B | C | D | E | F | G | H | - I | J | K | L | M | N | O | P | - Q | R | S | T | U | V | W | X | - Y | Z - digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | - 8 | 9 - alphanum = alpha | digit - OCTET = - CHAR = alpha | digit | separator | ! | # | $ | - %% | & | ' | * | + | - | . | ` | - ^ | _ | { | | | } | ~ | CTL - CTL = - SP = - HT = - NL = - LWSP = SP | HT | NL - separator = ( | ) | < | > | @ | , | ; | : | - \ | " | / | [ | ] | ? | = | { | - } | SP | HT - token = 1* - quoted-string = " *qdtext " - qdtext = - TEXT = - - 2.3. URL Encoding - - reserved = ; | / | ? | : | @ | & | = | + | $ | - , | [ | ] - - hex = digit | A | B | C | D | E | F | a | b - | c | d | e | f - escaped = "%%" hex hex - unreserved = alpha | digit | mark - mark = - | _ | . | ! | ~ | * | ' | ( | ) - - Note that newline (NL) need not be a single character, but can - be a character sequence. - - 3.2. The Script-URI - - script-URI = "://" ":" - "?" - - where is found from SERVER_PROTOCOL, , - and are the values of the respective - meta-variables. The SCRIPT_NAME and PATH_INFO values, URL-encoded - with ";", "=" and "?" reserved, give and . - - ]" - 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 - EWSGI_ENVIRONMENT - -inherit - EWSGI_VARIABLES [STRING_8] - - ITERABLE [STRING_8] - -feature -- Access - - table: HASH_TABLE [STRING, STRING] - -- These variables are specific to requests made with HTTP. - -- Interpretation of these variables may depend on the value of - -- SERVER_PROTOCOL. - -- - -- Environment variables with names beginning with "HTTP_" contain - -- header data read from the client, if the protocol used was HTTP. - -- The HTTP header name is converted to upper case, has all - -- occurrences of "-" replaced with "_" and has "HTTP_" prepended to - -- give the environment variable name. The header data may be - -- presented as sent by the client, or may be rewritten in ways which - -- do not change its semantics. If multiple headers with the same - -- field-name are received then they must be rewritten as a single - -- header having the same semantics. Similarly, a header that is - -- received on more than one line must be merged onto a single line. - -- The server must, if necessary, change the representation of the - -- data (for example, the character set) to be appropriate for a CGI - -- environment variable. - -- - -- The server is not required to create environment variables for all - -- the headers that it receives. In particular, it may remove any - -- headers carrying authentication information, such as - -- "Authorization"; it may remove headers whose value is available to - -- the script via other variables, such as "Content-Length" and - -- "Content-Type". - -- - -- For convenience it might also include the following CGI entries - deferred - end - -feature -- Access: table - - new_cursor: HASH_TABLE_ITERATION_CURSOR [STRING_8, STRING_8] - -- Fresh cursor associated with current structure - do - create Result.make (table) - end - -feature -- Common Gateway Interface - 1.1 8 January 1996 - - auth_type: detachable STRING - -- This variable is specific to requests made via the "http" - -- scheme. - -- - -- If the Script-URI required access authentication for external - -- access, then the server MUST set the value of this variable - -- from the 'auth-scheme' token in the request's "Authorization" - -- header field. Otherwise it is set to NULL. - -- - -- AUTH_TYPE = "" | auth-scheme - -- auth-scheme = "Basic" | "Digest" | token - -- - -- HTTP access authentication schemes are described in section 11 - -- of the HTTP/1.1 specification [8]. The auth-scheme is not - -- case-sensitive. - -- - -- Servers MUST provide this metavariable to scripts if the - -- request header included an "Authorization" field that was - -- authenticated. - deferred - end - - content_length: detachable STRING - -- This metavariable is set to the size of the message-body - -- entity attached to the request, if any, in decimal number of - -- octets. If no data are attached, then this metavariable is - -- either NULL or not defined. The syntax is the same as for the - -- HTTP "Content-Length" header field (section 14.14, HTTP/1.1 - -- specification [8]). - -- - -- CONTENT_LENGTH = "" | 1*digit - -- - -- Servers MUST provide this metavariable to scripts if the - -- request was accompanied by a message-body entity. - deferred - end - - content_length_value: INTEGER - -- Integer value related to `content_length" - deferred - end - - content_type: detachable STRING - -- If the request includes a message-body, CONTENT_TYPE is set to - -- the Internet Media Type [9] of the attached entity if the type - -- was provided via a "Content-type" field in the request header, - -- or if the server can determine it in the absence of a supplied - -- "Content-type" field. The syntax is the same as for the HTTP - -- "Content-Type" header field. - -- - -- CONTENT_TYPE = "" | media-type - -- media-type = type "/" subtype *( ";" parameter) - -- type = token - -- subtype = token - -- parameter = attribute "=" value - -- attribute = token - -- value = token | quoted-string - -- - -- The type, subtype, and parameter attribute names are not - -- case-sensitive. Parameter values MAY be case sensitive. Media - -- types and their use in HTTP are described in section 3.7 of - -- the HTTP/1.1 specification [8]. - -- - -- Example: - -- - -- application/x-www-form-urlencoded - -- - -- There is no default value for this variable. If and only if it - -- is unset, then the script MAY attempt to determine the media - -- type from the data received. If the type remains unknown, then - -- the script MAY choose to either assume a content-type of - -- application/octet-stream or reject the request with a 415 - -- ("Unsupported Media Type") error. See section 7.2.1.3 for more - -- information about returning error status values. - -- - -- Servers MUST provide this metavariable to scripts if a - -- "Content-Type" field was present in the original request - -- header. If the server receives a request with an attached - -- entity but no "Content-Type" header field, it MAY attempt to - -- determine the correct datatype, or it MAY omit this - -- metavariable when communicating the request information to the - -- script. - deferred - end - - gateway_interface: STRING - -- This metavariable is set to the dialect of CGI being used by - -- the server to communicate with the script. Syntax: - -- - -- GATEWAY_INTERFACE = "CGI" "/" major "." minor - -- major = 1*digit - -- minor = 1*digit - -- - -- Note that the major and minor numbers are treated as separate - -- integers and hence each may be more than a single digit. Thus - -- CGI/2.4 is a lower version than CGI/2.13 which in turn is - -- lower than CGI/12.3. Leading zeros in either the major or the - -- minor number MUST be ignored by scripts and SHOULD NOT be - -- generated by servers. - -- - -- This document defines the 1.1 version of the CGI interface - -- ("CGI/1.1"). - -- - -- Servers MUST provide this metavariable to scripts. - -- - -- The version of the CGI specification to which this server - -- complies. Syntax: - -- - -- GATEWAY_INTERFACE = "CGI" "/" 1*digit "." 1*digit - -- - -- Note that the major and minor numbers are treated as separate - -- integers and that each may be incremented higher than a single - -- digit. Thus CGI/2.4 is a lower version than CGI/2.13 which in - -- turn is lower than CGI/12.3. Leading zeros must be ignored by - -- scripts and should never be generated by servers. - deferred - end - - path_info: STRING assign update_path_info - -- The PATH_INFO metavariable specifies a path to be interpreted - -- by the CGI script. It identifies the resource or sub-resource - -- to be returned by the CGI script, and it is derived from the - -- portion of the URI path following the script name but - -- preceding any query data. The syntax and semantics are similar - -- to a decoded HTTP URL 'path' token (defined in RFC 2396 [4]), - -- with the exception that a PATH_INFO of "/" represents a single - -- void path segment. - -- - -- PATH_INFO = "" | ( "/" path ) - -- path = segment *( "/" segment ) - -- segment = *pchar - -- pchar = - -- - -- The PATH_INFO string is the trailing part of the - -- component of the Script-URI (see section 3.2) that follows the - -- SCRIPT_NAME portion of the path. - -- - -- Servers MAY impose their own restrictions and limitations on - -- what values they will accept for PATH_INFO, and MAY reject or - -- edit any values they consider objectionable before passing - -- them to the script. - -- - -- Servers MUST make this URI component available to CGI scripts. - -- The PATH_INFO value is case-sensitive, and the server MUST - -- preserve the case of the PATH_INFO element of the URI when - -- making it available to scripts. - deferred - end - - path_translated: detachable STRING - -- PATH_TRANSLATED is derived by taking any path-info component - -- of the request URI (see section 6.1.6), decoding it (see - -- section 3.1), parsing it as a URI in its own right, and - -- performing any virtual-to-physical translation appropriate to - -- map it onto the server's document repository structure. If the - -- request URI includes no path-info component, the - -- PATH_TRANSLATED metavariable SHOULD NOT be defined. - -- - -- - -- PATH_TRANSLATED = *CHAR - -- - -- For a request such as the following: - -- - -- http://somehost.com/cgi-bin/somescript/this%2eis%2epath%2einfo - -- - -- the PATH_INFO component would be decoded, and the result - -- parsed as though it were a request for the following: - -- - -- http://somehost.com/this.is.the.path.info - -- - -- This would then be translated to a location in the server's - -- document repository, perhaps a filesystem path something like - -- this: - -- - -- /usr/local/www/htdocs/this.is.the.path.info - -- - -- The result of the translation is the value of PATH_TRANSLATED. - -- - -- The value of PATH_TRANSLATED may or may not map to a valid - -- repository location. Servers MUST preserve the case of the - -- path-info segment if and only if the underlying repository - -- supports case-sensitive names. If the repository is only - -- case-aware, case-preserving, or case-blind with regard to - -- document names, servers are not required to preserve the case - -- of the original segment through the translation. - -- - -- The translation algorithm the server uses to derive - -- PATH_TRANSLATED is implementation defined; CGI scripts which - -- use this variable may suffer limited portability. - -- - -- Servers SHOULD provide this metavariable to scripts if and - -- only if the request URI includes a path-info component. - deferred - end - - query_string: STRING - -- A URL-encoded string; the part of the Script-URI. (See - -- section 3.2.) - -- - -- QUERY_STRING = query-string - -- query-string = *uric - - -- The URL syntax for a query string is described in section 3 of - -- RFC 2396 [4]. - -- - -- Servers MUST supply this value to scripts. The QUERY_STRING - -- value is case-sensitive. If the Script-URI does not include a - -- query component, the QUERY_STRING metavariable MUST be defined - -- as an empty string (""). - deferred - end - - remote_addr: STRING - -- The IP address of the client sending the request to the - -- server. This is not necessarily that of the user agent (such - -- as if the request came through a proxy). - -- - -- REMOTE_ADDR = hostnumber - -- hostnumber = ipv4-address | ipv6-address - - -- The definitions of ipv4-address and ipv6-address are provided - -- in Appendix B of RFC 2373 [13]. - -- - -- Servers MUST supply this value to scripts. - deferred - end - - remote_host: detachable STRING - -- The fully qualified domain name of the client sending the - -- request to the server, if available, otherwise NULL. (See - -- section 6.1.9.) Fully qualified domain names take the form as - -- described in section 3.5 of RFC 1034 [10] and section 2.1 of - -- RFC 1123 [5]. Domain names are not case sensitive. - -- - -- Servers SHOULD provide this information to scripts. - deferred - end - - remote_ident: detachable STRING - -- The identity information reported about the connection by a - -- RFC 1413 [11] request to the remote agent, if available. - -- Servers MAY choose not to support this feature, or not to - -- request the data for efficiency reasons. - -- - -- REMOTE_IDENT = *CHAR - -- - -- The data returned may be used for authentication purposes, but - -- the level of trust reposed in them should be minimal. - -- - -- Servers MAY supply this information to scripts if the RFC1413 - -- [11] lookup is performed. - deferred - end - - remote_user: detachable STRING - -- If the request required authentication using the "Basic" - -- mechanism (i.e., the AUTH_TYPE metavariable is set to - -- "Basic"), then the value of the REMOTE_USER metavariable is - -- set to the user-ID supplied. In all other cases the value of - -- this metavariable is undefined. - -- - -- REMOTE_USER = *OCTET - -- - -- This variable is specific to requests made via the HTTP - -- protocol. - -- - -- Servers SHOULD provide this metavariable to scripts. - deferred - end - - request_method: STRING - -- The REQUEST_METHOD metavariable is set to the method with - -- which the request was made, as described in section 5.1.1 of - -- the HTTP/1.0 specification [3] and section 5.1.1 of the - -- HTTP/1.1 specification [8]. - -- - -- REQUEST_METHOD = http-method - -- http-method = "GET" | "HEAD" | "POST" | "PUT" | "DELETE" - -- | "OPTIONS" | "TRACE" | extension-method - -- extension-method = token - -- - -- The method is case sensitive. CGI/1.1 servers MAY choose to - -- process some methods directly rather than passing them to - -- scripts. - -- - -- This variable is specific to requests made with HTTP. - -- - -- Servers MUST provide this metavariable to scripts. - deferred - end - - script_name: STRING - -- The SCRIPT_NAME metavariable is set to a URL path that could - -- identify the CGI script (rather than the script's output). The - -- syntax and semantics are identical to a decoded HTTP URL - -- 'path' token (see RFC 2396 [4]). - -- - -- SCRIPT_NAME = "" | ( "/" [ path ] ) - -- - -- The SCRIPT_NAME string is some leading part of the - -- component of the Script-URI derived in some implementation - -- defined manner. No PATH_INFO or QUERY_STRING segments (see - -- sections 6.1.6 and 6.1.8) are included in the SCRIPT_NAME - -- value. - -- - -- Servers MUST provide this metavariable to scripts. - deferred - end - - server_name: STRING - -- The SERVER_NAME metavariable is set to the name of the server, - -- as derived from the part of the Script-URI (see section - -- 3.2). - -- - -- SERVER_NAME = hostname | hostnumber - -- - -- Servers MUST provide this metavariable to scripts. - deferred - end - - server_port: INTEGER - -- The SERVER_PORT metavariable is set to the port on which the - -- request was received, as used in the part of the - -- Script-URI. - -- - -- SERVER_PORT = 1*digit - -- - -- If the portion of the script-URI is blank, the actual - -- port number upon which the request was received MUST be - -- supplied. - -- - -- Servers MUST provide this metavariable to scripts. - deferred - end - - server_protocol: STRING - -- The SERVER_PROTOCOL metavariable is set to the name and - -- revision of the information protocol with which the request - -- arrived. This is not necessarily the same as the protocol - -- version used by the server in its response to the client. - -- - -- SERVER_PROTOCOL = HTTP-Version | extension-version - -- | extension-token - -- HTTP-Version = "HTTP" "/" 1*digit "." 1*digit - -- extension-version = protocol "/" 1*digit "." 1*digit - -- protocol = 1*( alpha | digit | "+" | "-" | "." ) - -- extension-token = token - -- - -- 'protocol' is a version of the part of the - -- Script-URI, but is not identical to it. For example, the - -- scheme of a request may be "https" while the protocol remains - -- "http". The protocol is not case sensitive, but by convention, - -- 'protocol' is in upper case. - -- - -- A well-known extension token value is "INCLUDED", which - -- signals that the current document is being included as part of - -- a composite document, rather than being the direct target of - -- the client request. - -- - -- Servers MUST provide this metavariable to scripts. - deferred - end - - server_software: STRING - -- The SERVER_SOFTWARE metavariable is set to the name and - -- version of the information server software answering the - -- request (and running the gateway). - -- - -- SERVER_SOFTWARE = 1*product - -- product = token [ "/" product-version ] - -- product-version = token - - -- Servers MUST provide this metavariable to scripts. - deferred - end - -feature -- HTTP_* - - http_accept: detachable STRING - -- Contents of the Accept: header from the current request, if there is one. - -- Example: 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' - deferred - end - - http_accept_charset: detachable STRING - -- Contents of the Accept-Charset: header from the current request, if there is one. - -- Example: 'iso-8859-1,*,utf-8'. - deferred - end - - http_accept_encoding: detachable STRING - -- Contents of the Accept-Encoding: header from the current request, if there is one. - -- Example: 'gzip'. - deferred - end - - http_accept_language: detachable STRING - -- Contents of the Accept-Language: header from the current request, if there is one. - -- Example: 'en'. - deferred - end - - http_connection: detachable STRING - -- Contents of the Connection: header from the current request, if there is one. - -- Example: 'Keep-Alive'. - deferred - end - - http_host: detachable STRING - -- Contents of the Host: header from the current request, if there is one. - deferred - end - - http_referer: detachable STRING - -- The address of the page (if any) which referred the user agent to the current page. - -- This is set by the user agent. - -- Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. - -- In short, it cannot really be trusted. - deferred - end - - http_user_agent: detachable STRING - -- Contents of the User-Agent: header from the current request, if there is one. - -- This is a string denoting the user agent being which is accessing the page. - -- A typical example is: Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586). - -- Among other things, you can use this value to tailor your page's - -- output to the capabilities of the user agent. - deferred - end - - http_authorization: detachable STRING - -- Contents of the Authorization: header from the current request, if there is one. - deferred - end - -feature -- Extra - - request_uri: STRING - -- The URI which was given in order to access this page; for instance, '/index.html'. - deferred - end - - orig_path_info: detachable STRING - -- Original version of `path_info' before processed by Current environment - deferred - end - -feature {EWSGI_REQUEST} -- Element change - - set_orig_path_info (s: STRING) - -- Set ORIG_PATH_INFO to `s' - require - s_attached: s /= Void - deferred - ensure - same_orig_path_info: orig_path_info ~ variable ({EWSGI_ENVIRONMENT_NAMES}.orig_path_info) - end - - unset_orig_path_info - -- Unset ORIG_PATH_INFO - deferred - ensure - unset: not has_variable ({EWSGI_ENVIRONMENT_NAMES}.orig_path_info) - end - - update_path_info (a_path_info: like path_info) - -- Updated PATH_INFO - deferred - ensure - same_path_info: path_info ~ variable ({EWSGI_ENVIRONMENT_NAMES}.path_info) - end - -invariant - server_name_not_empty: not server_name.is_empty - server_port_set: server_port /= 0 - request_method_attached: request_method /= Void - path_info_attached: path_info /= Void - query_string_attached: query_string /= Void - remote_addr_attached: remote_addr /= Void - - path_info_identical: path_info ~ variable ({EWSGI_ENVIRONMENT_NAMES}.path_info) - -;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/request/ewsgi_environment_names.e b/library/server/ewsgi/src/request/ewsgi_environment_names.e deleted file mode 100644 index 46860b5d..00000000 --- a/library/server/ewsgi/src/request/ewsgi_environment_names.e +++ /dev/null @@ -1,89 +0,0 @@ -note - description: "Summary description for {EWSGI_ENVIRONMENT_NAMES}." - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -class - EWSGI_ENVIRONMENT_NAMES - -feature -- Access - - request_uri: STRING = "REQUEST_URI" - - request_method: STRING = "REQUEST_METHOD" - - query_string: STRING = "QUERY_STRING" - - content_type: STRING = "CONTENT_TYPE" - - content_length: STRING = "CONTENT_LENGTH" - - path_info: STRING = "PATH_INFO" - - path_translated: STRING = "PATH_TRANSLATED" - - http_user_agent: STRING = "HTTP_USER_AGENT" - - http_authorization: STRING = "HTTP_AUTHORIZATION" - - http_host: STRING = "HTTP_HOST" - - http_cookie: STRING = "HTTP_COOKIE" - - http_from: STRING = "HTTP_FROM" - - http_accept: STRING = "HTTP_ACCEPT" - - http_accept_charset: STRING = "HTTP_ACCEPT_CHARSET" - - http_accept_encoding: STRING = "HTTP_ACCEPT_ENCODING" - - http_accept_language: STRING = "HTTP_ACCEPT_LANGUAGE" - - http_connection: STRING = "HTTP_CONNECTION" - - http_referer: STRING = "HTTP_REFERER" - - gateway_interface: STRING = "GATEWAY_INTERFACE" - - auth_type: STRING = "AUTH_TYPE" - - remote_host: STRING = "REMOTE_HOST" - - remote_addr: STRING = "REMOTE_ADDR" - - remote_ident: STRING = "REMOTE_IDENT" - - remote_user: STRING = "REMOTE_USER" - - script_name: STRING = "SCRIPT_NAME" - - server_name: STRING = "SERVER_NAME" - - server_port: STRING = "SERVER_PORT" - - server_protocol: STRING = "SERVER_PROTOCOL" - - server_software: STRING = "SERVER_SOFTWARE" - -feature -- Extra names - - request_time: STRING = "REQUEST_TIME" - - self: STRING = "SELF" - - orig_path_info: STRING = "ORIG_PATH_INFO" - -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/request/ewsgi_environment_variables.e b/library/server/ewsgi/src/request/ewsgi_environment_variables.e deleted file mode 100644 index bdb7cdf1..00000000 --- a/library/server/ewsgi/src/request/ewsgi_environment_variables.e +++ /dev/null @@ -1,292 +0,0 @@ -note - description: "Summary description for {EWSGI_ENVIRONMENT_VARIABLES}." - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -class - EWSGI_ENVIRONMENT_VARIABLES - -inherit - EWSGI_ENVIRONMENT - redefine - update_path_info - end - -create - make_with_variables - -feature {NONE} -- Initialization - - make_with_variables (a_vars: HASH_TABLE [STRING, STRING]) - -- Fill with variable from `a_vars' - local - s: detachable STRING - do - create empty_string.make_empty - - create table.make (a_vars.count) - from - a_vars.start - until - a_vars.after - loop - table.force (a_vars.item_for_iteration, a_vars.key_for_iteration) - a_vars.forth - end - - --| QUERY_STRING - query_string := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.query_string, empty_string, False) - - --| REQUEST_METHOD - request_method := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.request_method, empty_string, False) - - --| CONTENT_TYPE - s := variable ({EWSGI_ENVIRONMENT_NAMES}.content_type) - if s /= Void and then not s.is_empty then - content_type := s - else - content_type := Void - end - - --| CONTENT_LENGTH - s := variable ({EWSGI_ENVIRONMENT_NAMES}.content_length) - content_length := s - if s /= Void and then s.is_integer then - content_length_value := s.to_integer - else - --| content_length := 0 - end - - --| PATH_INFO - path_info := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.path_info, empty_string, False) - - --| SERVER_NAME - server_name := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.server_name, empty_string, False) - - --| SERVER_PORT - s := variable ({EWSGI_ENVIRONMENT_NAMES}.server_port) - if s /= Void and then s.is_integer then - server_port := s.to_integer - else - server_port := 80 - end - - --| SCRIPT_NAME - script_name := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.script_name, empty_string, False) - - --| REMOTE_ADDR - remote_addr := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.remote_addr, empty_string, False) - - --| REMOTE_HOST - remote_host := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.remote_host, empty_string, False) - - --| REQUEST_URI - request_uri := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.request_uri, empty_string, False) - end - -feature -- Access - - table: HASH_TABLE [STRING, STRING] - -feature -- Access - - variable (a_name: STRING): detachable STRING - do - Result := table.item (a_name) - end - - has_variable (a_name: STRING): BOOLEAN - do - Result := table.has_key (a_name) - end - -feature {EWSGI_REQUEST, EWSGI_APPLICATION, EWSGI_CONNECTOR} -- Element change - - set_variable (a_name: STRING; a_value: STRING) - do - table.force (a_value, a_name) - end - - unset_variable (a_name: STRING) - do - table.remove (a_name) - end - -feature -- Common Gateway Interface - 1.1 8 January 1996 - - auth_type: detachable STRING - - content_length: detachable STRING - - content_length_value: INTEGER - - content_type: detachable STRING - - gateway_interface: STRING - do - Result := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.gateway_interface, "", False) - end - - path_info: STRING - -- - -- - --| For instance, if the current script was accessed via the URL - --| http://www.example.com/eiffel/path_info.exe/some/stuff?foo=bar, then $_SERVER['PATH_INFO'] would contain /some/stuff. - --| - --| Note that is the PATH_INFO variable does not exists, the `path_info' value will be empty - - path_translated: detachable STRING - do - Result := variable ({EWSGI_ENVIRONMENT_NAMES}.path_translated) - end - - query_string: STRING - - remote_addr: STRING - - remote_host: STRING - - remote_ident: detachable STRING - do - Result := variable ({EWSGI_ENVIRONMENT_NAMES}.remote_ident) - end - - remote_user: detachable STRING - do - Result := variable ({EWSGI_ENVIRONMENT_NAMES}.remote_user) - end - - request_method: STRING - - script_name: STRING - - server_name: STRING - - server_port: INTEGER - - server_protocol: STRING - do - Result := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.server_protocol, "HTTP/1.0", True) - end - - server_software: STRING - do - Result := variable_or_default ({EWSGI_ENVIRONMENT_NAMES}.server_software, "Unknown Server", True) - end - -feature -- HTTP_* - - http_accept: detachable STRING - -- Contents of the Accept: header from the current request, if there is one. - do - Result := table.item ({EWSGI_ENVIRONMENT_NAMES}.http_accept) - end - - http_accept_charset: detachable STRING - -- Contents of the Accept-Charset: header from the current request, if there is one. - -- Example: 'iso-8859-1,*,utf-8'. - do - Result := table.item ({EWSGI_ENVIRONMENT_NAMES}.http_accept_charset) - end - - http_accept_encoding: detachable STRING - -- Contents of the Accept-Encoding: header from the current request, if there is one. - -- Example: 'gzip'. - do - Result := table.item ({EWSGI_ENVIRONMENT_NAMES}.http_accept_encoding) - end - - http_accept_language: detachable STRING - -- Contents of the Accept-Language: header from the current request, if there is one. - -- Example: 'en'. - do - Result := table.item ({EWSGI_ENVIRONMENT_NAMES}.http_accept_language) - end - - http_connection: detachable STRING - -- Contents of the Connection: header from the current request, if there is one. - -- Example: 'Keep-Alive'. - do - Result := table.item ({EWSGI_ENVIRONMENT_NAMES}.http_connection) - end - - http_host: detachable STRING - -- Contents of the Host: header from the current request, if there is one. - do - Result := table.item ({EWSGI_ENVIRONMENT_NAMES}.http_host) - end - - http_referer: detachable STRING - -- The address of the page (if any) which referred the user agent to the current page. - -- This is set by the user agent. - -- Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. - -- In short, it cannot really be trusted. - do - Result := table.item ({EWSGI_ENVIRONMENT_NAMES}.http_referer) - end - - http_user_agent: detachable STRING - -- Contents of the User-Agent: header from the current request, if there is one. - -- This is a string denoting the user agent being which is accessing the page. - -- A typical example is: Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586). - -- Among other things, you can use this value to tailor your page's - -- output to the capabilities of the user agent. - do - Result := table.item ({EWSGI_ENVIRONMENT_NAMES}.http_user_agent) - end - - http_authorization: detachable STRING - -- Contents of the Authorization: header from the current request, if there is one. - do - Result := table.item ({EWSGI_ENVIRONMENT_NAMES}.http_authorization) - end - -feature -- Extra - - request_uri: STRING - -- The URI which was given in order to access this page; for instance, '/index.html'. - - orig_path_info: detachable STRING - -- Original version of `path_info' before processed by Current environment - -feature {EWSGI_REQUEST} -- Update - - set_orig_path_info (s: STRING) - do - orig_path_info := s - set_variable ({EWSGI_ENVIRONMENT_NAMES}.orig_path_info, s) - end - - unset_orig_path_info - do - orig_path_info := Void - unset_variable ({EWSGI_ENVIRONMENT_NAMES}.orig_path_info) - end - - update_path_info (a_path_info: like path_info) - do - path_info := a_path_info - set_variable ({EWSGI_ENVIRONMENT_NAMES}.path_info, a_path_info) - end - -feature {NONE} -- Implementation - - empty_string: STRING - -- Reusable empty string - -invariant - empty_string_unchanged: empty_string.is_empty - -;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/request/ewsgi_request_variables.e b/library/server/ewsgi/src/request/ewsgi_request_variables.e deleted file mode 100644 index 236dc135..00000000 --- a/library/server/ewsgi/src/request/ewsgi_request_variables.e +++ /dev/null @@ -1,147 +0,0 @@ -note - description: "[ - Variables/field related to the current request. - ]" - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -class - EWSGI_REQUEST_VARIABLES - -inherit - EWSGI_VARIABLES [STRING_32] - -create - make, - make_from_urlencoded - -feature -- Initialization - - make (n: INTEGER) - do - create table.make (n) - table.compare_objects - end - - make_from_urlencoded (a_content: STRING; decoding: BOOLEAN) - do - make (a_content.occurrences ('&') + 1) - import_urlencoded (a_content, decoding) - end - -feature -- Status report - - count: INTEGER - -- Variables count - do - Result := table.count - end - - variable (a_name: STRING): detachable STRING_32 - do - Result := table.item (a_name) - end - - has_variable (a_name: STRING): BOOLEAN - do - Result := table.has (a_name) - end - -feature {EWSGI_REQUEST, EWSGI_APPLICATION, EWSGI_CONNECTOR} -- Element change - - set_variable (a_name: STRING; a_value: STRING_32) - do - table.force (a_value, a_name) - end - - unset_variable (a_name: STRING) - do - table.remove (a_name) - end - -feature -- Import urlencoded - - import_urlencoded (a_content: STRING; decoding: BOOLEAN) - -- Import `a_content' - local - n, p, i, j: INTEGER - s: STRING - l_name,l_value: STRING_32 - do - n := a_content.count - if n > 0 then - from - p := 1 - until - p = 0 - loop - i := a_content.index_of ('&', p) - if i = 0 then - s := a_content.substring (p, n) - p := 0 - else - s := a_content.substring (p, i - 1) - p := i + 1 - end - if not s.is_empty then - j := s.index_of ('=', 1) - if j > 0 then - l_name := s.substring (1, j - 1) - l_value := s.substring (j + 1, s.count) - if decoding then - l_name := url_encoder.decoded_string (l_name) - l_value := url_encoder.decoded_string (l_value) - end - add_variable (l_value, l_name) - end - end - end - end - end - -feature -- Access: table - - new_cursor: HASH_TABLE_ITERATION_CURSOR [STRING_32, STRING_32] - -- Fresh cursor associated with current structure - do - create Result.make (table) - end - -feature {EWSGI_REQUEST} -- Element change - - add_variable (v: STRING_32; k: STRING_32) - -- Added `k,v' to variables table - -- Not exported to common client - -- Simulate Read Only Access - require - k_attached: k /= Void - v_attached: v /= Void - do - table.force (v, k) - end - -feature {EWSGI_REQUEST} -- Element change - - table: HASH_TABLE [STRING_32, STRING_32] - -- Variables table - -feature {NONE} -- Implementation - - url_encoder: URL_ENCODER - once - create Result - 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/request/ewsgi_uploaded_file_data.e b/library/server/ewsgi/src/request/ewsgi_uploaded_file_data.e deleted file mode 100644 index a8f2ea36..00000000 --- a/library/server/ewsgi/src/request/ewsgi_uploaded_file_data.e +++ /dev/null @@ -1,103 +0,0 @@ -note - description: "Summary description for {GW_UPLOADED_FILE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - EWSGI_UPLOADED_FILE_DATA - -create - make - -feature {NONE} -- Initialization - - make (n: like name; t: like content_type; s: like size) - do - name := n - content_type := t - size := s - end - -feature -- Access - - name: STRING - -- original filename - - content_type: STRING - -- Content type - - size: INTEGER - -- Size of uploaded file - - tmp_name: detachable STRING - -- Filename of tmp file - - tmp_basename: detachable STRING - -- Basename of tmp file - -feature -- Basic operation - - move_to (a_destination: STRING): BOOLEAN - -- Move current uploaded file to `a_destination' - require - has_no_error: not has_error - local - f: RAW_FILE - do - if attached tmp_name as n then - create f.make (n) - if f.exists then - f.change_name (a_destination) - Result := True - end - end - end - -feature -- Status - - has_error: BOOLEAN - -- Has error during uploading - do - Result := error /= 0 - end - - error: INTEGER - -- Eventual error code - --| no error => 0 - -feature -- Element change - - set_error (e: like error) - -- Set `error' to `e' - do - error := e - end - - set_tmp_name (n: like tmp_name) - -- Set `tmp_name' to `n' - do - tmp_name := n - end - - set_tmp_basename (n: like tmp_basename) - -- Set `tmp_basename' to `n' - do - tmp_basename := n - end - -invariant - - valid_tmp_name: not has_error implies attached tmp_name as n and then not n.is_empty - -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/request/ewsgi_request.e b/library/server/ewsgi/src/request/wgi_request_from_table.e similarity index 55% rename from library/server/ewsgi/src/request/ewsgi_request.e rename to library/server/ewsgi/src/request/wgi_request_from_table.e index 3cecdcc7..eeed7909 100644 --- a/library/server/ewsgi/src/request/ewsgi_request.e +++ b/library/server/ewsgi/src/request/wgi_request_from_table.e @@ -1,7 +1,6 @@ note description: "[ - EWSGI interface to represent the Request - + Request instanciated from a hash_table of meta variables ]" specification: "EWSGI specification https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki/EWSGI-specification" legal: "See notice at end of class." @@ -10,21 +9,23 @@ note revision: "$Revision$" class - EWSGI_REQUEST + WGI_REQUEST_FROM_TABLE + +inherit + WGI_REQUEST create make feature {NONE} -- Initialization - make (env: EWSGI_ENVIRONMENT; a_input: like input) + make (a_vars: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]; a_input: like input) require - env_attached: env /= Void + vars_attached: a_vars /= Void do create error_handler.make input := a_input - environment := env - content_length := env.content_length_value + set_meta_parameters (a_vars) create uploaded_files.make (0) raw_post_data_recorded := True @@ -33,26 +34,93 @@ feature {NONE} -- Initialization analyze end + set_meta_parameters (a_vars: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]) + -- Fill with variable from `a_vars' + local + s: like meta_variable + table: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] + do + create {STRING_32} empty_string.make_empty + + create table.make (a_vars.count) + meta_variables := table + from + a_vars.start + until + a_vars.after + loop + table.force (a_vars.item_for_iteration, a_vars.key_for_iteration) + a_vars.forth + end + + --| QUERY_STRING + query_string := meta_parameter_or_default ({WGI_META_NAMES}.query_string, empty_string, False) + + --| REQUEST_METHOD + request_method := meta_parameter_or_default ({WGI_META_NAMES}.request_method, empty_string, False) + + --| CONTENT_TYPE + s := meta_variable ({WGI_META_NAMES}.content_type) + if s /= Void and then not s.is_empty then + content_type := s + else + content_type := Void + end + + --| CONTENT_LENGTH + s := meta_variable ({WGI_META_NAMES}.content_length) + content_length := s + if s /= Void and then s.is_natural_64 then + content_length_value := s.to_natural_64 + else + --| content_length := 0 + end + + --| PATH_INFO + path_info := meta_parameter_or_default ({WGI_META_NAMES}.path_info, empty_string, False) + + --| SERVER_NAME + server_name := meta_parameter_or_default ({WGI_META_NAMES}.server_name, empty_string, False) + + --| SERVER_PORT + s := meta_variable ({WGI_META_NAMES}.server_port) + if s /= Void and then s.is_integer then + server_port := s.to_integer + else + server_port := 80 + end + + --| SCRIPT_NAME + script_name := meta_parameter_or_default ({WGI_META_NAMES}.script_name, empty_string, False) + + --| REMOTE_ADDR + remote_addr := meta_parameter_or_default ({WGI_META_NAMES}.remote_addr, empty_string, False) + + --| REMOTE_HOST + remote_host := meta_parameter_or_default ({WGI_META_NAMES}.remote_host, empty_string, False) + + --| REQUEST_URI + request_uri := meta_parameter_or_default ({WGI_META_NAMES}.request_uri, empty_string, False) + end + initialize -- Specific initialization local p: INTEGER - env: like environment do - env := environment --| Here one can set its own environment entries if needed --| do not use `force', to avoid overwriting existing variable - if attached env.request_uri as rq_uri then + if attached request_uri as rq_uri then p := rq_uri.index_of ('?', 1) if p > 0 then - env.set_variable (rq_uri.substring (1, p-1), {EWSGI_ENVIRONMENT_NAMES}.self) + set_meta_variable (rq_uri.substring (1, p-1), {WGI_META_NAMES}.self) else - env.set_variable (rq_uri, {EWSGI_ENVIRONMENT_NAMES}.self) + set_meta_variable (rq_uri, {WGI_META_NAMES}.self) end end - if env.variable ({EWSGI_ENVIRONMENT_NAMES}.request_time) = Void then - env.set_variable (date_time_utilities.unix_time_stamp (Void).out, {EWSGI_ENVIRONMENT_NAMES}.request_time) + if meta_variable ({WGI_META_NAMES}.request_time) = Void then + set_meta_variable (date_time_utilities.unix_time_stamp (Void).out, {WGI_META_NAMES}.request_time) end end @@ -62,15 +130,10 @@ feature {NONE} -- Initialization extract_variables end -feature -- Access: Input - - input: EWSGI_INPUT_STREAM - -- Server input channel - feature -- Status raw_post_data_recorded: BOOLEAN assign set_raw_post_data_recorded - -- Record RAW POST DATA in environment variables + -- Record RAW POST DATA in meta parameters -- otherwise just forget about it -- Default: true --| warning: you might keep in memory big amount of memory ... @@ -86,37 +149,261 @@ feature -- Error handling -- Error handler -- By default initialized to new handler -feature -- Access: environment variables +feature -- Access: Input - environment: EWSGI_ENVIRONMENT - -- Environment variables + input: WGI_INPUT_STREAM + -- Server input channel - environment_variable (a_name: STRING): detachable STRING - -- Environment variable related to `a_name' - require - a_name_valid: a_name /= Void and then not a_name.is_empty +feature -- Access extra information + + request_time: detachable DATE_TIME + -- Request time (UTC) do - Result := environment.variable (a_name) + if + attached meta_variable ({WGI_META_NAMES}.request_time) as t and then + t.is_integer_64 + then + Result := date_time_utilities.unix_time_stamp_to_date_time (t.to_integer_64) + end end - content_length: INTEGER - -- Extracted Content-Length value +feature -- Access: CGI meta parameters -feature -- URL parameters + meta_variables: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] + -- CGI Environment parameters - parameters: EWSGI_REQUEST_VARIABLES + meta_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + -- CGI meta variable related to `a_name' + do + Result := meta_variables.item (a_name) + end + + meta_parameter_or_default (a_name: READABLE_STRING_GENERAL; a_default: READABLE_STRING_32; use_default_when_empty: BOOLEAN): READABLE_STRING_32 + -- Value for meta parameter `a_name' + -- If not found, return `a_default' + require + a_name_not_empty: a_name /= Void and then not a_name.is_empty + do + if attached meta_variable (a_name) as s then + if use_default_when_empty and then s.is_empty then + Result := a_default + else + Result := s + end + else + Result := a_default + end + end + + set_meta_variable (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_32) + do + meta_variables.force (a_value, a_name) + ensure + param_set: meta_variable (a_name) ~ a_value + end + + unset_meta_variable (a_name: READABLE_STRING_GENERAL) + do + meta_variables.remove (a_name) + ensure + param_unset: meta_variable (a_name) = Void + end + +feature -- Access: CGI meta parameters - 1.1 + + auth_type: detachable READABLE_STRING_32 + + content_length: detachable READABLE_STRING_32 + + content_length_value: NATURAL_64 + + content_type: detachable READABLE_STRING_32 + + gateway_interface: READABLE_STRING_32 + do + Result := meta_parameter_or_default ({WGI_META_NAMES}.gateway_interface, "", False) + end + + path_info: READABLE_STRING_32 + -- + -- + --| For instance, if the current script was accessed via the URL + --| http://www.example.com/eiffel/path_info.exe/some/stuff?foo=bar, then $_SERVER['PATH_INFO'] would contain /some/stuff. + --| + --| Note that is the PATH_INFO variable does not exists, the `path_info' value will be empty + + path_translated: detachable READABLE_STRING_32 + do + Result := meta_variable ({WGI_META_NAMES}.path_translated) + end + + query_string: READABLE_STRING_32 + + remote_addr: READABLE_STRING_32 + + remote_host: READABLE_STRING_32 + + remote_ident: detachable READABLE_STRING_32 + do + Result := meta_variable ({WGI_META_NAMES}.remote_ident) + end + + remote_user: detachable READABLE_STRING_32 + do + Result := meta_variable ({WGI_META_NAMES}.remote_user) + end + + request_method: READABLE_STRING_32 + + script_name: READABLE_STRING_32 + + server_name: READABLE_STRING_32 + + server_port: INTEGER + + server_protocol: READABLE_STRING_32 + do + Result := meta_parameter_or_default ({WGI_META_NAMES}.server_protocol, "HTTP/1.0", True) + end + + server_software: READABLE_STRING_32 + do + Result := meta_parameter_or_default ({WGI_META_NAMES}.server_software, "Unknown Server", True) + end + +feature -- Access: HTTP_* CGI meta parameters - 1.1 + + http_accept: detachable READABLE_STRING_32 + -- Contents of the Accept: header from the current request, if there is one. + do + Result := meta_variable ({WGI_META_NAMES}.http_accept) + end + + http_accept_charset: detachable READABLE_STRING_32 + -- Contents of the Accept-Charset: header from the current request, if there is one. + -- Example: 'iso-8859-1,*,utf-8'. + do + Result := meta_variable ({WGI_META_NAMES}.http_accept_charset) + end + + http_accept_encoding: detachable READABLE_STRING_32 + -- Contents of the Accept-Encoding: header from the current request, if there is one. + -- Example: 'gzip'. + do + Result := meta_variable ({WGI_META_NAMES}.http_accept_encoding) + end + + http_accept_language: detachable READABLE_STRING_32 + -- Contents of the Accept-Language: header from the current request, if there is one. + -- Example: 'en'. + do + Result := meta_variable ({WGI_META_NAMES}.http_accept_language) + end + + http_connection: detachable READABLE_STRING_32 + -- Contents of the Connection: header from the current request, if there is one. + -- Example: 'Keep-Alive'. + do + Result := meta_variable ({WGI_META_NAMES}.http_connection) + end + + http_host: detachable READABLE_STRING_32 + -- Contents of the Host: header from the current request, if there is one. + do + Result := meta_variable ({WGI_META_NAMES}.http_host) + end + + http_referer: detachable READABLE_STRING_32 + -- The address of the page (if any) which referred the user agent to the current page. + -- This is set by the user agent. + -- Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. + -- In short, it cannot really be trusted. + do + Result := meta_variable ({WGI_META_NAMES}.http_referer) + end + + http_user_agent: detachable READABLE_STRING_32 + -- Contents of the User-Agent: header from the current request, if there is one. + -- This is a string denoting the user agent being which is accessing the page. + -- A typical example is: Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586). + -- Among other things, you can use this value to tailor your page's + -- output to the capabilities of the user agent. + do + Result := meta_variable ({WGI_META_NAMES}.http_user_agent) + end + + http_authorization: detachable READABLE_STRING_32 + -- Contents of the Authorization: header from the current request, if there is one. + do + Result := meta_variable ({WGI_META_NAMES}.http_authorization) + end + +feature -- Access: Extension to CGI meta parameters - 1.1 + + request_uri: READABLE_STRING_32 + -- The URI which was given in order to access this page; for instance, '/index.html'. + + orig_path_info: detachable READABLE_STRING_32 + -- Original version of `path_info' before processed by Current environment + +feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO + + set_orig_path_info (s: READABLE_STRING_32) + -- Set ORIG_PATH_INFO to `s' + require + s_attached: s /= Void + do + orig_path_info := s + set_meta_variable ({WGI_META_NAMES}.orig_path_info, s) + end + + unset_orig_path_info + -- Unset ORIG_PATH_INFO + do + orig_path_info := Void + unset_meta_variable ({WGI_META_NAMES}.orig_path_info) + ensure + unset: attached meta_variable ({WGI_META_NAMES}.orig_path_info) + end + + update_path_info + -- Fix and update PATH_INFO value if needed + local + l_path_info: STRING + do + l_path_info := path_info + --| Warning + --| on IIS: we might have PATH_INFO = /sample.exe/foo/bar + --| on apache: PATH_INFO = /foo/bar + --| So, we might need to check with SCRIPT_NAME and remove it on IIS + --| store original PATH_INFO in ORIG_PATH_INFO + if l_path_info.is_empty then + unset_orig_path_info + else + set_orig_path_info (l_path_info) + if attached script_name as l_script_name then + if l_path_info.starts_with (l_script_name) then + path_info := l_path_info.substring (l_script_name.count + 1 , l_path_info.count) + end + end + end + end + +feature -- Query parameters + + query_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] -- Variables extracted from QUERY_STRING local - vars: like internal_parameters + vars: like internal_query_parameters p,e: INTEGER - rq_uri: like environment.request_uri + rq_uri: like request_uri s: detachable STRING do - vars := internal_parameters + vars := internal_query_parameters if vars = Void then - s := environment.query_string + s := query_string if s = Void then - rq_uri := environment.request_uri + rq_uri := request_uri p := rq_uri.index_of ('?', 1) if p > 0 then e := rq_uri.index_of ('#', p + 1) @@ -128,71 +415,110 @@ feature -- URL parameters s := rq_uri.substring (p+1, e) end end - if s /= Void and then not s.is_empty then - create vars.make_from_urlencoded (s, True) - else - create vars.make (0) - end - internal_parameters := vars + vars := urlencoded_parameters (s, True) + internal_query_parameters := vars end Result := vars end - parameter (a_name: STRING): detachable STRING_32 + query_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- Parameter for name `n'. - require - a_name_valid: a_name /= Void and then not a_name.is_empty do - Result := parameters.variable (a_name) + Result := query_parameters.item (a_name) + end + +feature {NONE} -- Query parameters: implementation + + urlencoded_parameters (a_content: detachable READABLE_STRING_8; decoding: BOOLEAN): HASH_TABLE [READABLE_STRING_32, STRING] + -- Import `a_content' + local + n, p, i, j: INTEGER + s: STRING + l_name,l_value: STRING_32 + do + if a_content = Void then + create Result.make (0) + else + n := a_content.count + if n = 0 then + create Result.make (0) + else + create Result.make (3) + from + p := 1 + until + p = 0 + loop + i := a_content.index_of ('&', p) + if i = 0 then + s := a_content.substring (p, n) + p := 0 + else + s := a_content.substring (p, i - 1) + p := i + 1 + end + if not s.is_empty then + j := s.index_of ('=', 1) + if j > 0 then + l_name := s.substring (1, j - 1) + l_value := s.substring (j + 1, s.count) + if decoding then + l_name := url_encoder.decoded_string (l_name) + l_value := url_encoder.decoded_string (l_value) + end + Result.force (l_value, l_name) + end + end + end + end + end end feature -- Form fields and related - form_fields: EWSGI_REQUEST_VARIABLES + form_data_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] -- Variables sent by POST request local - vars: like internal_form_fields + vars: like internal_form_data_parameters s: STRING - n: INTEGER - l_type: detachable STRING + n: NATURAL_64 + l_type: like content_type do - vars := internal_form_fields + vars := internal_form_data_parameters if vars = Void then - n := content_length + n := content_length_value if n > 0 then - l_type := environment.content_type + l_type := content_type if l_type /= Void and then l_type.starts_with ({HTTP_CONSTANTS}.multipart_form) then create vars.make (5) --| FIXME: optimization ... fetch the input data progressively, otherwise we might run out of memory ... - s := form_input_data (n) + s := form_input_data (n.to_integer_32) --| FIXME truncated from NAT64 to INT32 analyze_multipart_form (l_type, s, vars) else - s := form_input_data (n) - create vars.make_from_urlencoded (s, True) + s := form_input_data (n.to_integer_32) --| FIXME truncated from NAT64 to INT32 + vars := urlencoded_parameters (s, True) end if raw_post_data_recorded then - vars.add_variable (s, "RAW_POST_DATA") + vars.force (s, "RAW_POST_DATA") end else create vars.make (0) end - internal_form_fields := vars + internal_form_data_parameters := vars end Result := vars end - form_field (a_name: STRING): detachable STRING_32 + form_data_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- Field for name `a_name'. - require - a_name_valid: a_name /= Void and then not a_name.is_empty do - Result := form_fields.variable (a_name) + Result := form_data_parameters.item (a_name) end - uploaded_files: HASH_TABLE [EWSGI_UPLOADED_FILE_DATA, STRING] + uploaded_files: HASH_TABLE [WGI_UPLOADED_FILE_DATA, STRING] -- Table of uploaded files information --| name: original path from the user --| type: content type @@ -203,45 +529,8 @@ feature -- Form fields and related feature -- Cookies - cookies_variables: HASH_TABLE [STRING, STRING] + cookies: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] -- Expanded cookies variable - local - l_cookies: like cookies - do - l_cookies := cookies - create Result.make (l_cookies.count) - from - l_cookies.start - until - l_cookies.after - loop - if attached l_cookies.item_for_iteration.variables as vars then - from - vars.start - until - vars.after - loop - Result.force (vars.item_for_iteration, vars.key_for_iteration) - vars.forth - end - else - check same_name: l_cookies.key_for_iteration.same_string (l_cookies.item_for_iteration.name) end - Result.force (l_cookies.item_for_iteration.value, l_cookies.key_for_iteration) - end - l_cookies.forth - end - end - - cookies_variable (a_name: STRING): detachable STRING - -- Field for name `a_name'. - require - a_name_valid: a_name /= Void and then not a_name.is_empty - do - Result := cookies_variables.item (a_name) - end - - cookies: HASH_TABLE [EWSGI_COOKIE, STRING] - -- Cookies Information local i,j,p,n: INTEGER l_cookies: like internal_cookies @@ -249,7 +538,7 @@ feature -- Cookies do l_cookies := internal_cookies if l_cookies = Void then - if attached environment_variable ({EWSGI_ENVIRONMENT_NAMES}.http_cookie) as s then + if attached meta_variable ({WGI_META_NAMES}.http_cookie) as s then create l_cookies.make (5) from n := s.count @@ -272,7 +561,7 @@ feature -- Cookies v := s.substring (i + 1, j - 1) p := j + 1 end - l_cookies.put (create {EWSGI_COOKIE}.make (k,v), k) + l_cookies.force (v, k) end end else @@ -283,72 +572,78 @@ feature -- Cookies Result := l_cookies end + cookie (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + -- Field for name `a_name'. + do + Result := cookies.item (a_name) + end + feature -- Access: global variable - variables: HASH_TABLE [STRING_32, STRING_32] + parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] -- Table containing all the various variables -- Warning: this is computed each time, if you change the content of other containers -- this won't update this Result's content, unless you query it again local - vars: HASH_TABLE [STRING_GENERAL, STRING_GENERAL] + vars: HASH_TABLE [READABLE_STRING_GENERAL, READABLE_STRING_GENERAL] do create Result.make (100) - vars := environment.table + vars := meta_variables from vars.start until vars.after loop - Result.put (vars.item_for_iteration, vars.key_for_iteration) + Result.force (vars.item_for_iteration.as_string_32, vars.key_for_iteration) vars.forth end - vars := parameters.table + vars := query_parameters from vars.start until vars.after loop - Result.put (vars.item_for_iteration, vars.key_for_iteration) + Result.force (vars.item_for_iteration.as_string_32, vars.key_for_iteration) vars.forth end - vars := form_fields.table + vars := form_data_parameters from vars.start until vars.after loop - Result.put (vars.item_for_iteration, vars.key_for_iteration) + Result.force (vars.item_for_iteration.as_string_32, vars.key_for_iteration) vars.forth end - vars := cookies_variables + vars := cookies from vars.start until vars.after loop - Result.put (vars.item_for_iteration, vars.key_for_iteration) + Result.force (vars.item_for_iteration.as_string_32, vars.key_for_iteration) vars.forth end end - variable (a_name: STRING_8): detachable STRING_32 + parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- Variable named `a_name' from any of the variables container -- and following a specific order -- execution, environment, get, post, cookies local - s: detachable STRING_GENERAL + s: detachable READABLE_STRING_GENERAL do - s := environment_variable (a_name) + s := meta_variable (a_name) if s = Void then - s := parameter (a_name) + s := query_parameter (a_name) if s = Void then - s := form_field (a_name) + s := form_data_parameter (a_name) if s = Void then - s := cookies_variable (a_name) + s := cookie (a_name) end end end @@ -357,19 +652,6 @@ feature -- Access: global variable end end -feature -- Access extra information - - request_time: detachable DATE_TIME - -- Request time (UTC) - do - if - attached environment.variable ({EWSGI_ENVIRONMENT_NAMES}.request_time) as t and then - t.is_integer_64 - then - Result := date_time_utilities.unix_time_stamp_to_date_time (t.to_integer_64) - end - end - feature -- Uploaded File Handling is_uploaded_file (a_filename: STRING): BOOLEAN @@ -398,7 +680,7 @@ feature -- URL Utility -- Absolute Url for the script if any, extended by `a_path' do Result := script_url (a_path) - if attached environment.http_host as h then + if attached http_host as h then Result.prepend (h) else --| Issue ?? @@ -410,14 +692,12 @@ feature -- URL Utility local l_base_url: like internal_url_base i,m,n: INTEGER - l_rq_uri: like environment.request_uri - env: like environment + l_rq_uri: like request_uri do l_base_url := internal_url_base if l_base_url = Void then - env := environment - if attached env.script_name as l_script_name then - l_rq_uri := env.request_uri + if attached script_name as l_script_name then + l_rq_uri := request_uri if l_rq_uri.starts_with (l_script_name) then l_base_url := l_script_name else @@ -466,32 +746,9 @@ feature -- Element change error_handler := ehdl end - update_path_info (env: EWSGI_ENVIRONMENT) - -- Fix and update PATH_INFO value if needed - local - l_path_info: STRING - do - l_path_info := env.path_info - --| Warning - --| on IIS: we might have PATH_INFO = /sample.exe/foo/bar - --| on apache: PATH_INFO = /foo/bar - --| So, we might need to check with SCRIPT_NAME and remove it on IIS - --| store original PATH_INFO in ORIG_PATH_INFO - if l_path_info.is_empty then - env.unset_orig_path_info - else - env.set_orig_path_info (l_path_info) - if attached env.script_name as l_script_name then - if l_path_info.starts_with (l_script_name) then - env.path_info := l_path_info.substring (l_script_name.count + 1 , l_path_info.count) - end - end - end - end - feature {NONE} -- Temporary File handling - delete_uploaded_file (uf: EWSGI_UPLOADED_FILE_DATA) + delete_uploaded_file (uf: WGI_UPLOADED_FILE_DATA) -- Delete file `a_filename' require uf_valid: uf /= Void @@ -514,7 +771,7 @@ feature {NONE} -- Temporary File handling end end - save_uploaded_file (a_content: STRING; a_up_fn_info: EWSGI_UPLOADED_FILE_DATA) + save_uploaded_file (a_content: STRING; a_up_fn_info: WGI_UPLOADED_FILE_DATA) -- Save uploaded file content to `a_filename' local bn: STRING @@ -605,7 +862,7 @@ feature {NONE} -- Temporary File handling feature {NONE} -- Implementation: Form analyzer - analyze_multipart_form (t: STRING; s: STRING; vars: like form_fields) + analyze_multipart_form (t: STRING; s: STRING; vars: like form_data_parameters) -- Analyze multipart form content --| FIXME[2011-06-21]: integrate eMIME parser library require @@ -671,7 +928,7 @@ feature {NONE} -- Implementation: Form analyzer end end - analyze_multipart_form_input (s: STRING; vars_post: like form_fields) + analyze_multipart_form_input (s: STRING; vars_post: like form_data_parameters) -- Analyze multipart entry require s_not_empty: s /= Void and then not s.is_empty @@ -681,7 +938,7 @@ feature {NONE} -- Implementation: Form analyzer l_header: detachable STRING l_content: detachable STRING l_line: detachable STRING - l_up_file_info: EWSGI_UPLOADED_FILE_DATA + l_up_file_info: WGI_UPLOADED_FILE_DATA do from p := 1 @@ -778,7 +1035,7 @@ feature {NONE} -- Implementation: Form analyzer save_uploaded_file (l_content, l_up_file_info) uploaded_files.force (l_up_file_info, l_name) else - vars_post.add_variable (l_content, l_name) + vars_post.force (l_content, l_name) end else error_handler.add_custom_error (0, "unamed multipart entry", Void) @@ -818,10 +1075,10 @@ feature {NONE} -- Internal value end end - internal_parameters: detachable like parameters - -- cached value for `parameters' + internal_query_parameters: detachable like query_parameters + -- cached value for `query_parameters' - internal_form_fields: detachable like form_fields + internal_form_data_parameters: detachable like form_data_parameters -- cached value for `form_fields' internal_cookies: detachable like cookies @@ -846,7 +1103,7 @@ feature {NONE} -- Implementation report_bad_request_error (a_message: detachable STRING) -- Report error local - e: GW_ERROR + e: EWF_ERROR do create e.make ({HTTP_STATUS_CODE}.bad_request) if a_message /= Void then @@ -856,39 +1113,50 @@ feature {NONE} -- Implementation end extract_variables - -- Extract relevant environment variables + -- Extract relevant meta parameters local - s: detachable STRING + s: detachable READABLE_STRING_32 do - s := environment.request_uri + s := request_uri if s.is_empty then report_bad_request_error ("Missing URI") end if not has_error then - s := environment.request_method + s := request_method if s.is_empty then report_bad_request_error ("Missing request method") end end if not has_error then - s := environment.http_host + s := http_host if s = Void or else s.is_empty then report_bad_request_error ("Missing host header") end end if not has_error then - update_path_info (environment) + update_path_info end end feature {NONE} -- Implementation: utilities + empty_string: READABLE_STRING_32 + -- Reusable empty string + + url_encoder: URL_ENCODER + once + create Result + end + date_time_utilities: HTTP_DATE_TIME_UTILITIES -- Utilities classes related to date and time. once create Result end +invariant + empty_string_unchanged: empty_string.is_empty + note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/src/response/ewsgi_response_buffer.e b/library/server/ewsgi/src/response/wgi_response_stream_buffer.e similarity index 78% rename from library/server/ewsgi/src/response/ewsgi_response_buffer.e rename to library/server/ewsgi/src/response/wgi_response_stream_buffer.e index 84a428d3..b8dcd245 100644 --- a/library/server/ewsgi/src/response/ewsgi_response_buffer.e +++ b/library/server/ewsgi/src/response/wgi_response_stream_buffer.e @@ -8,9 +8,12 @@ note revision: "$Revision$" class - EWSGI_RESPONSE_BUFFER + WGI_RESPONSE_STREAM_BUFFER -create {EWSGI_APPLICATION} +inherit + WGI_RESPONSE_BUFFER + +create make feature {NONE} -- Initialization @@ -20,17 +23,13 @@ feature {NONE} -- Initialization output := a_output end -feature {EWSGI_APPLICATION} -- Commit +feature {WGI_APPLICATION} -- Commit commit -- Commit the current response do output.flush message_committed := True - ensure - status_is_set: status_is_set - header_committed: header_committed - message_committed: message_committed end feature -- Status report @@ -67,61 +66,26 @@ feature -- Status setting set_status_code (a_code: INTEGER) -- Set response status code -- Should be done before sending any data back to the client - require - status_not_set: not status_is_set - header_not_committed: not header_committed do status_code := a_code output.put_status_line (a_code) - ensure - status_code_set: status_code = a_code - status_set: status_is_set end status_code: INTEGER -- Response status -feature -- Output operation - - flush - do - output.flush - end - - write_string (s: STRING) - -- Send the string `s' - require - message_writable: message_writable - do - write (s) - end - - write_substring (s: STRING; start_index, end_index: INTEGER) - -- Send the substring `start_index:end_index]' - --| Could be optimized according to the target output - require - message_writable: message_writable - do - output.put_substring (s, start_index, end_index) - end - - write_file_content (fn: STRING) - -- Send the content of file `fn' - require - message_writable: message_writable - do - output.put_file_content (fn) - end - feature -- Header output operation + write_headers_string (a_headers: STRING) + do + write (a_headers) + header_committed := True + end + write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: STRING; value: STRING]]) -- Send headers with status `a_status', and headers from `a_headers' - require - status_not_set: not status_is_set - header_not_committed: not header_committed local - h: GW_HEADER + h: EWF_HEADER i,n: INTEGER do set_status_code (a_status_code) @@ -138,16 +102,38 @@ feature -- Header output operation i := i + 1 end end - write (h.string) - header_committed := True - ensure - status_set: status_is_set - header_committed: header_committed + write_headers_string (h.string) + end + +feature -- Output operation + + write_string (s: STRING) + -- Send the string `s' + do + write (s) + end + + write_substring (s: STRING; start_index, end_index: INTEGER) + -- Send the substring `start_index:end_index]' + --| Could be optimized according to the target output + do + output.put_substring (s, start_index, end_index) + end + + write_file_content (fn: STRING) + -- Send the content of file `fn' + do + output.put_file_content (fn) + end + + flush + do + output.flush end feature {NONE} -- Implementation: Access - output: EWSGI_OUTPUT_STREAM + output: WGI_OUTPUT_STREAM -- Server output channel ;note diff --git a/library/server/ewsgi/src/stream/ewsgi_input_stream.e b/library/server/ewsgi/src/stream/wgi_input_stream.e similarity index 97% rename from library/server/ewsgi/src/stream/ewsgi_input_stream.e rename to library/server/ewsgi/src/stream/wgi_input_stream.e index 7affe82f..bde896d6 100644 --- a/library/server/ewsgi/src/stream/ewsgi_input_stream.e +++ b/library/server/ewsgi/src/stream/wgi_input_stream.e @@ -9,7 +9,7 @@ note revision: "$Revision$" deferred class - EWSGI_INPUT_STREAM + WGI_INPUT_STREAM feature -- Access diff --git a/library/server/ewsgi/src/stream/ewsgi_output_stream.e b/library/server/ewsgi/src/stream/wgi_output_stream.e similarity index 98% rename from library/server/ewsgi/src/stream/ewsgi_output_stream.e rename to library/server/ewsgi/src/stream/wgi_output_stream.e index ac2127ff..fe1b677d 100644 --- a/library/server/ewsgi/src/stream/ewsgi_output_stream.e +++ b/library/server/ewsgi/src/stream/wgi_output_stream.e @@ -9,7 +9,7 @@ note revision: "$Revision$" deferred class - EWSGI_OUTPUT_STREAM + WGI_OUTPUT_STREAM feature -- Core operation diff --git a/library/server/ewsgi/src/support/gw_error.e b/library/server/ewsgi/src/support/ewf_error.e similarity index 94% rename from library/server/ewsgi/src/support/gw_error.e rename to library/server/ewsgi/src/support/ewf_error.e index 61823e9e..5884d12e 100644 --- a/library/server/ewsgi/src/support/gw_error.e +++ b/library/server/ewsgi/src/support/ewf_error.e @@ -1,12 +1,12 @@ note - description: "Summary description for {GW_ERROR}." + description: "Summary description for {EWF_ERROR}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - GW_ERROR + EWF_ERROR inherit ERROR diff --git a/library/server/ewsgi/src/support/gw_header.e b/library/server/ewsgi/src/support/ewf_header.e similarity index 99% rename from library/server/ewsgi/src/support/gw_header.e rename to library/server/ewsgi/src/support/ewf_header.e index 223367de..7bacd217 100644 --- a/library/server/ewsgi/src/support/gw_header.e +++ b/library/server/ewsgi/src/support/ewf_header.e @@ -1,6 +1,6 @@ note description: "[ - Summary description for {GW_HEADER}. + Summary description for {EWF_HEADER}. Note the return status code is not part of the HTTP header ]" @@ -10,7 +10,7 @@ note revision: "$Revision$" class - GW_HEADER + EWF_HEADER inherit ANY diff --git a/library/server/ewsgi/tests/ewsgi-full-safe.ecf b/library/server/ewsgi/tests/ewsgi-full-safe.ecf index 9acab6e2..bdb8b5f4 100644 --- a/library/server/ewsgi/tests/ewsgi-full-safe.ecf +++ b/library/server/ewsgi/tests/ewsgi-full-safe.ecf @@ -20,5 +20,8 @@ + + + diff --git a/library/server/ewsgi/tests/ewsgi-full.ecf b/library/server/ewsgi/tests/ewsgi-full.ecf index 0d27bb90..64e31420 100644 --- a/library/server/ewsgi/tests/ewsgi-full.ecf +++ b/library/server/ewsgi/tests/ewsgi-full.ecf @@ -10,9 +10,9 @@ + - @@ -20,5 +20,7 @@ + + diff --git a/library/server/request/router/src/application/routed_application.e b/library/server/request/router/src/application/routed_application.e index ffba0738..c22e6080 100644 --- a/library/server/request/router/src/application/routed_application.e +++ b/library/server/request/router/src/application/routed_application.e @@ -35,7 +35,7 @@ feature -- Setup feature -- Execution - execute (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) do if attached router.dispatch (req, res) as r then --| done @@ -44,7 +44,7 @@ feature -- Execution end end - execute_default (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) deferred end diff --git a/library/server/request/router/src/context/request_handler_context.e b/library/server/request/router/src/context/request_handler_context.e index ca92756f..9fa5f0bc 100644 --- a/library/server/request/router/src/context/request_handler_context.e +++ b/library/server/request/router/src/context/request_handler_context.e @@ -17,43 +17,42 @@ inherit feature -- Access - request: EWSGI_REQUEST + request: WGI_REQUEST -- Associated request - path: STRING - -- ??? + path: READABLE_STRING_GENERAL + -- Associated path - request_content_type (content_type_supported: detachable ARRAY [STRING]): detachable STRING + request_content_type (content_type_supported: detachable ARRAY [STRING]): detachable READABLE_STRING_8 local - s: detachable STRING + s: detachable READABLE_STRING_32 i,n: INTEGER do - Result := request.environment.content_type - if Result = Void then - s := request.environment.http_accept - if s /= Void then - if attached accepted_content_types (request) as l_accept_lst then - from - l_accept_lst.start - until - l_accept_lst.after or Result /= Void - loop - s := l_accept_lst.item - if content_type_supported /= Void then - from - i := content_type_supported.lower - n := content_type_supported.upper - until - i > n or Result /= Void - loop - if content_type_supported[i].same_string (s) then - Result := s - end - i := i + 1 + s := request.content_type + if s /= Void then + Result := s + else + if attached accepted_content_types (request) as l_accept_lst then + from + l_accept_lst.start + until + l_accept_lst.after or Result /= Void + loop + s := l_accept_lst.item + if content_type_supported /= Void then + from + i := content_type_supported.lower + n := content_type_supported.upper + until + i > n or Result /= Void + loop + if content_type_supported[i].same_string (s) then + Result := s end + i := i + 1 end - l_accept_lst.forth end + l_accept_lst.forth end end end @@ -61,18 +60,18 @@ feature -- Access feature -- Query - path_parameter (a_name: STRING): detachable STRING_32 + path_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- Parameter value for path variable `a_name' deferred end - query_parameter (a_name: STRING): detachable STRING_32 + query_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- Parameter value for query variable `a_name' --| i.e after the ? character deferred end - parameter (a_name: STRING): detachable STRING_32 + parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- Any parameter value for variable `a_name' -- URI template parameter and query parameters do diff --git a/library/server/request/router/src/context/request_uri_handler_context.e b/library/server/request/router/src/context/request_uri_handler_context.e index 1cbecbce..c6884918 100644 --- a/library/server/request/router/src/context/request_uri_handler_context.e +++ b/library/server/request/router/src/context/request_uri_handler_context.e @@ -15,7 +15,7 @@ create feature {NONE} -- Initialization - make (req: EWSGI_REQUEST; p: like path) + make (req: WGI_REQUEST; p: like path) do request := req path := p @@ -23,11 +23,11 @@ feature {NONE} -- Initialization feature -- Query - path_parameter (a_name: STRING): detachable STRING_32 + path_parameter (a_name: READABLE_STRING_GENERAL): detachable STRING_32 do end - query_parameter (a_name: STRING): detachable STRING_32 + query_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 do Result := request.parameter (a_name) end diff --git a/library/server/request/router/src/context/request_uri_template_handler_context.e b/library/server/request/router/src/context/request_uri_template_handler_context.e index 678e35b8..1d8aa5c8 100644 --- a/library/server/request/router/src/context/request_uri_template_handler_context.e +++ b/library/server/request/router/src/context/request_uri_template_handler_context.e @@ -15,7 +15,7 @@ create feature {NONE} -- Initialization - make (req: EWSGI_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT; p: like path) + make (req: WGI_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT; p: like path) do request := req uri_template := tpl @@ -31,12 +31,12 @@ feature -- Access feature -- Query - path_parameter (a_name: STRING): detachable STRING_32 + path_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 do Result := uri_template_match.url_decoded_path_variable (a_name) end - query_parameter (a_name: STRING): detachable STRING_32 + query_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 do Result := uri_template_match.url_decoded_query_variable (a_name) if Result = Void then diff --git a/library/server/request/router/src/handler/request_agent_handler.e b/library/server/request/router/src/handler/request_agent_handler.e index bcf9e475..545df575 100644 --- a/library/server/request/router/src/handler/request_agent_handler.e +++ b/library/server/request/router/src/handler/request_agent_handler.e @@ -23,11 +23,11 @@ feature -- Initialization feature -- Access - action: PROCEDURE [ANY, TUPLE [ctx: REQUEST_HANDLER_CONTEXT; req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER]] + action: PROCEDURE [ANY, TUPLE [ctx: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]] feature -- Execution - execute_application (ctx: REQUEST_HANDLER_CONTEXT; req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute_application (ctx: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) do action.call ([ctx, req, res]) end diff --git a/library/server/request/router/src/handler/request_handler.e b/library/server/request/router/src/handler/request_handler.e index 7a72c8c5..7c4cd294 100644 --- a/library/server/request/router/src/handler/request_handler.e +++ b/library/server/request/router/src/handler/request_handler.e @@ -21,15 +21,15 @@ feature -- Access feature -- Status report - is_valid_context (req: EWSGI_REQUEST): BOOLEAN + is_valid_context (req: WGI_REQUEST): BOOLEAN -- Is `req' valid context for current handler? do - Result := request_method_name_supported (req.environment.request_method) + Result := request_method_name_supported (req.request_method) end feature -- Execution - execute (a_hdl_context: REQUEST_HANDLER_CONTEXT; req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute (a_hdl_context: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Execute request handler require is_valid_context: is_valid_context (req) @@ -37,7 +37,7 @@ feature -- Execution rescued: BOOLEAN do if not rescued then - if request_method_name_supported (req.environment.request_method) then + if request_method_name_supported (req.request_method) then pre_execute (req) execute_application (a_hdl_context, req, res) post_execute (req, res) @@ -52,7 +52,7 @@ feature -- Execution retry end - execute_method_not_allowed (a_hdl_context: REQUEST_HANDLER_CONTEXT; req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute_method_not_allowed (a_hdl_context: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) local s: STRING lst: LIST [STRING] @@ -75,24 +75,24 @@ feature -- Execution res.write_header ({HTTP_STATUS_CODE}.method_not_allowed, <<["Allow", s]>>) end - execute_application (a_hdl_context: REQUEST_HANDLER_CONTEXT; req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + execute_application (a_hdl_context: REQUEST_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Execute request handler deferred end - pre_execute (req: EWSGI_REQUEST) + pre_execute (req: WGI_REQUEST) -- Operation processed before `execute' do --| To be redefined if needed end - post_execute (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + post_execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Operation processed after `execute' do --| To be redefined if needed end - rescue_execute (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER) + rescue_execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) -- Operation processed after a rescue do --| To be redefined if needed @@ -101,7 +101,7 @@ feature -- Execution feature -- Execution: report --- execution_information (req: EWSGI_REQUEST): detachable REQUEST_HANDLER_CONTEXT +-- execution_information (req: WGI_REQUEST): detachable REQUEST_HANDLER_CONTEXT -- -- Execution information related to the request -- do -- if attached path_information (req, req.environment.path_info) as info then @@ -109,7 +109,7 @@ feature -- Execution: report -- end -- end --- path_information (req: EWSGI_REQUEST; a_rq_path: STRING): detachable TUPLE [format: detachable STRING; arguments: detachable STRING] +-- path_information (req: WGI_REQUEST; a_rq_path: STRING): detachable TUPLE [format: detachable STRING; arguments: detachable STRING] -- -- Information related to `a_path' -- local -- l_rq_path: STRING @@ -156,7 +156,7 @@ feature -- Execution: report -- end -- end - url (req: EWSGI_REQUEST; args: detachable STRING; abs: BOOLEAN): STRING + url (req: WGI_REQUEST; args: detachable STRING; abs: BOOLEAN): STRING -- Associated url based on `path' and `args' -- if `abs' then return absolute url local @@ -165,12 +165,12 @@ feature -- Execution: report s := args if s /= Void and then s.count > 0 then if s[1] /= '/' then - s := req.environment.request_uri + "/" + s + s := req.request_uri + "/" + s else - s := req.environment.request_uri + s + s := req.request_uri + s end else - s := req.environment.request_uri + s := req.request_uri end if abs then Result := req.absolute_script_url (s) diff --git a/library/server/request/router/src/router/request_router.e b/library/server/request/router/src/router/request_router.e index acb22f4c..b5f0e414 100644 --- a/library/server/request/router/src/router/request_router.e +++ b/library/server/request/router/src/router/request_router.e @@ -7,6 +7,9 @@ note deferred class REQUEST_ROUTER +inherit + ITERABLE [TUPLE [handler: REQUEST_HANDLER; resource: READABLE_STRING_8; request_methods: detachable ARRAY [READABLE_STRING_8]]] + feature -- Registration map_default (r: like default_handler) @@ -17,22 +20,33 @@ feature -- Registration default_handler := r end - map (a_id: STRING; h: REQUEST_HANDLER) + map (a_id: READABLE_STRING_8; h: REQUEST_HANDLER) -- Map handler `h' with `a_id' + do + map_with_request_methods (a_id, h, Void) + end + + map_with_request_methods (a_id: READABLE_STRING_8; h: REQUEST_HANDLER; rqst_methods: detachable ARRAY [READABLE_STRING_8]) + -- Map handler `h' with `a_id' and `rqst_methods' deferred end - map_agent (a_id: STRING; a_action: like {REQUEST_AGENT_HANDLER}.action) + map_agent (a_id: READABLE_STRING_8; a_action: like {REQUEST_AGENT_HANDLER}.action) + do + map_agent_with_request_methods (a_id, a_action, Void) + end + + map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: like {REQUEST_AGENT_HANDLER}.action; rqst_methods: detachable ARRAY [READABLE_STRING_8]) local h: REQUEST_AGENT_HANDLER do create h.make (a_action) - map (a_id, h) + map_with_request_methods (a_id, h, rqst_methods) end feature -- Execution - dispatch (req: EWSGI_REQUEST; res: EWSGI_RESPONSE_BUFFER): detachable REQUEST_HANDLER + dispatch (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER): detachable REQUEST_HANDLER -- Dispatch `req, res' to the associated handler -- And return this handler -- If Result is Void, this means no handler was found. @@ -60,13 +74,55 @@ feature -- Execution feature {NONE} -- Access: Implementation - handler (req: EWSGI_REQUEST): detachable TUPLE [handler: REQUEST_HANDLER; context: REQUEST_HANDLER_CONTEXT] + handler (req: WGI_REQUEST): detachable TUPLE [handler: REQUEST_HANDLER; context: REQUEST_HANDLER_CONTEXT] -- Handler whose map matched with `req' require - req_valid: req /= Void and then req.environment.path_info /= Void + req_valid: req /= Void and then req.path_info /= Void deferred ensure - req_path_info_unchanged: req.environment.path_info.same_string (old req.environment.path_info) + req_path_info_unchanged: req.path_info.same_string (old req.path_info) + end + + is_matching_request_methods (a_request_method: READABLE_STRING_GENERAL; rqst_methods: like formatted_request_methods): BOOLEAN + -- `a_request_method' is matching `rqst_methods' contents + local + i,n: INTEGER + m: READABLE_STRING_GENERAL + do + if rqst_methods /= Void and then not rqst_methods.is_empty then + m := a_request_method + from + i := rqst_methods.lower + n := rqst_methods.upper + until + i > n or Result + loop + Result := m.same_string (rqst_methods[i]) + i := i + 1 + end + else + Result := True + end + end + + formatted_request_methods (rqst_methods: like formatted_request_methods): detachable ARRAY [READABLE_STRING_8] + -- Formatted request methods values + local + i,l,u: INTEGER + do + if rqst_methods /= Void and then not rqst_methods.is_empty then + l := rqst_methods.lower + u := rqst_methods.upper + create Result.make_filled (rqst_methods[l], l, u) + from + i := l + 1 + until + i > u + loop + Result[i] := rqst_methods[i].as_string_8.as_upper + i := i + 1 + end + end end feature {NONE} -- Implementation diff --git a/library/server/request/router/src/router/request_uri_router.e b/library/server/request/router/src/router/request_uri_router.e index b4080739..303a1c3c 100644 --- a/library/server/request/router/src/router/request_uri_router.e +++ b/library/server/request/router/src/router/request_uri_router.e @@ -10,11 +10,6 @@ class inherit REQUEST_ROUTER - ITERABLE [REQUEST_HANDLER] - redefine - new_cursor - end - create make @@ -28,21 +23,21 @@ feature -- Initialization feature -- Registration - map (p: STRING; h: REQUEST_HANDLER) + map_with_request_methods (p: READABLE_STRING_8; h: REQUEST_HANDLER; rqst_methods: detachable ARRAY [READABLE_STRING_8]) do - handlers.force (h, p) + handlers.force ([h, p, formatted_request_methods (rqst_methods)]) end feature {NONE} -- Access: Implementation - handler (req: EWSGI_REQUEST): detachable TUPLE [handler: REQUEST_HANDLER; context: REQUEST_HANDLER_CONTEXT] + handler (req: WGI_REQUEST): detachable TUPLE [handler: REQUEST_HANDLER; context: REQUEST_HANDLER_CONTEXT] local h: detachable REQUEST_HANDLER ctx: detachable REQUEST_HANDLER_CONTEXT do - h := handler_by_path (req.environment.path_info) + h := handler_by_path (req.path_info, req.request_method) if h = Void then - if attached smart_handler_by_path (req.environment.path_info) as info then + if attached smart_handler_by_path (req.path_info, req.request_method) as info then h := info.handler ctx := handler_context (info.path, req) end @@ -59,30 +54,45 @@ feature {NONE} -- Access: Implementation end end - smart_handler (req: EWSGI_REQUEST): detachable TUPLE [path: STRING; handler: REQUEST_HANDLER] + smart_handler (req: WGI_REQUEST): detachable TUPLE [path: READABLE_STRING_8; handler: REQUEST_HANDLER] require - req_valid: req /= Void and then req.environment.path_info /= Void + req_valid: req /= Void and then req.path_info /= Void do - Result := smart_handler_by_path (req.environment.path_info) + Result := smart_handler_by_path (req.path_info, req.request_method) ensure - req_path_info_unchanged: req.environment.path_info.same_string (old req.environment.path_info) + req_path_info_unchanged: req.path_info.same_string (old req.path_info) end - handler_by_path (a_path: STRING): detachable REQUEST_HANDLER + handler_by_path (a_path: READABLE_STRING_GENERAL; rqst_method: READABLE_STRING_GENERAL): detachable REQUEST_HANDLER require a_path_valid: a_path /= Void + local + l_handlers: like handlers + l_item: like handlers.item do - Result := handlers.item (context_path (a_path)) + l_handlers := handlers + from + l_handlers.start + until + l_handlers.after or Result /= Void + loop + l_item := l_handlers.item + if is_matching_request_methods (rqst_method, l_item.request_methods) and a_path.same_string (l_item.resource) then + Result := l_item.handler + end + l_handlers.forth + end +-- Result := handlers.item (context_path (a_path)) ensure a_path_unchanged: a_path.same_string (old a_path) end - smart_handler_by_path (a_path: STRING): detachable TUPLE [path: STRING; handler: REQUEST_HANDLER] + smart_handler_by_path (a_path: READABLE_STRING_8; rqst_method: READABLE_STRING_GENERAL): detachable TUPLE [path: READABLE_STRING_8; handler: REQUEST_HANDLER] require a_path_valid: a_path /= Void local p: INTEGER - l_context_path, l_path: STRING + l_context_path, l_path: READABLE_STRING_8 h: detachable REQUEST_HANDLER do l_context_path := context_path (a_path) @@ -92,7 +102,7 @@ feature {NONE} -- Access: Implementation p <= 1 or Result /= Void loop l_path := l_context_path.substring (1, p - 1) - h := handler_by_path (l_path) + h := handler_by_path (l_path, rqst_method) if h /= Void then Result := [l_path, h] else @@ -107,45 +117,44 @@ feature {NONE} -- Access: Implementation feature -- Context factory - handler_context (p: detachable STRING; req: EWSGI_REQUEST): REQUEST_URI_HANDLER_CONTEXT + handler_context (p: detachable STRING; req: WGI_REQUEST): REQUEST_URI_HANDLER_CONTEXT do if p /= Void then create Result.make (req, p) else - create Result.make (req, req.environment.path_info) + create Result.make (req, req.path_info) end end feature -- Access - new_cursor: HASH_TABLE_ITERATION_CURSOR [REQUEST_HANDLER, STRING] + new_cursor: ITERATION_CURSOR [TUPLE [handler: REQUEST_HANDLER; resource: READABLE_STRING_8; request_methods: detachable ARRAY [READABLE_STRING_8]]] -- Fresh cursor associated with current structure do Result := handlers.new_cursor end - item (a_path: STRING): detachable REQUEST_HANDLER - do - Result := handler_by_path (a_path) - end - feature {NONE} -- Implementation - handlers: HASH_TABLE [REQUEST_HANDLER, STRING] - -- Handlers + handlers: ARRAYED_LIST [TUPLE [handler: REQUEST_HANDLER; resource: READABLE_STRING_8; request_methods: detachable ARRAY [READABLE_STRING_8]]] + -- Handlers indexed by the template expression + -- see `templates' - context_path (a_path: STRING): STRING + context_path (a_path: READABLE_STRING_8): READABLE_STRING_8 -- Prepared path from context which match requirement -- i.e: not empty, starting with '/' local p: INTEGER + s: STRING_8 do Result := a_path if Result.is_empty then Result := "/" else if Result[1] /= '/' then - Result := "/" + Result + create s.make_from_string (Result) + s.prepend_character ('/') + Result := s end p := Result.index_of ('.', 1) if p > 0 then diff --git a/library/server/request/router/src/router/request_uri_template_router.e b/library/server/request/router/src/router/request_uri_template_router.e index d5a43d33..d4554320 100644 --- a/library/server/request/router/src/router/request_uri_template_router.e +++ b/library/server/request/router/src/router/request_uri_template_router.e @@ -10,11 +10,6 @@ class inherit REQUEST_ROUTER - ITERABLE [REQUEST_HANDLER] - redefine - new_cursor - end - create make @@ -31,40 +26,51 @@ feature -- Registration map_with_uri_template (uri: URI_TEMPLATE; h: REQUEST_HANDLER) do - handlers.force (h, uri.template) + map_with_uri_template_and_request_methods (uri, h, Void) + end + + map_with_uri_template_and_request_methods (uri: URI_TEMPLATE; h: REQUEST_HANDLER; rqst_methods: detachable ARRAY [READABLE_STRING_8]) + do + handlers.force ([h, uri.template, formatted_request_methods (rqst_methods)]) templates.force (uri, uri.template) end - map (tpl: STRING; h: REQUEST_HANDLER) + map_with_request_methods (tpl: READABLE_STRING_8; h: REQUEST_HANDLER; rqst_methods: detachable ARRAY [READABLE_STRING_8]) local uri: URI_TEMPLATE do create uri.make (tpl) - map_with_uri_template (uri, h) + map_with_uri_template_and_request_methods (uri, h, rqst_methods) end feature {NONE} -- Access: Implementation - handler (req: EWSGI_REQUEST): detachable TUPLE [handler: REQUEST_HANDLER; context: REQUEST_HANDLER_CONTEXT] + handler (req: WGI_REQUEST): detachable TUPLE [handler: REQUEST_HANDLER; context: REQUEST_HANDLER_CONTEXT] local ctx: detachable REQUEST_URI_TEMPLATE_HANDLER_CONTEXT l_handlers: like handlers t: STRING p: STRING + l_req_method: READABLE_STRING_GENERAL do - p := req.environment.request_uri + p := req.request_uri from + l_req_method := req.request_method l_handlers := handlers l_handlers.start until l_handlers.after or Result /= Void loop - t := l_handlers.key_for_iteration - if attached templates.item (t) as tpl and then - attached tpl.match (p) as res - then - ctx := handler_context (p, req, tpl, res) - Result := [l_handlers.item_for_iteration, ctx] + if attached l_handlers.item as l_info then + if is_matching_request_methods (l_req_method, l_info.request_methods) then + t := l_info.resource + if attached templates.item (t) as tpl and then + attached tpl.match (p) as res + then + ctx := handler_context (p, req, tpl, res) + Result := [l_info.handler, ctx] + end + end end l_handlers.forth end @@ -72,35 +78,30 @@ feature {NONE} -- Access: Implementation feature -- Context factory - handler_context (p: detachable STRING; req: EWSGI_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT): REQUEST_URI_TEMPLATE_HANDLER_CONTEXT + handler_context (p: detachable STRING; req: WGI_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT): REQUEST_URI_TEMPLATE_HANDLER_CONTEXT do if p /= Void then create Result.make (req, tpl, tpl_res, p) else - create Result.make (req, tpl, tpl_res, req.environment.path_info) + create Result.make (req, tpl, tpl_res, req.path_info) end end -feature -- Access +feature -- Access: ITERABLE - new_cursor: HASH_TABLE_ITERATION_CURSOR [REQUEST_HANDLER, STRING] + new_cursor: ITERATION_CURSOR [TUPLE [handler: REQUEST_HANDLER; resource: READABLE_STRING_8; request_methods: detachable ARRAY [READABLE_STRING_8]]] -- Fresh cursor associated with current structure do Result := handlers.new_cursor end - item (a_path: STRING): detachable REQUEST_HANDLER - do - Result := handlers.item (a_path) - end - feature {NONE} -- Implementation - handlers: HASH_TABLE [REQUEST_HANDLER, STRING] + handlers: ARRAYED_LIST [TUPLE [handler: REQUEST_HANDLER; resource: READABLE_STRING_8; request_methods: detachable ARRAY [READABLE_STRING_8]]] -- Handlers indexed by the template expression -- see `templates' - templates: HASH_TABLE [URI_TEMPLATE, STRING] + templates: HASH_TABLE [URI_TEMPLATE, READABLE_STRING_8] -- URI Template indexed by the template expression context_path (a_path: STRING): STRING diff --git a/library/server/request/router/src/utility/request_format_utility.e b/library/server/request/router/src/utility/request_format_utility.e index 225d24f0..b5914a49 100644 --- a/library/server/request/router/src/utility/request_format_utility.e +++ b/library/server/request/router/src/utility/request_format_utility.e @@ -9,19 +9,20 @@ class feature -- Access - accepted_content_types (req: EWSGI_REQUEST): detachable ARRAYED_LIST [STRING] + accepted_content_types (req: WGI_REQUEST): detachable ARRAYED_LIST [READABLE_STRING_8] local - l_accept: detachable STRING - s,q: STRING + l_accept: detachable READABLE_STRING_32 + s: STRING_8 + q: READABLE_STRING_8 p: INTEGER - lst: LIST [STRING] - qs: QUICK_SORTER [STRING] + lst: LIST [READABLE_STRING_8] + qs: QUICK_SORTER [READABLE_STRING_8] do - l_accept := req.environment.http_accept + l_accept := req.http_accept --TEST l_accept := "text/html,application/xhtml+xml;q=0.6,application/xml;q=0.2,text/plain;q=0.5,*/*;q=0.8" if l_accept /= Void then - lst := l_accept.split (',') + lst := l_accept.as_string_8.split (',') create Result.make (lst.count) from lst.start @@ -40,7 +41,7 @@ feature -- Access lst.forth end - create qs.make (create {COMPARABLE_COMPARATOR [STRING]}) + create qs.make (create {COMPARABLE_COMPARATOR [READABLE_STRING_8]}) qs.reverse_sort (Result) from Result.start