diff --git a/examples/simple/application_execution.e b/examples/simple/application_execution.e index d823a16e..a27e79d2 100644 --- a/examples/simple/application_execution.e +++ b/examples/simple/application_execution.e @@ -30,8 +30,8 @@ feature -- Basic operations response.set_status_code ({HTTP_STATUS_CODE}.ok) response.header.put_content_type_text_html response.header.put_content_length (s.count) - if attached request.http_connection as l_connection and then l_connection.is_case_insensitive_equal_general ("keep-alive") then - response.header.put_header_key_value ("Connection", "keep-alive") + if request.is_keep_alive_http_connection then + response.header.put_connection_keep_alive end response.put_string (s) end diff --git a/examples/simple_file/service.ini b/examples/simple_file/service.ini new file mode 100644 index 00000000..a8c39747 --- /dev/null +++ b/examples/simple_file/service.ini @@ -0,0 +1,4 @@ +port=9090 +verbose=true +socket_recv_timeout=15 +keep_alive_timeout=30 diff --git a/examples/simple_file/service_file.e b/examples/simple_file/service_file.e index 44de0e62..edec85f8 100644 --- a/examples/simple_file/service_file.e +++ b/examples/simple_file/service_file.e @@ -21,6 +21,7 @@ feature {NONE} -- Initialization do Precursor set_service_option ("port", 9090) + import_service_options (create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI}.make_from_file ("service.ini")) end end diff --git a/examples/simple_ssl/application_execution.e b/examples/simple_ssl/application_execution.e index 2d6d0a75..7e2c3c6d 100644 --- a/examples/simple_ssl/application_execution.e +++ b/examples/simple_ssl/application_execution.e @@ -32,8 +32,8 @@ feature -- Basic operations response.set_status_code ({HTTP_STATUS_CODE}.ok) response.header.put_content_type_text_html response.header.put_content_length (s.count) - if attached request.http_connection as l_connection and then l_connection.is_case_insensitive_equal_general ("keep-alive") then - response.header.put_header_key_value ("Connection", "keep-alive") + if request.is_keep_alive_http_connection then + response.header.put_connection_keep_alive end response.put_string (s) end diff --git a/examples/websocket/application_execution.e b/examples/websocket/application_execution.e index fc920446..506bbedf 100644 --- a/examples/websocket/application_execution.e +++ b/examples/websocket/application_execution.e @@ -35,8 +35,8 @@ feature -- Basic operations response.set_status_code ({HTTP_STATUS_CODE}.ok) response.header.put_content_type_text_html response.header.put_content_length (s.count) - if attached request.http_connection as l_connection and then l_connection.is_case_insensitive_equal_general ("keep-alive") then - response.header.put_header_key_value ("Connection", "keep-alive") + if request.is_keep_alive_http_connection then + response.header.put_connection_keep_alive end response.put_string (s) end @@ -96,9 +96,10 @@ $(document).ready(function() { function connect(){ - var host = "##WSSCHEME##://127.0.0.1:##PORTNUMBER##"; + var host = "##WSSCHEME##://127.0.0.1:##PORTNUMBER##/app"; try{ + socket = new WebSocket(host); message('

Socket Status: '+socket.readyState); socket.onopen = function(){ diff --git a/library/network/protocol/http/src/http_header_modifier.e b/library/network/protocol/http/src/http_header_modifier.e index 3af4e45b..9c06a9f9 100644 --- a/library/network/protocol/http/src/http_header_modifier.e +++ b/library/network/protocol/http/src/http_header_modifier.e @@ -508,9 +508,16 @@ feature -- Others put_expires (a_seconds: INTEGER) -- Put "Expires" header to `a_seconds' seconds + -- and also "Cache-Control: max-age=.." . + -- To be supported by most browser. + local + dt: DATE_TIME do - put_expires_string (a_seconds.out) - end + create dt.make_now_utc + dt.second_add (a_seconds) + put_expires_date (dt) + put_cache_control ("max-age=" + a_seconds.out) + end put_expires_string (a_expires: STRING) -- Put "Expires" header with `a_expires' string value @@ -544,6 +551,26 @@ feature -- Others put_pragma ("no-cache") end +feature -- Connection + + put_connection (a_conn: READABLE_STRING_8) + -- Put "Connection" header with `a_conn' value. + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_connection, a_conn) + end + + put_connection_keep_alive + -- Put "Connection" header with "keep-alive". + do + put_connection ("keep-alive") + end + + put_connection_close + -- Put "Connection" header with "close". + do + put_connection ("close") + end + feature -- Redirection put_location (a_uri: READABLE_STRING_8) diff --git a/library/server/ewsgi/specification/response/wgi_filter_response.e b/library/server/ewsgi/specification/response/wgi_filter_response.e index f9b14d70..1cea7bed 100644 --- a/library/server/ewsgi/specification/response/wgi_filter_response.e +++ b/library/server/ewsgi/specification/response/wgi_filter_response.e @@ -131,6 +131,12 @@ feature -- Output operation wgi_response.put_substring (s, a_begin_index, a_end_index) end + put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER) + -- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'. + do + wgi_response.put_file_content (f, a_offset, a_count) + end + flush -- Flush if it makes sense do diff --git a/library/server/ewsgi/specification/response/wgi_response.e b/library/server/ewsgi/specification/response/wgi_response.e index 4a6041b9..df690dd2 100644 --- a/library/server/ewsgi/specification/response/wgi_response.e +++ b/library/server/ewsgi/specification/response/wgi_response.e @@ -142,6 +142,14 @@ feature -- Output operation deferred end + put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER) + -- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'. + require + message_writable: message_writable + not_too_big: a_offset + a_count <= f.count + deferred + end + flush -- Flush if it makes sense deferred diff --git a/library/server/ewsgi/specification/stream/wgi_output_stream.e b/library/server/ewsgi/specification/stream/wgi_output_stream.e index 8d02bdea..943259f3 100644 --- a/library/server/ewsgi/specification/stream/wgi_output_stream.e +++ b/library/server/ewsgi/specification/stream/wgi_output_stream.e @@ -37,6 +37,53 @@ feature -- Output end end + put_file_content (a_file: FILE; a_offset: INTEGER; a_byte_count: INTEGER) + -- Send `a_byte_count' bytes from the content of file `a_file' starting at offset `a_offset'. + --| Could be redefined for optimization. + require + a_file_closed_or_openread: a_file.exists and then (a_file.is_access_readable or a_file.is_closed) + is_open_write: is_open_write + a_file_not_void: a_file /= Void + local + l_close_needed: BOOLEAN + l_remain: INTEGER + l_done: BOOLEAN + s: STRING + do + if a_file.exists and then a_file.is_access_readable then + if a_file.is_open_read then + l_close_needed := False + else + l_close_needed := True + a_file.open_read + end + if a_offset > 0 then + a_file.move (a_offset) + end + from + l_remain := a_byte_count + l_done := False + until + a_file.exhausted or l_done + loop + a_file.read_stream (l_remain.min (4_096)) + s := a_file.last_string + if s.is_empty then + -- network error? + l_done := True + else + put_string (s) + l_remain := l_remain - s.count + check l_remain >= 0 end + l_done := l_remain = 0 + end + end + if l_close_needed then + a_file.close + end + end + end + put_character (c: CHARACTER_8) -- Write `c' to output stream. --| Could be redefined for optimization diff --git a/library/server/ewsgi/src/implementation/wgi_response_stream.e b/library/server/ewsgi/src/implementation/wgi_response_stream.e index 73edf89a..82bf3a6b 100644 --- a/library/server/ewsgi/src/implementation/wgi_response_stream.e +++ b/library/server/ewsgi/src/implementation/wgi_response_stream.e @@ -103,6 +103,12 @@ feature -- Output operation output.put_substring (s, start_index, end_index) end + put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER) + -- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'. + do + output.put_file_content (f, a_offset, a_count) + end + flush do output.flush diff --git a/library/server/httpd/httpd_request_handler_i.e b/library/server/httpd/httpd_request_handler_i.e index 6263cb5c..6ae119df 100644 --- a/library/server/httpd/httpd_request_handler_i.e +++ b/library/server/httpd/httpd_request_handler_i.e @@ -455,14 +455,11 @@ feature -- Parsing -- Except for HTTP/1.0, persistent connection is the default. is_persistent_connection_requested := True if is_http_version_1_0 then - is_persistent_connection_requested := attached request_header_map.item ("Connection") as l_connection and then - l_connection.is_case_insensitive_equal_general ("keep-alive") + is_persistent_connection_requested := has_keep_alive_http_connection_header (request_header_map) else -- By default HTTP:1/1 support persistent connection. - if attached request_header_map.item ("Connection") as l_connection then - if l_connection.is_case_insensitive_equal_general ("close") then - is_persistent_connection_requested := False - end + if has_close_http_connection_header (request_header_map) then + is_persistent_connection_requested := False else is_persistent_connection_requested := True end @@ -476,6 +473,46 @@ feature -- Parsing end end + has_keep_alive_http_connection_header (h_map: like request_header_map): BOOLEAN + -- Does Current request header map `h_map' have "keep-alive" connection header? + local + i: INTEGER + do + if attached h_map.item ("Connection") as l_connection then + -- Could be for instance "keep-alive, Upgrade" + i := l_connection.substring_index ("keep-alive", 1) + if i > 0 then + i := i + 9 -- "keep-alive" has 10 characters + check i <= l_connection.count end + if i = l_connection.count then + Result := True + else + Result := l_connection [i + 1] = ',' or l_connection [i + 1].is_space + end + end + end + end + + has_close_http_connection_header (h_map: like request_header_map): BOOLEAN + -- Does Current request header map `h_map' have "close" connection header? + local + i: INTEGER + do + if attached h_map.item ("Connection") as l_connection then + -- Could be for instance "close, ..." + i := l_connection.substring_index ("close", 1) + if i > 0 then + i := i + 4 -- "close" has 5 characters + check i <= l_connection.count end + if i = l_connection.count then + Result := True + else + Result := l_connection [i + 1] = ',' or l_connection [i + 1].is_space + end + end + end + end + analyze_request_line (line: STRING) -- Analyze `line' as a HTTP request line. -- note: may update `has_error'. diff --git a/library/server/wsf/router/filter/wsf_filter.e b/library/server/wsf/router/filter/wsf_filter.e index 9e4ea502..66922784 100644 --- a/library/server/wsf/router/filter/wsf_filter.e +++ b/library/server/wsf/router/filter/wsf_filter.e @@ -1,6 +1,5 @@ note description: "Objects than can pre-process incoming data and post-process outgoing data." - author: "Olivier Ligot" date: "$Date$" revision: "$Revision$" @@ -9,9 +8,23 @@ deferred class feature -- Access - next: detachable WSF_FILTER + next: detachable WSF_FILTER assign set_next -- Next filter + last: WSF_FILTER + -- Last filter in the chain following `next'. + do + from + Result := Current + until + not attached Result.next as l_next + loop + Result := l_next + end + ensure + is_closing: Result /= Void and then Result.next = Void + end + feature -- Element change set_next (a_next: like next) @@ -22,6 +35,24 @@ feature -- Element change next_set: next = a_next end + append (a_filter: attached like next) + -- Append `a_filter' to the `last' filter. + do + last.set_next (a_filter) + end + + insert_after (a_filter: attached like next) + -- Append `a_filter' to the `last' filter. + local + f: like next + do + f := next + set_next (a_filter) + if f /= Void then + a_filter.append (f) + end + end + feature -- Basic operations execute (req: WSF_REQUEST; res: WSF_RESPONSE) diff --git a/library/server/wsf/router/filter/wsf_filtered.e b/library/server/wsf/router/filter/wsf_filtered.e index 0ac3c60d..6d41a412 100644 --- a/library/server/wsf/router/filter/wsf_filtered.e +++ b/library/server/wsf/router/filter/wsf_filtered.e @@ -29,22 +29,19 @@ feature {NONE} -- Initialization deferred end + append_filter (a_filter: WSF_FILTER) + -- Append `a_filter' to the end of the `filter' chain. + do + filter.append (a_filter) + end + append_filters (a_filters: ITERABLE [WSF_FILTER]) -- Append collection `a_filters' of filters to the end of the `filter' chain. local f: like filter l_next_filter: detachable like filter do - from - f := filter - l_next_filter := f.next - until - l_next_filter = Void - loop - f := l_next_filter - l_next_filter := f.next - end - check f_attached_without_next: f /= Void and then f.next = Void end + f := filter.last across a_filters as ic loop @@ -59,5 +56,4 @@ feature -- Access filter: WSF_FILTER -- Filter - end diff --git a/library/server/wsf/router/wsf_file_system_handler.e b/library/server/wsf/router/wsf_file_system_handler.e index 9a17cb7c..9cd4f647 100644 --- a/library/server/wsf/router/wsf_file_system_handler.e +++ b/library/server/wsf/router/wsf_file_system_handler.e @@ -39,6 +39,7 @@ feature {NONE} -- Initialization make_with_path (d: like document_root) do + max_age := -1 if d.is_empty then document_root := execution_environment.current_working_path else @@ -87,6 +88,7 @@ feature -- Access document_root: PATH max_age: INTEGER + -- Max age, initialized at -1 by default. index_disabled: BOOLEAN -- Index disabled? @@ -367,15 +369,17 @@ feature -- Execution create fres.make_with_content_type (ct, f.path.name) fres.set_status_code ({HTTP_STATUS_CODE}.ok) - -- cache control + -- cache control create dt.make_now_utc - fres.header.put_cache_control ("private, max-age=" + max_age.out) fres.header.put_utc_date (dt) - if max_age > 0 then - dt := dt.twin - dt.second_add (max_age) + if max_age >= 0 then + fres.set_max_age (max_age) + if max_age > 0 then + dt := dt.twin + dt.second_add (max_age) + end + fres.set_expires_date (dt) end - fres.header.put_expires_date (dt) fres.set_answer_head_request_method (req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head)) res.send (fres) @@ -388,14 +392,15 @@ feature -- Execution do create dt.make_now_utc create h.make - h.put_cache_control ("private, max-age=" + max_age.out) h.put_utc_date (dt) - if max_age > 0 then - dt := dt.twin - dt.second_add (max_age) + if max_age >= 0 then + h.put_cache_control ("max-age=" + max_age.out) + if max_age > 0 then + dt := dt.twin + dt.second_add (max_age) + end + h.put_expires_date (dt) end - h.put_expires_date (dt) - if a_utc_date /= Void then h.put_last_modified (a_utc_date) end @@ -637,7 +642,7 @@ feature {NONE} -- implementation: date time end note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/implementation/wsf_wgi_delayed_header_response.e b/library/server/wsf/src/implementation/wsf_wgi_delayed_header_response.e index b5aeb6fc..e10f839b 100644 --- a/library/server/wsf/src/implementation/wsf_wgi_delayed_header_response.e +++ b/library/server/wsf/src/implementation/wsf_wgi_delayed_header_response.e @@ -13,6 +13,7 @@ inherit put_character, put_string, put_substring, + put_file_content, flush, message_writable, message_committed @@ -108,6 +109,13 @@ feature -- Output operation Precursor (s, a_begin_index, a_end_index) end + put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER) + -- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'. + do + process_header + Precursor (f, a_offset, a_count) + end + flush -- Flush if it makes sense do diff --git a/library/server/wsf/src/response/wsf_file_response.e b/library/server/wsf/src/response/wsf_file_response.e index 28b21ff2..6005d860 100644 --- a/library/server/wsf/src/response/wsf_file_response.e +++ b/library/server/wsf/src/response/wsf_file_response.e @@ -1,8 +1,7 @@ note - description : "Objects that ..." - author : "$Author$" - date : "$Date$" - revision : "$Revision$" + description: "Response to send a file back to the client" + date: "$Date$" + revision: "$Revision$" class WSF_FILE_RESPONSE @@ -105,22 +104,46 @@ feature {NONE} -- Initialization feature -- Element change - set_expires_in_seconds (sec: INTEGER) + set_max_age (sec: INTEGER) do - set_expires (sec.out) + header.put_cache_control ("max-age=" + sec.out) + end + + set_public_max_age (sec: INTEGER) + do + header.put_cache_control ("public, max-age=" + sec.out) + end + + set_private_max_age (sec: INTEGER) + do + header.put_cache_control ("private, max-age=" + sec.out) + end + + set_expires_in_seconds (sec: INTEGER) + -- Set Expires and Cache-control: max-age... to value related `sec' seconds. + do + header.put_expires (sec) end set_expires (s: STRING) + -- Set Expires header value to `s'. do header.put_expires_string (s) end + set_expires_date (dt: DATE_TIME) + -- Set Expires header value to date time `dt'. + do + header.put_expires_date (dt) + end + set_no_cache local h: like header do h := header h.put_expires (0) + h.put_cache_control ("max-age=0") h.put_cache_control ("no-cache, must-revalidate") h.put_pragma_no_cache end @@ -250,7 +273,7 @@ feature {NONE} -- Implementation: file system helper f: RAW_FILE do create f.make_with_path (file_path) - create Result.make_from_epoch (f.change_date) + create Result.make_from_epoch (f.date) end file_extension (fn: PATH): STRING_32 @@ -293,19 +316,11 @@ feature {NONE} -- Implementation: output create f.make_with_path (fn) check f.is_readable end - f.open_read - from - until - f.exhausted - loop - f.read_stream (4_096) - res.put_string (f.last_string) - end - f.close + res.put_file_content (f, 0, f.count) end note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index 10d8dfca..3df32b6c 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -1200,11 +1200,19 @@ feature -- HTTP_* http_connection: detachable READABLE_STRING_8 -- Contents of the Connection: header from the current wgi_request, if there is one. - -- Example: 'Keep-Alive'. + -- Example: 'keep-alive'. do Result := wgi_request.http_connection end + is_keep_alive_http_connection: BOOLEAN + -- Is a keep-alive connection? + do + if attached http_connection as conn then + Result := conn.starts_with ("keep-alive") + end + end + http_expect: detachable READABLE_STRING_8 -- The Expect request-header field is used to indicate that particular server behaviors are required by the client. -- Example: '100-continue'. diff --git a/library/server/wsf/src/wsf_response.e b/library/server/wsf/src/wsf_response.e index 0ca3530c..faf40a4f 100644 --- a/library/server/wsf/src/wsf_response.e +++ b/library/server/wsf/src/wsf_response.e @@ -383,6 +383,16 @@ feature -- Body increment_transfered_content_length (a_end_index - a_begin_index + 1) end + put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER) + -- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'. + require + message_writable: message_writable + not_too_big: a_offset + a_count <= f.count + do + wgi_response.put_file_content (f, a_offset, a_count) + increment_transfered_content_length (a_count) + end + feature -- Chunk body put_chunk (a_content: READABLE_STRING_8; a_ext: detachable READABLE_STRING_8) @@ -572,7 +582,7 @@ feature {NONE} -- Implemenation end note - copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" + copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/tests/src/wgi_response_null.e b/library/server/wsf/tests/src/wgi_response_null.e index 95b47c83..3d41b925 100644 --- a/library/server/wsf/tests/src/wgi_response_null.e +++ b/library/server/wsf/tests/src/wgi_response_null.e @@ -108,6 +108,49 @@ feature -- Output operation output.append_substring (s, start_index, end_index) end + put_file_content (a_file: FILE; a_offset: INTEGER; a_byte_count: INTEGER) + -- Send `a_byte_count' bytes from the content of file `a_file' starting at offset `a_offset'. + --| Could be redefined for optimization. + local + l_close_needed: BOOLEAN + l_remain: INTEGER + l_done: BOOLEAN + s: STRING + do + if a_file.exists and then a_file.is_access_readable then + if a_file.is_open_read then + l_close_needed := False + else + l_close_needed := True + a_file.open_read + end + if a_offset > 0 then + a_file.move (a_offset) + end + from + l_remain := a_byte_count + l_done := False + until + a_file.exhausted or l_done + loop + a_file.read_stream (l_remain.min (4_096)) + s := a_file.last_string + if s.is_empty then + -- network error? + l_done := True + else + put_string (s) + l_remain := l_remain - s.count + check l_remain >= 0 end + l_done := l_remain = 0 + end + end + if l_close_needed then + a_file.close + end + end + end + flush do output.wipe_out diff --git a/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e b/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e index a0ab3c6b..e01f7b72 100644 --- a/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e +++ b/library/server/wsf_proxy/reverse_proxy/wsf_simple_reverse_proxy_handler.e @@ -291,11 +291,8 @@ feature {NONE} -- Implementation response.set_status_code (a_status_code) response.header.put_content_type_text_html response.header.put_content_length (s.count) - if - attached request.http_connection as l_connection and then - l_connection.is_case_insensitive_equal_general ("keep-alive") - then - response.header.put_header_key_value ("Connection", "keep-alive") + if request.is_keep_alive_http_connection then + response.header.put_connection_keep_alive end response.put_string (s) end diff --git a/tools/estudio_wizard/rootdir/resources/${APP_NAME}.ecf b/tools/estudio_wizard/rootdir/resources/${APP_NAME}.ecf index e4ef2809..9b2044d4 100644 --- a/tools/estudio_wizard/rootdir/resources/${APP_NAME}.ecf +++ b/tools/estudio_wizard/rootdir/resources/${APP_NAME}.ecf @@ -15,10 +15,10 @@ + {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{/if} {if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"}{/if} {if condition="$WIZ.connectors.use_libfcgi ~ $WIZ_YES"}{/if} - {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{/if} - + diff --git a/tools/estudio_wizard/rootdir/resources/launcher/any/application_launcher_i.e b/tools/estudio_wizard/rootdir/resources/launcher/any/application_launcher_i.e index c6213e30..fe0ff855 100644 --- a/tools/estudio_wizard/rootdir/resources/launcher/any/application_launcher_i.e +++ b/tools/estudio_wizard/rootdir/resources/launcher/any/application_launcher_i.e @@ -20,28 +20,27 @@ feature -- Execution launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) -- Launch Web Server Application using optionals `opts'. local - launcher: WSF_SERVICE_LAUNCHER + launcher: WSF_SERVICE_LAUNCHER [G] do - l_id := launcher_id if not attached launcher_id as l_id then {unless condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{literal} io.error.put_string ("Application launcher not found!%N") (create {EXCEPTIONS}).die (-1){/literal}{/unless} {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{literal} -- Choose a default -> standalone - create {WSF_STANDALONE_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} + create {WSF_STANDALONE_SERVICE_LAUNCHER [G]} launcher.make_and_launch (opts){/literal}{/if} {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{literal} elseif is_standalone_launcher_id (l_id) then - create {WSF_STANDALONE_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} + create {WSF_STANDALONE_SERVICE_LAUNCHER [G]} launcher.make_and_launch (opts){/literal}{/if} {if condition="$WIZ.connectors.use_libfcgi ~ $WIZ_YES"}{literal} elseif is_libfcgi_launcher_id (l_id) then - create {WSF_LIBFCGI_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} + create {WSF_LIBFCGI_SERVICE_LAUNCHER [G]} launcher.make_and_launch (opts){/literal}{/if} {if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"}{literal} elseif is_cgi_launcher_id (l_id) then - create {WSF_CGI_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} + create {WSF_CGI_SERVICE_LAUNCHER [G]} launcher.make_and_launch (opts){/literal}{/if} {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"}{literal} elseif is_standalone_launcher_id (l_id) then - create {WSF_STANDALONE_SERVICE_LAUNCHER} launcher.make_and_launch (opts){/literal}{/if} + create {WSF_STANDALONE_SERVICE_LAUNCHER [G]} launcher.make_and_launch (opts){/literal}{/if} {literal} else io.error.put_string ("Application launcher not found!%N") @@ -53,31 +52,39 @@ feature -- Execution -- Launcher id based on the executable extension name if any. -- This can be redefine to customize for your application. --| ex: standalone, cgi, libfcgi or Void. + local + p: PATH + s: READABLE_STRING_32 do - if attached (create {PATH}.make_from_string (execution_environment.arguments.command_name)).extension as ext then - Result := ext + create p.make_from_string (execution_environment.arguments.command_name) + if attached p.extension as ext then + if ext.is_case_insensitive_equal_general ("exe") then + -- Windows + s := p.name + create p.make_from_string (s.head (s.count - 4)) + Result := p.extension + else + Result := ext + end end end -feature -- Status report -{/literal} +feature -- Status report{/literal} {if condition="$WIZ.connectors.use_standalone ~ $WIZ_YES"} is_standalone_launcher_id (a_id: READABLE_STRING_GENERAL): BOOLEAN do - Result := a_id.is_case_insensitive ("standalone") + Result := a_id.is_case_insensitive_equal ("standalone") end{/if} - {if condition="$WIZ.connectors.use_cgi ~ $WIZ_YES"} is_cgi_launcher_id (a_id: READABLE_STRING_GENERAL): BOOLEAN do - Result := a_id.is_case_insensitive ("cgi") + Result := a_id.is_case_insensitive_equal ("cgi") end{/if} - {if condition="$WIZ.connectors.use_libfcgi ~ $WIZ_YES"} is_libfcgi_launcher_id (a_id: READABLE_STRING_GENERAL): BOOLEAN do - Result := a_id.is_case_insensitive ("libfcgi") - or a_id.is_case_insensitive ("fcgi") + Result := a_id.is_case_insensitive_equal ("libfcgi") + or a_id.is_case_insensitive_equal ("fcgi") end{/if} end diff --git a/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}.e b/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}.e index 0dab746f..70325bb9 100644 --- a/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}.e +++ b/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}.e @@ -14,10 +14,8 @@ inherit redefine initialize end -{if condition="$WIZ.routers.use_router ~ $WIZ_YES"} - WSF_ROUTED_SERVICE{/if} {if isset="$APP_ROOT"}APPLICATION_LAUNCHER [{$APP_ROOT/}_EXECUTION]{/if} - {unless isset="$APP_ROOT"}APPLICATION_LAUNCHER [APPLICATION_EXECUTION]{/if} + {unless isset="$APP_ROOT"}APPLICATION_LAUNCHER [APPLICATION_EXECUTION]{/unless} {literal}create make_and_launch @@ -29,6 +27,7 @@ feature {NONE} -- Initialization do Precursor set_service_option ("port", {$WIZ.standalone_connector.port/}) + set_service_option ("verbose", "{$WIZ.standalone_connector.verbose/}") end diff --git a/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}_EXECUTION.e b/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}_EXECUTION.e index 9baf8fe4..4929295a 100644 --- a/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}_EXECUTION.e +++ b/tools/estudio_wizard/rootdir/resources/src/${APP_ROOT}_EXECUTION.e @@ -11,15 +11,15 @@ class inherit {unless condition="$WIZ.routers.use_router ~ $WIZ_YES"} - {unless condition="$WIZ.routers.use_filter ~ $WIZ_YES"} + {unless condition="$WIZ.filters.use_filter ~ $WIZ_YES"} WSF_EXECUTION{/unless} - {if condition="$WIZ.routers.use_filter ~ $WIZ_YES"} + {if condition="$WIZ.filters.use_filter ~ $WIZ_YES"} WSF_FILTERED_EXECUTION{/if} {/unless} {if condition="$WIZ.routers.use_router ~ $WIZ_YES"} - {unless condition="$WIZ.routers.use_filter ~ $WIZ_YES"} + {unless condition="$WIZ.filters.use_filter ~ $WIZ_YES"} WSF_ROUTED_EXECUTION{/unless} - {if condition="$WIZ.routers.use_filter ~ $WIZ_YES"} + {if condition="$WIZ.filters.use_filter ~ $WIZ_YES"} WSF_FILTERED_ROUTED_EXECUTION{/if} {/if} @@ -28,7 +28,6 @@ inherit feature {NONE} -- Initialization {/literal} - {unless condition="$WIZ.routers.use_router ~ $WIZ_YES"}{literal} feature -- Execution @@ -42,9 +41,9 @@ feature -- Execution --| To send back easily a simple plaintext message. create mesg.make_with_body ("Hello Eiffel Web") response.send (mesg) - end{/unless} - -{if condition="$WIZ.routers.use_filter ~ $WIZ_YES"}{literal} + end +{/literal}{/unless} +{if condition="$WIZ.filters.use_filter ~ $WIZ_YES"}{literal} feature -- Filter create_filter @@ -56,15 +55,18 @@ feature -- Filter setup_filter -- Setup `filter' + local + f: like filter do - append_filters (<< - create {WSF_CORS_FILTER}, - create {WSF_LOGGING_FILTER} - >>) + create {WSF_CORS_FILTER} f + f.set_next (create {WSF_LOGGING_FILTER}) + --| Chain more filters like {WSF_CUSTOM_HEADER_FILTER}, ... --| and your owns filters. - end{/if} + filter.append (f) + end +{/literal}{/if} {if condition="$WIZ.routers.use_router ~ $WIZ_YES"}{literal} feature -- Router @@ -78,12 +80,12 @@ feature -- Router --| /* are dispatched to serve files/directories contained in "www" directory --| Self documentation - router.handle_with_request_methods ("/doc", create {WSF_ROUTER_SELF_DOCUMENTATION_HANDLER}.make (router), router.methods_GET) + router.handle ("/doc", create {WSF_ROUTER_SELF_DOCUMENTATION_HANDLER}.make (router), router.methods_GET) --| Files publisher create fhdl.make_hidden ("www") fhdl.set_directory_index (<<"index.html">>) - router.handle_with_request_methods ("", fhdl, router.methods_GET) + router.handle ("", fhdl, router.methods_GET) end{/literal}{/if} end diff --git a/tools/install_ewf.bat b/tools/install_ewf.bat index dd1fa889..ff873472 100644 --- a/tools/install_ewf.bat +++ b/tools/install_ewf.bat @@ -53,6 +53,8 @@ echo Install framework ewf %SAFE_MD% %TMP_CONTRIB_DIR%\library\web\framework\ewf echo Install library: ewf/ewsgi %COPYCMD% %TMP_DIR%\library\server\ewsgi %TMP_CONTRIB_DIR%\library\web\framework\ewf\ewsgi +echo Install library: ewf/httpd +%COPYCMD% %TMP_DIR%\library\server\httpd %TMP_CONTRIB_DIR%\library\web\framework\ewf\httpd echo Install library: ewf/libfcgi %COPYCMD% %TMP_DIR%\library\server\libfcgi %TMP_CONTRIB_DIR%\library\web\framework\ewf\libfcgi echo Install library: ewf/wsf @@ -86,6 +88,10 @@ echo Install library: error %COPYCMD% %TMP_DIR%\library\utility\general\error %TMP_CONTRIB_DIR%\library\utility\general\error echo Install library: http_client %COPYCMD% %TMP_DIR%\library\network\http_client %TMP_CONTRIB_DIR%\library\network\http_client +echo Install library: http_network +%COPYCMD% %TMP_DIR%\library\network\http_network %TMP_CONTRIB_DIR%\library\network\http_network +echo Install library: websocket +%COPYCMD% %TMP_DIR%\library\network\websocket %TMP_CONTRIB_DIR%\library\network\websocket echo Install library: http %COPYCMD% %TMP_DIR%\library\network\protocol\http %TMP_CONTRIB_DIR%\library\network\protocol\http echo Install library: content_negotiation diff --git a/tools/uninstall_ewf.bat b/tools/uninstall_ewf.bat index f1cef7c3..e65b7cb6 100644 --- a/tools/uninstall_ewf.bat +++ b/tools/uninstall_ewf.bat @@ -55,6 +55,10 @@ echo Uninstall library: error %RDCMD% %TMP_CONTRIB_DIR%\library\utility\general\error echo Uninstall library: http_client %RDCMD% %TMP_CONTRIB_DIR%\library\network\http_client +echo Uninstall library: http_network +%RDCMD% %TMP_CONTRIB_DIR%\library\network\http_network +echo Uninstall library: websocket +%RDCMD% %TMP_CONTRIB_DIR%\library\network\websocket echo Uninstall library: http %RDCMD% %TMP_CONTRIB_DIR%\library\network\protocol\http echo Uninstall library: content_negotiation