Removed any (put|write)_file_content from the WSF_ or WGI_ OUTPUT classes
Now DEFAULT_SERVICE has to be created instead of inherited. - This seems to be better for new user, and this avoid potential conflict and difference when inheriting between the various DEFAULT_SERVICE implementation. - remember that DEFAULT_SERVICE, is mainly to help the user to build its very first service. Use READABLE_STRING_8 as argument whenever it is possible. Added WSF_RESPONSE_MESSAGE, and WSF_RESPONSE.put_response (a_response_message) Now WSF_RESPONSE inherit from WGI_RESPONSE
This commit is contained in:
Submodule contrib/library/server/nino updated: 59505ccdc4...8b4f774bab
@@ -1,24 +1,28 @@
|
|||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-9-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-9-0 http://www.eiffel.com/developers/xml/configuration-1-9-0.xsd" name="hello_routed_world" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-9-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-9-0 http://www.eiffel.com/developers/xml/configuration-1-9-0.xsd" name="hello_routed_world" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
|
||||||
<target name="hello_connector">
|
<target name="hello_connector" abstract="true">
|
||||||
<root class="HELLO_ROUTED_WORLD" feature="make"/>
|
<root class="HELLO_ROUTED_WORLD" feature="make"/>
|
||||||
<file_rule>
|
<file_rule>
|
||||||
<exclude>/EIFGENs$</exclude>
|
<exclude>/EIFGENs$</exclude>
|
||||||
<exclude>/\.git$</exclude>
|
<exclude>/\.git$</exclude>
|
||||||
<exclude>/\.svn$</exclude>
|
<exclude>/\.svn$</exclude>
|
||||||
</file_rule>
|
</file_rule>
|
||||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||||
|
<debug name="nino" enabled="true"/>
|
||||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" supplier_precondition="true"/>
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" supplier_precondition="true"/>
|
||||||
</option>
|
</option>
|
||||||
<setting name="concurrency" value="thread"/>
|
<setting name="concurrency" value="thread"/>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
|
||||||
<library name="http" location="..\..\library\protocol\http\http-safe.ecf" readonly="false"/>
|
<library name="http" location="..\..\library\protocol\http\http-safe.ecf" readonly="false"/>
|
||||||
<library name="router" location="..\..\library\server\request\router\router-safe.ecf" readonly="false"/>
|
<library name="router" location="..\..\library\server\request\router\router-safe.ecf" readonly="false"/>
|
||||||
|
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="hello_nino" extends="hello_connector">
|
<target name="hello_nino" extends="hello_connector">
|
||||||
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf"/>
|
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||||
|
<debug name="nino" enabled="true"/>
|
||||||
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" supplier_precondition="true"/>
|
||||||
|
</option>
|
||||||
|
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" use_application_options="true"/>
|
||||||
<cluster name="src" location="src\" recursive="true"/>
|
<cluster name="src" location="src\" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
<target name="hello_cgi" extends="hello_connector">
|
<target name="hello_cgi" extends="hello_connector">
|
||||||
|
|||||||
@@ -8,24 +8,21 @@ class
|
|||||||
HELLO_ROUTED_WORLD
|
HELLO_ROUTED_WORLD
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
ANY
|
|
||||||
|
|
||||||
URI_TEMPLATE_ROUTED_SERVICE
|
URI_TEMPLATE_ROUTED_SERVICE
|
||||||
|
|
||||||
ROUTED_SERVICE_HELPER
|
ROUTED_SERVICE_HELPER
|
||||||
|
|
||||||
DEFAULT_SERVICE
|
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
|
||||||
make
|
make
|
||||||
|
local
|
||||||
|
s: DEFAULT_SERVICE
|
||||||
do
|
do
|
||||||
initialize_router
|
initialize_router
|
||||||
make_and_launch
|
create s.make_and_launch (agent execute)
|
||||||
end
|
end
|
||||||
|
|
||||||
create_router
|
create_router
|
||||||
@@ -90,7 +87,11 @@ feature -- Execution
|
|||||||
n: INTEGER
|
n: INTEGER
|
||||||
i: INTEGER
|
i: INTEGER
|
||||||
s: STRING_8
|
s: STRING_8
|
||||||
|
df: WSF_FILE_RESPONSE
|
||||||
do
|
do
|
||||||
|
create df.make_html ("index.html")
|
||||||
|
df.set_no_cache
|
||||||
|
|
||||||
l_url := req.script_url ("/home")
|
l_url := req.script_url ("/home")
|
||||||
|
|
||||||
n := 3
|
n := 3
|
||||||
@@ -199,7 +200,7 @@ feature -- Execution
|
|||||||
|
|
||||||
handle_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
handle_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
do
|
do
|
||||||
execute_hello (req, res, Void, ctx)
|
execute_hello (req, res, ctx.string_parameter ("name"), ctx)
|
||||||
end
|
end
|
||||||
|
|
||||||
handle_anonymous_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
handle_anonymous_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ inherit
|
|||||||
|
|
||||||
ROUTED_SERVICE_HELPER
|
ROUTED_SERVICE_HELPER
|
||||||
|
|
||||||
DEFAULT_SERVICE
|
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make
|
make
|
||||||
|
local
|
||||||
|
s: DEFAULT_SERVICE
|
||||||
do
|
do
|
||||||
initialize_router
|
initialize_router
|
||||||
make_and_launch
|
create s.make_and_launch (agent execute)
|
||||||
end
|
end
|
||||||
|
|
||||||
create_router
|
create_router
|
||||||
|
|||||||
@@ -193,6 +193,12 @@ feature -- Content related header
|
|||||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_transfer_encoding, a_enc)
|
put_header_key_value ({HTTP_HEADER_NAMES}.header_transfer_encoding, a_enc)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
put_transfer_encoding_binary
|
||||||
|
-- Put "Transfer-Encoding: binary" header
|
||||||
|
do
|
||||||
|
put_transfer_encoding ("binary")
|
||||||
|
end
|
||||||
|
|
||||||
put_transfer_encoding_chunked
|
put_transfer_encoding_chunked
|
||||||
-- Put "Transfer-Encoding: chunked" header
|
-- Put "Transfer-Encoding: chunked" header
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ note
|
|||||||
deferred class
|
deferred class
|
||||||
WGI_RESPONSE
|
WGI_RESPONSE
|
||||||
|
|
||||||
feature {WGI_SERVICE} -- Commit
|
feature {WGI_RESPONSE, WGI_SERVICE} -- Commit
|
||||||
|
|
||||||
commit
|
commit
|
||||||
-- Commit the current response
|
-- Commit the current response
|
||||||
@@ -110,13 +110,6 @@ feature -- Output operation
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
write_file_content (fn: READABLE_STRING_8)
|
|
||||||
-- Send the content of file `fn'
|
|
||||||
require
|
|
||||||
message_writable: message_writable
|
|
||||||
deferred
|
|
||||||
end
|
|
||||||
|
|
||||||
flush
|
flush
|
||||||
-- Flush if it makes sense
|
-- Flush if it makes sense
|
||||||
deferred
|
deferred
|
||||||
|
|||||||
@@ -43,25 +43,6 @@ feature -- Basic operation
|
|||||||
put_string (s.substring (start_index, end_index))
|
put_string (s.substring (start_index, end_index))
|
||||||
end
|
end
|
||||||
|
|
||||||
put_file_content (fn: STRING)
|
|
||||||
-- Send the content of file `fn'
|
|
||||||
local
|
|
||||||
f: RAW_FILE
|
|
||||||
do
|
|
||||||
create f.make (fn)
|
|
||||||
if f.exists and then f.is_readable then
|
|
||||||
f.open_read
|
|
||||||
from
|
|
||||||
until
|
|
||||||
f.exhausted
|
|
||||||
loop
|
|
||||||
f.read_stream (4096)
|
|
||||||
put_string (f.last_string)
|
|
||||||
end
|
|
||||||
f.close
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
put_header_line (s: STRING)
|
put_header_line (s: STRING)
|
||||||
-- Send `s' to http client as header line
|
-- Send `s' to http client as header line
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -115,12 +115,6 @@ feature -- Output operation
|
|||||||
output.put_substring (s, start_index, end_index)
|
output.put_substring (s, start_index, end_index)
|
||||||
end
|
end
|
||||||
|
|
||||||
write_file_content (fn: READABLE_STRING_8)
|
|
||||||
-- Send the content of file `fn'
|
|
||||||
do
|
|
||||||
output.put_file_content (fn)
|
|
||||||
end
|
|
||||||
|
|
||||||
flush
|
flush
|
||||||
do
|
do
|
||||||
output.flush
|
output.flush
|
||||||
|
|||||||
@@ -46,28 +46,6 @@ feature -- Output
|
|||||||
put_string (c.out)
|
put_string (c.out)
|
||||||
end
|
end
|
||||||
|
|
||||||
put_file_content (fn: READABLE_STRING_8)
|
|
||||||
-- Send the content of file `fn'
|
|
||||||
require
|
|
||||||
string_not_empty: not fn.is_empty
|
|
||||||
is_readable: (create {RAW_FILE}.make (fn)).is_readable
|
|
||||||
local
|
|
||||||
f: RAW_FILE
|
|
||||||
do
|
|
||||||
create f.make (fn)
|
|
||||||
check f.exists and then f.is_readable end
|
|
||||||
|
|
||||||
f.open_read
|
|
||||||
from
|
|
||||||
until
|
|
||||||
f.exhausted
|
|
||||||
loop
|
|
||||||
f.read_stream (4096)
|
|
||||||
put_string (f.last_string)
|
|
||||||
end
|
|
||||||
f.close
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Specific output
|
feature -- Specific output
|
||||||
|
|
||||||
put_header_line (s: READABLE_STRING_8)
|
put_header_line (s: READABLE_STRING_8)
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ feature -- Input
|
|||||||
|
|
||||||
feature -- Output
|
feature -- Output
|
||||||
|
|
||||||
put_string (a_str: STRING)
|
put_string (a_str: READABLE_STRING_8)
|
||||||
-- Put `a_str' on the FastCGI stdout.
|
-- Put `a_str' on the FastCGI stdout.
|
||||||
require
|
require
|
||||||
a_str_not_void: a_str /= Void
|
a_str_not_void: a_str /= Void
|
||||||
|
|||||||
@@ -147,32 +147,21 @@ feature -- Execution
|
|||||||
|
|
||||||
respond_file (f: FILE; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
respond_file (f: FILE; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
local
|
local
|
||||||
fn: READABLE_STRING_8
|
|
||||||
h: HTTP_HEADER
|
h: HTTP_HEADER
|
||||||
ext: READABLE_STRING_8
|
ext: READABLE_STRING_8
|
||||||
ct: detachable READABLE_STRING_8
|
ct: detachable READABLE_STRING_8
|
||||||
|
fres: WSF_FILE_RESPONSE
|
||||||
do
|
do
|
||||||
fn := f.name
|
ext := extension (f.name)
|
||||||
ext := extension (fn)
|
|
||||||
ct := extension_mime_mapping.mime_type (ext)
|
ct := extension_mime_mapping.mime_type (ext)
|
||||||
create h.make
|
if ct = Void then
|
||||||
|
ct := {HTTP_MIME_TYPES}.application_force_download
|
||||||
|
end
|
||||||
|
create fres.make_with_content_type (ct, f.name)
|
||||||
|
fres.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
|
fres.set_answer_head_request_method (req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head))
|
||||||
|
|
||||||
if ct /= Void then
|
res.put_response (fres)
|
||||||
h.put_content_type (ct)
|
|
||||||
h.put_content_length (f.count)
|
|
||||||
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
|
||||||
res.write_header_text (h.string)
|
|
||||||
else
|
|
||||||
create h.make
|
|
||||||
h.put_content_type ({HTTP_MIME_TYPES}.application_force_download)
|
|
||||||
h.put_content_length (f.count)
|
|
||||||
res.set_status_code ({HTTP_STATUS_CODE}.ok)
|
|
||||||
res.write_header_text (h.string)
|
|
||||||
end
|
|
||||||
if not req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head) then
|
|
||||||
res.write_file_content (fn)
|
|
||||||
end
|
|
||||||
res.flush
|
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_not_found (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
respond_not_found (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
|||||||
@@ -3,22 +3,37 @@ note
|
|||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
deferred class
|
class
|
||||||
DEFAULT_SERVICE
|
DEFAULT_SERVICE
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
WSF_SERVICE
|
WSF_SERVICE
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make_and_launch
|
make_and_launch (a_action: like action)
|
||||||
local
|
local
|
||||||
cgi: WGI_CGI_CONNECTOR
|
cgi: WGI_CGI_CONNECTOR
|
||||||
do
|
do
|
||||||
|
action := a_action
|
||||||
create cgi.make (Current)
|
create cgi.make (Current)
|
||||||
cgi.launch
|
cgi.launch
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature -- Execution
|
||||||
|
|
||||||
|
action: PROCEDURE [ANY, TUPLE [WSF_REQUEST, WSF_RESPONSE]]
|
||||||
|
-- Action to be executed on request incoming
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
action.call ([req, res])
|
||||||
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2011, Eiffel Software and others"
|
copyright: "2011-2011, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
|||||||
@@ -3,22 +3,37 @@ note
|
|||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
deferred class
|
class
|
||||||
DEFAULT_SERVICE
|
DEFAULT_SERVICE
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
WSF_SERVICE
|
WSF_SERVICE
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make_and_launch
|
make_and_launch (a_action: like action)
|
||||||
local
|
local
|
||||||
conn: WGI_LIBFCGI_CONNECTOR
|
conn: WGI_LIBFCGI_CONNECTOR
|
||||||
do
|
do
|
||||||
|
action := a_action
|
||||||
create conn.make (Current)
|
create conn.make (Current)
|
||||||
conn.launch
|
conn.launch
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature -- Execution
|
||||||
|
|
||||||
|
action: PROCEDURE [ANY, TUPLE [WSF_REQUEST, WSF_RESPONSE]]
|
||||||
|
-- Action to be executed on request incoming
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
action.call ([req, res])
|
||||||
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2011, Eiffel Software and others"
|
copyright: "2011-2011, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
|||||||
@@ -3,34 +3,48 @@ note
|
|||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
deferred class
|
class
|
||||||
DEFAULT_SERVICE
|
DEFAULT_SERVICE
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
WSF_SERVICE
|
WSF_SERVICE
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make_and_launch
|
make_and_launch (a_action: like action)
|
||||||
local
|
local
|
||||||
app: NINO_SERVICE
|
app: NINO_SERVICE
|
||||||
|
port_number: INTEGER
|
||||||
|
base_url: STRING
|
||||||
do
|
do
|
||||||
port_number := 8080
|
action := a_action
|
||||||
|
port_number := 80 --| Default, but quite often, this port is already used ...
|
||||||
base_url := ""
|
base_url := ""
|
||||||
debug ("nino")
|
debug ("nino")
|
||||||
print ("Example: start a Nino web server on port " + port_number.out +
|
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 + "/" + base_url + "%N")
|
", %Nand reply Hello World for any request such as http://localhost:" + port_number.out + "/" + base_url + "%N")
|
||||||
end
|
end
|
||||||
create app.make_custom (agent wgi_execute, base_url)
|
create app.make_custom (agent wgi_execute, base_url)
|
||||||
|
debug ("nino")
|
||||||
|
app.set_is_verbose (True)
|
||||||
|
end
|
||||||
app.listen (port_number)
|
app.listen (port_number)
|
||||||
end
|
end
|
||||||
|
|
||||||
port_number: INTEGER
|
feature -- Execution
|
||||||
|
|
||||||
base_url: STRING
|
action: PROCEDURE [ANY, TUPLE [WSF_REQUEST, WSF_RESPONSE]]
|
||||||
|
-- Action to be executed on request incoming
|
||||||
|
|
||||||
|
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
action.call ([req, res])
|
||||||
|
end
|
||||||
|
|
||||||
invariant
|
|
||||||
port_number_valid: port_number > 0
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2011, Eiffel Software and others"
|
copyright: "2011-2011, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
|||||||
26
library/server/wsf/src/response/wsf_download_response.e
Normal file
26
library/server/wsf/src/response/wsf_download_response.e
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
note
|
||||||
|
description : "Objects that ..."
|
||||||
|
author : "$Author$"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_DOWNLOAD_RESPONSE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_FILE_RESPONSE
|
||||||
|
redefine
|
||||||
|
get_content_type
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
get_content_type
|
||||||
|
do
|
||||||
|
content_type := {HTTP_MIME_TYPES}.application_force_download
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
210
library/server/wsf/src/response/wsf_file_response.e
Normal file
210
library/server/wsf/src/response/wsf_file_response.e
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
note
|
||||||
|
description : "Objects that ..."
|
||||||
|
author : "$Author$"
|
||||||
|
date : "$Date$"
|
||||||
|
revision : "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_FILE_RESPONSE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_RESPONSE_MESSAGE
|
||||||
|
|
||||||
|
create
|
||||||
|
make,
|
||||||
|
make_with_content_type,
|
||||||
|
make_html
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_file_name: READABLE_STRING_8)
|
||||||
|
do
|
||||||
|
file_name := a_file_name
|
||||||
|
base_name := basename (a_file_name)
|
||||||
|
get_content_type
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
make_with_content_type (a_content_type: READABLE_STRING_8; a_filename: READABLE_STRING_8)
|
||||||
|
-- Initialize `Current'.
|
||||||
|
do
|
||||||
|
file_name := a_filename
|
||||||
|
base_name := basename (a_filename)
|
||||||
|
content_type := a_content_type
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
make_html (a_filename: READABLE_STRING_8)
|
||||||
|
-- Initialize `Current'.
|
||||||
|
do
|
||||||
|
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
initialize
|
||||||
|
local
|
||||||
|
h: like header
|
||||||
|
do
|
||||||
|
create h.make
|
||||||
|
header := h
|
||||||
|
h.put_content_type (content_type)
|
||||||
|
h.put_transfer_encoding_binary
|
||||||
|
h.put_content_length (filesize (file_name))
|
||||||
|
h.put_content_disposition ("attachment", "filename=%""+ base_name +"%"")
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
set_expires (t: INTEGER)
|
||||||
|
do
|
||||||
|
header.put_expires (t)
|
||||||
|
end
|
||||||
|
|
||||||
|
set_no_cache
|
||||||
|
local
|
||||||
|
h: like header
|
||||||
|
do
|
||||||
|
h := header
|
||||||
|
h.put_expires (0)
|
||||||
|
h.put_cache_control ("no-cache, must-revalidate")
|
||||||
|
h.put_pragma_no_cache
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
header: HTTP_HEADER
|
||||||
|
|
||||||
|
status_code: INTEGER assign set_status_code
|
||||||
|
|
||||||
|
file_name: READABLE_STRING_8
|
||||||
|
|
||||||
|
base_name: READABLE_STRING_8
|
||||||
|
|
||||||
|
content_type: READABLE_STRING_8
|
||||||
|
|
||||||
|
feature -- Settings
|
||||||
|
|
||||||
|
answer_head_request_method: BOOLEAN assign set_answer_head_request_method
|
||||||
|
-- For HEAD request method, only http header should be sent
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
set_status_code (c: like status_code)
|
||||||
|
-- Set `status_code' to `c'.
|
||||||
|
require
|
||||||
|
valid_status_code: status_code > 0
|
||||||
|
do
|
||||||
|
status_code := c
|
||||||
|
ensure
|
||||||
|
status_code_set: status_code = c
|
||||||
|
end
|
||||||
|
|
||||||
|
set_answer_head_request_method (b: BOOLEAN)
|
||||||
|
-- Set answer_head_request_method' to `b'.
|
||||||
|
do
|
||||||
|
answer_head_request_method := b
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Basic operations
|
||||||
|
|
||||||
|
send_to (res: WSF_RESPONSE)
|
||||||
|
do
|
||||||
|
res.set_status_code (status_code)
|
||||||
|
res.write_header_text (header.string)
|
||||||
|
if not answer_head_request_method then
|
||||||
|
send_file_content_to (file_name, res)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation: file system helper
|
||||||
|
|
||||||
|
filesize (fn: STRING): INTEGER
|
||||||
|
-- Size of the file `fn'.
|
||||||
|
local
|
||||||
|
f: RAW_FILE
|
||||||
|
do
|
||||||
|
create f.make (fn)
|
||||||
|
if f.exists then
|
||||||
|
Result := f.count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
file_extension (fn: STRING): STRING
|
||||||
|
-- Extension of file `fn'.
|
||||||
|
local
|
||||||
|
p: INTEGER
|
||||||
|
do
|
||||||
|
p := fn.last_index_of ('.', fn.count)
|
||||||
|
if p > 0 then
|
||||||
|
Result := fn.substring (p + 1, fn.count)
|
||||||
|
else
|
||||||
|
create Result.make_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
basename (fn: STRING): STRING
|
||||||
|
-- Basename of `fn'.
|
||||||
|
local
|
||||||
|
p: INTEGER
|
||||||
|
do
|
||||||
|
p := fn.last_index_of ((create {OPERATING_ENVIRONMENT}).Directory_separator, fn.count)
|
||||||
|
if p > 0 then
|
||||||
|
Result := fn.substring (p + 1, fn.count)
|
||||||
|
else
|
||||||
|
Result := fn
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
dirname (fn: STRING): STRING
|
||||||
|
-- Dirname of `fn'.
|
||||||
|
local
|
||||||
|
p: INTEGER
|
||||||
|
do
|
||||||
|
p := fn.last_index_of ((create {OPERATING_ENVIRONMENT}).Directory_separator, fn.count)
|
||||||
|
if p > 0 then
|
||||||
|
Result := fn.substring (1, p - 1)
|
||||||
|
else
|
||||||
|
create Result.make_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Content-type related
|
||||||
|
|
||||||
|
get_content_type
|
||||||
|
-- Content type associated with `file_name'
|
||||||
|
local
|
||||||
|
m_map: HTTP_FILE_EXTENSION_MIME_MAPPING
|
||||||
|
m: detachable READABLE_STRING_8
|
||||||
|
do
|
||||||
|
create m_map.make_default
|
||||||
|
m := m_map.mime_type (file_extension (file_name).as_lower)
|
||||||
|
if m = Void then
|
||||||
|
m := {HTTP_MIME_TYPES}.application_force_download
|
||||||
|
end
|
||||||
|
content_type := m
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation: output
|
||||||
|
|
||||||
|
send_file_content_to (fn: READABLE_STRING_8; res: WSF_RESPONSE)
|
||||||
|
-- Send the content of file `fn'
|
||||||
|
require
|
||||||
|
string_not_empty: not fn.is_empty
|
||||||
|
is_readable: (create {RAW_FILE}.make (fn)).is_readable
|
||||||
|
local
|
||||||
|
f: RAW_FILE
|
||||||
|
do
|
||||||
|
create f.make (fn)
|
||||||
|
check f.exists and then f.is_readable end
|
||||||
|
|
||||||
|
f.open_read
|
||||||
|
from
|
||||||
|
until
|
||||||
|
f.exhausted
|
||||||
|
loop
|
||||||
|
f.read_stream (4_096)
|
||||||
|
res.write_string (f.last_string)
|
||||||
|
end
|
||||||
|
f.close
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
45
library/server/wsf/src/response/wsf_page_response.e
Normal file
45
library/server/wsf/src/response/wsf_page_response.e
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_PAGE_RESPONSE}."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_PAGE_RESPONSE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_RESPONSE_MESSAGE
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make
|
||||||
|
do
|
||||||
|
status_code := {HTTP_STATUS_CODE}.ok
|
||||||
|
create header.make
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Status
|
||||||
|
|
||||||
|
status_code: INTEGER
|
||||||
|
|
||||||
|
feature -- Header
|
||||||
|
|
||||||
|
header: HTTP_HEADER
|
||||||
|
|
||||||
|
body: detachable STRING_8
|
||||||
|
|
||||||
|
feature -- Output
|
||||||
|
|
||||||
|
send_to (res: WSF_RESPONSE)
|
||||||
|
do
|
||||||
|
res.set_status_code (status_code)
|
||||||
|
res.write_header_text (header.string)
|
||||||
|
if attached body as b then
|
||||||
|
res.write_string (b)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -8,6 +8,9 @@ note
|
|||||||
class
|
class
|
||||||
WSF_RESPONSE
|
WSF_RESPONSE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WGI_RESPONSE
|
||||||
|
|
||||||
create {WSF_SERVICE}
|
create {WSF_SERVICE}
|
||||||
make_from_wgi
|
make_from_wgi
|
||||||
|
|
||||||
@@ -55,14 +58,8 @@ feature -- Status setting
|
|||||||
set_status_code (a_code: INTEGER)
|
set_status_code (a_code: INTEGER)
|
||||||
-- Set response status code
|
-- Set response status code
|
||||||
-- Should be done before sending any data back to the client
|
-- 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
|
do
|
||||||
wgi_response.set_status_code (a_code)
|
wgi_response.set_status_code (a_code)
|
||||||
ensure
|
|
||||||
status_code_set: status_code = a_code
|
|
||||||
status_set: status_is_set
|
|
||||||
end
|
end
|
||||||
|
|
||||||
status_code: INTEGER
|
status_code: INTEGER
|
||||||
@@ -71,18 +68,20 @@ feature -- Status setting
|
|||||||
Result := wgi_response.status_code
|
Result := wgi_response.status_code
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature {WGI_RESPONSE} -- Core output operation
|
||||||
|
|
||||||
|
write (s: READABLE_STRING_8)
|
||||||
|
-- Send the string `s'
|
||||||
|
-- this can be used for header and body
|
||||||
|
do
|
||||||
|
wgi_response.write (s)
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Header output operation
|
feature -- Header output operation
|
||||||
|
|
||||||
write_header_text (a_headers: READABLE_STRING_8)
|
write_header_text (a_headers: READABLE_STRING_8)
|
||||||
require
|
|
||||||
status_set: status_is_set
|
|
||||||
header_not_committed: not header_committed
|
|
||||||
do
|
do
|
||||||
wgi_response.write_header_text (a_headers)
|
wgi_response.write_header_text (a_headers)
|
||||||
ensure
|
|
||||||
status_set: status_is_set
|
|
||||||
header_committed: header_committed
|
|
||||||
message_writable: message_writable
|
|
||||||
end
|
end
|
||||||
|
|
||||||
write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]])
|
write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]])
|
||||||
@@ -114,20 +113,21 @@ feature -- Header output operation
|
|||||||
message_writable: message_writable
|
message_writable: message_writable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
write_header_lines (a_lines: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
|
||||||
|
do
|
||||||
|
wgi_response.write_header_lines (a_lines)
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Output operation
|
feature -- Output operation
|
||||||
|
|
||||||
write_string (s: READABLE_STRING_8)
|
write_string (s: READABLE_STRING_8)
|
||||||
-- Send the string `s'
|
-- Send the string `s'
|
||||||
require
|
|
||||||
message_writable: message_writable
|
|
||||||
do
|
do
|
||||||
wgi_response.write_string (s)
|
wgi_response.write_string (s)
|
||||||
end
|
end
|
||||||
|
|
||||||
write_substring (s: READABLE_STRING_8; a_begin_index, a_end_index: INTEGER)
|
write_substring (s: READABLE_STRING_8; a_begin_index, a_end_index: INTEGER)
|
||||||
-- Send the substring `s[a_begin_index:a_end_index]'
|
-- Send the substring `s[a_begin_index:a_end_index]'
|
||||||
require
|
|
||||||
message_writable: message_writable
|
|
||||||
do
|
do
|
||||||
wgi_response.write_substring (s, a_begin_index, a_end_index)
|
wgi_response.write_substring (s, a_begin_index, a_end_index)
|
||||||
end
|
end
|
||||||
@@ -163,14 +163,6 @@ feature -- Output operation
|
|||||||
flush
|
flush
|
||||||
end
|
end
|
||||||
|
|
||||||
write_file_content (fn: READABLE_STRING_8)
|
|
||||||
-- Send the content of file `fn'
|
|
||||||
require
|
|
||||||
message_writable: message_writable
|
|
||||||
do
|
|
||||||
wgi_response.write_file_content (fn)
|
|
||||||
end
|
|
||||||
|
|
||||||
flush
|
flush
|
||||||
-- Flush if it makes sense
|
-- Flush if it makes sense
|
||||||
do
|
do
|
||||||
@@ -179,6 +171,17 @@ feature -- Output operation
|
|||||||
|
|
||||||
feature -- Helper
|
feature -- Helper
|
||||||
|
|
||||||
|
put_response (obj: WSF_RESPONSE_MESSAGE)
|
||||||
|
require
|
||||||
|
not header_committed
|
||||||
|
not status_is_set
|
||||||
|
not message_committed
|
||||||
|
do
|
||||||
|
obj.send_to (Current)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Redirect
|
||||||
|
|
||||||
redirect_now_with_custom_status_code (a_url: READABLE_STRING_8; a_status_code: INTEGER)
|
redirect_now_with_custom_status_code (a_url: READABLE_STRING_8; a_status_code: INTEGER)
|
||||||
-- Redirect to the given url `a_url' and precise custom `a_status_code'
|
-- Redirect to the given url `a_url' and precise custom `a_status_code'
|
||||||
-- Please see http://www.faqs.org/rfcs/rfc2616 to use proper status code.
|
-- Please see http://www.faqs.org/rfcs/rfc2616 to use proper status code.
|
||||||
@@ -205,6 +208,14 @@ feature -- Helper
|
|||||||
redirect_now_with_custom_status_code (a_url, {HTTP_STATUS_CODE}.moved_permanently)
|
redirect_now_with_custom_status_code (a_url, {HTTP_STATUS_CODE}.moved_permanently)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature {WGI_RESPONSE, WGI_SERVICE} -- Commit
|
||||||
|
|
||||||
|
commit
|
||||||
|
-- Commit the current response
|
||||||
|
do
|
||||||
|
wgi_response.commit
|
||||||
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2011, Eiffel Software and others"
|
copyright: "2011-2011, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
|||||||
16
library/server/wsf/src/wsf_response_message.e
Normal file
16
library/server/wsf/src/wsf_response_message.e
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_RESPONSE_MESSAGE}."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
WSF_RESPONSE_MESSAGE
|
||||||
|
|
||||||
|
feature -- Output
|
||||||
|
|
||||||
|
send_to (res: WSF_RESPONSE)
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user