Prepared httpd_stream to be useable for client too.

Fixed obsolete tests/dev compilation (mainly to avoid wrong failure reports).
added package.iron files.
This commit is contained in:
2016-06-15 17:56:22 +02:00
parent 113aa69efc
commit dfa60bf8f5
11 changed files with 378 additions and 256 deletions

View File

@@ -92,10 +92,10 @@ feature -- Access: SSL
is_secure: BOOLEAN
-- Is SSL/TLS session?.
ca_crt: STRING
ca_crt: IMMUTABLE_STRING_8
-- the signed certificate.
ca_key: STRING
ca_key: IMMUTABLE_STRING_8
-- private key to the certificate.
ssl_protocol: NATURAL
@@ -218,20 +218,16 @@ feature -- Element change
feature -- Element change
set_ca_crt (a_value: STRING)
-- Set `ca_crt' with `a_value'
set_ca_crt (a_value: separate READABLE_STRING_8)
-- Set `ca_crt' from `a_value'.
do
ca_crt := a_value
ensure
ca_crt_set: ca_crt = a_value
create ca_crt.make_from_separate (a_value)
end
set_ca_key (a_value: STRING)
-- Set `ca_key' with `a_value'
-- Set `ca_key' with `a_value'.
do
ca_key := a_value
ensure
ca_key_set: ca_key = a_value
create ca_key.make_from_separate (a_value)
end
set_ssl_protocol (a_version: NATURAL)

View File

@@ -12,6 +12,8 @@ class
create
make_server_by_address_and_port,
make_server_by_port,
make_client_by_address_and_port,
make_client_by_port,
make_from_separate,
make_empty
@@ -30,6 +32,16 @@ feature {NONE} -- Initialization
create {TCP_STREAM_SOCKET} socket.make_server_by_port (a_port)
end
make_client_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
do
create {TCP_STREAM_SOCKET} socket.make_client_by_address_and_port (an_address, a_port)
end
make_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING)
do
create {TCP_STREAM_SOCKET} socket.make_client_by_port (a_peer_port, a_peer_host)
end
make_from_separate (s: separate HTTPD_STREAM_SOCKET)
require
descriptor_available: s.descriptor_available
@@ -164,6 +176,11 @@ feature -- Status Report
end
end
exists: BOOLEAN
do
Result := socket.exists
end
is_blocking: BOOLEAN
do
Result := socket.is_blocking
@@ -176,6 +193,13 @@ feature -- Status Report
end
end
is_connected: BOOLEAN
do
if attached {TCP_STREAM_SOCKET} socket as l_socket then
Result := l_socket.is_connected
end
end
is_created: BOOLEAN
do
if attached {NETWORK_SOCKET} socket as l_socket then
@@ -220,6 +244,16 @@ feature -- Status Report
end
end
connect
do
socket.connect
end
close
do
socket.close
end
listen (a_queue: INTEGER)
do
socket.listen (a_queue)

View File

@@ -15,6 +15,8 @@ inherit
create
make_server_by_address_and_port,
make_server_by_port,
make_client_by_address_and_port,
make_client_by_port,
make_from_separate,
make_empty

View File

@@ -0,0 +1,20 @@
package httpd
project
httpd = "httpd-safe.ecf"
httpd = "httpd.ecf"
note
title: HTTP server
description: "[
Simple HTTP listener and handler, that can be extended easily.
]"
tags: http,httpd,server,web
collection: EWF
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)
link[license]: http://www.eiffel.com/licensing/forum.txt
link[source]: "Github" https://github.com/EiffelWebFramework/EWF/library/server/httpd
link[doc]: "Documentation" http://eiffelwebframework.github.io/EWF/
end

View File

@@ -22,7 +22,9 @@ inherit
create
make_ssl_server_by_address_and_port, make_ssl_server_by_port,
make_server_by_address_and_port, make_server_by_port
make_server_by_address_and_port, make_server_by_port,
make_ssl_client_by_address_and_port, make_ssl_client_by_port,
make_client_by_address_and_port, make_client_by_port
create {HTTPD_STREAM_SOCKET}
make
@@ -49,6 +51,26 @@ feature {NONE} -- Initialization
set_certificates (a_crt, a_key)
end
make_ssl_client_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
local
l_socket: SSL_TCP_STREAM_SOCKET
do
create l_socket.make_client_by_address_and_port (an_address, a_port)
l_socket.set_tls_protocol (a_ssl_protocol)
socket := l_socket
set_certificates (a_crt, a_key)
end
make_ssl_client_by_port (a_peer_port: INTEGER; a_peer_host: STRING; a_ssl_protocol: NATURAL; a_crt: STRING; a_key: STRING)
local
l_socket: SSL_TCP_STREAM_SOCKET
do
create l_socket.make_client_by_port (a_peer_port, a_peer_host)
l_socket.set_tls_protocol (a_ssl_protocol)
socket := l_socket
set_certificates (a_crt, a_key)
end
feature -- Output
put_readable_string_8 (s: READABLE_STRING_8)

View File

@@ -12,6 +12,7 @@ inherit
create
make_server_by_address_and_port, make_server_by_port,
make_client_by_address_and_port, make_client_by_port,
make_empty
create {SSL_NETWORK_STREAM_SOCKET}

View File

@@ -1,13 +1,3 @@
note
title: Web Server Foundation
description: Core of the Eiffel Web Framework, used to build web server application.
tags: ewf,server,httpd,request,connector
license: Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)
link[license]: https://github.com/EiffelWebFramework/EWF/blob/master/LICENSE
link[source]: "Github" https://github.com/EiffelWebFramework/EWF
link[doc]: "Documentation" http://eiffelwebframework.github.io/EWF/
end
package wsf
@@ -37,6 +27,7 @@ project
default_standalone = "default/standalone-safe.ecf"
default_standalone = "default/standalone.ecf"
note
title: Web Server Foundation
description: "[

View File

@@ -17,6 +17,7 @@
<library name="connector_libfcgi" location="..\library\server\ewsgi\connectors\libfcgi\libfcgi-safe.ecf" readonly="false"/>
<library name="connector_nino" location="..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
<library name="connector_null" location="..\library\server\ewsgi\connectors\null\null-safe.ecf" readonly="false"/>
<library name="connector_standalone" location="..\library\server\ewsgi\connectors\standalone\standalone-safe.ecf" readonly="false"/>
<library name="conneg" location="..\library\network\protocol\content_negotiation\conneg-safe.ecf" readonly="false"/>
<library name="default_cgi" location="..\library\server\wsf\default\cgi-safe.ecf" readonly="false"/>
<library name="default_libfcgi" location="..\library\server\wsf\default\libfcgi-safe.ecf" readonly="false"/>
@@ -30,6 +31,7 @@
<library name="filter" location="..\examples\filter\filter-safe.ecf" readonly="false"/>
<library name="hello_world" location="..\library\server\ewsgi\examples\hello_world\hello-safe.ecf" readonly="false"/>
<library name="http" location="..\library\network\protocol\http\http-safe.ecf" readonly="false"/>
<library name="httpd" location="..\library\server\httpd\httpd-safe.ecf" readonly="false"/>
<library name="http_authorization" location="..\library\server\authentication\http_authorization\http_authorization-safe.ecf" readonly="false"/>
<library name="http_client" location="..\library\network\http_client\http_client-safe.ecf" readonly="false"/>
<library name="libfcgi" location="..\library\server\libfcgi\libfcgi-safe.ecf" readonly="false"/>

View File

@@ -1,14 +1,15 @@
<?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_dev" uuid="7C9887BD-4AE4-47F2-A0AA-4BBB6736D433">
<target name="hello_dev" abstract="true">
<root class="HELLO_ROUTED_WORLD" feature="make"/>
<root class="HELLO_ROUTED_WORLD" feature="make_and_launch"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
<debug name="nino" enabled="true"/>
<debug name="standalone" enabled="true"/>
<debug name="ew_standalone" enabled="true"/>
<assertions precondition="true" postcondition="true" check="true" invariant="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="thread"/>
@@ -16,20 +17,20 @@
<library name="http" location="../../library/network/protocol/http/http-safe.ecf" readonly="false"/>
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
</target>
<target name="hello_nino" extends="hello_connector">
<target name="hello_standalone" extends="hello_dev">
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
<debug name="nino" enabled="true"/>
<debug name="standalone" 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" readonly="false" use_application_options="true"/>
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone-safe.ecf" readonly="false" use_application_options="true"/>
<cluster name="src" location="src\" recursive="true"/>
<override name="override" location="override\" recursive="true"/>
</target>
<target name="hello_cgi" extends="hello_connector">
<target name="hello_cgi" extends="hello_dev">
<library name="default_cgi" location="..\..\library\server\wsf\default\cgi-safe.ecf"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
<target name="hello_libfcgi" extends="hello_connector">
<target name="hello_libfcgi" extends="hello_dev">
<library name="default_libfcgi" location="..\..\library\server\wsf\default\libfcgi-safe.ecf"/>
<cluster name="src" location="src\" recursive="true"/>
</target>

View File

@@ -8,243 +8,24 @@ class
HELLO_ROUTED_WORLD
inherit
WSF_URI_TEMPLATE_ROUTED_SERVICE
WSF_HANDLER_HELPER
WSF_DEFAULT_SERVICE
WSF_DEFAULT_SERVICE [HELLO_ROUTED_WORLD_EXECUTION]
redefine
initialize
end
create
make
make_and_launch
feature {NONE} -- Initialization
make
initialize
do
initialize_router
Precursor
set_service_option ("port", 8099)
make_and_launch
end
create_router
do
create router.make (5)
end
setup_router
local
ra: WSF_AGENT_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
hello: WSF_URI_TEMPLATE_ROUTING_HANDLER
www: WSF_FILE_SYSTEM_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
do
router.map_agent ("/refresh", agent execute_refresh)
router.map_agent ("/home", agent execute_home)
create www.make (document_root)
www.set_directory_index (<<"index.html">>)
router.map ("/www{/path}{?query}", www)
--| Map all "/hello*" using a ROUTING_HANDLER
create hello.make (3)
router.map ("/hello", hello)
create ra.make (agent handle_hello)
hello.map ("/hello/{name}.{format}", ra)
hello.map ("/hello.{format}/{name}", ra)
hello.map ("/hello/{name}", ra)
create ra.make (agent handle_anonymous_hello)
hello.map ("/hello", ra)
hello.map ("/hello.{format}", ra)
--| Various various route, directly on the "router"
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
document_root: READABLE_STRING_8
local
e: EXECUTION_ENVIRONMENT
dn: DIRECTORY_NAME
once
create e
create dn.make_from_string (e.current_working_directory)
dn.extend ("htdocs")
Result := dn.string
if Result[Result.count] = Operating_environment.directory_separator then
Result := Result.substring (1, Result.count - 1)
end
end
feature -- Execution
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
local
l_url: STRING
do
l_url := req.absolute_script_url ("/home")
res.redirect_now_with_content (l_url, "You are now being redirected to " + l_url, {HTTP_MIME_TYPES}.text_html)
end
execute_refresh (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
local
h: HTTP_HEADER
l_url: STRING
e: EXECUTION_ENVIRONMENT
n: INTEGER
i: INTEGER
s: STRING_8
do
l_url := req.absolute_script_url ("/home")
n := 3
create h.make
h.put_refresh (l_url, 5)
h.put_location (l_url)
h.put_content_type_text_plain
h.put_transfer_encoding_chunked
-- h.put_content_length (0)
-- res.set_status_code ({HTTP_STATUS_CODE}.moved_permanently)
res.set_status_code ({HTTP_STATUS_CODE}.ok)
res.put_header_text (h.string)
from
create e
create s.make (255)
until
n = 0
loop
if n > 1 then
s.append ("%NRedirected to " + l_url + " in " + n.out + " seconds :%N")
else
s.append ("%NRedirected to " + l_url + " in 1 second :%N")
end
res.put_chunk (s, Void); s.wipe_out
from
i := 1
until
i = 1001
loop
s.append_character ('.')
if i \\ 100 = 0 then
s.append_character ('%N')
end
res.put_chunk (s, Void); s.wipe_out
e.sleep (1_000_000)
i := i + 1
end
n := n - 1
end
s.append ("%NYou are now being redirected...%N")
res.put_chunk (s, Void); s.wipe_out
res.put_chunk_end
end
execute_home (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
local
l_body: STRING_8
do
create l_body.make (255)
l_body.append ("<html><body>Hello World ?!%N")
l_body.append ("<h3>Please try the following links</h3><ul>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/") + "%">default</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/refresh") + "%">redirect using refresh and chunked encoding</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello") + "%">/hello</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello.html/Joce") + "%">/hello.html/Joce</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello.json/Joce") + "%">/hello.json/Joce</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce.html") + "%">/hello/Joce.html</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce.xml") + "%">/hello/Joce.xml</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce") + "%">/hello/Joce</a></li>%N")
l_body.append ("</ul>%N")
if attached req.item ("REQUEST_COUNT") as rqc then
l_body.append ("request #"+ rqc.as_string.string + "%N")
end
l_body.append ("</body></html>%N")
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_body.count.out]>>)
res.put_string (l_body)
end
execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE; a_name: detachable READABLE_STRING_32; ctx: WSF_HANDLER_CONTEXT)
local
l_response_content_type: detachable STRING
h: HTTP_HEADER
content_type_supported: ARRAY [STRING]
l_body: STRING_8
do
if a_name /= Void then
l_body := "Hello %"" + a_name + "%" !%N"
else
l_body := "Hello anonymous visitor !%N"
end
content_type_supported := <<{HTTP_MIME_TYPES}.application_json, {HTTP_MIME_TYPES}.text_html, {HTTP_MIME_TYPES}.text_xml, {HTTP_MIME_TYPES}.text_plain>>
inspect ctx.request_format_id ("format", content_type_supported)
when {HTTP_FORMAT_CONSTANTS}.json then
l_response_content_type := {HTTP_MIME_TYPES}.application_json
l_body := "{%N%"application%": %"/hello%",%N %"message%": %"" + l_body + "%" %N}"
when {HTTP_FORMAT_CONSTANTS}.html then
l_response_content_type := {HTTP_MIME_TYPES}.text_html
when {HTTP_FORMAT_CONSTANTS}.xml then
l_response_content_type := {HTTP_MIME_TYPES}.text_xml
l_body := "<response><application>/hello</application><message>" + l_body + "</message></response>%N"
when {HTTP_FORMAT_CONSTANTS}.text then
l_response_content_type := {HTTP_MIME_TYPES}.text_plain
else
execute_content_type_not_allowed (req, res, content_type_supported,
<<{HTTP_FORMAT_CONSTANTS}.json_name, {HTTP_FORMAT_CONSTANTS}.html_name, {HTTP_FORMAT_CONSTANTS}.xml_name, {HTTP_FORMAT_CONSTANTS}.text_name>>
)
end
if l_response_content_type /= Void then
create h.make
h.put_content_type (l_response_content_type)
h.put_content_length (l_body.count)
res.set_status_code ({HTTP_STATUS_CODE}.ok)
res.put_header_text (h.string)
res.put_string (l_body)
end
end
handle_hello (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, ctx.string_parameter ("name"), ctx)
end
handle_anonymous_hello (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, ctx.string_parameter ("name"), ctx)
end
handle_method_any (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, req.request_method, ctx)
end
handle_method_get (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, "GET", ctx)
end
handle_method_post (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, "POST", ctx)
end
handle_method_get_or_post (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, "GET or POST", ctx)
end
note
copyright: "2011-2011, Eiffel Software and others"
copyright: "2011-2016, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -0,0 +1,272 @@
note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
HELLO_ROUTED_WORLD_EXECUTION
inherit
WSF_ROUTED_EXECUTION
redefine
execute_default
end
WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION
create
make
feature {NONE} -- Initialization
setup_router
local
ra: WSF_URI_TEMPLATE_AGENT_HANDLER
hello: WSF_URI_TEMPLATE_ROUTING_HANDLER
www: WSF_FILE_SYSTEM_HANDLER
do
map_uri_template_agent ("/refresh", agent execute_refresh, Void)
map_uri_template_agent ("/home", agent execute_home, Void)
create www.make (document_root)
www.set_directory_index (<<"index.html">>)
router.handle ("/www{/path}{?query}", www, Void)
--| Map all "/hello*" using a ROUTING_HANDLER
create hello.make (3)
router.handle ("/hello", hello, Void)
create ra.make (agent handle_hello)
hello.router.handle ("/hello/{name}.{format}", ra, Void)
hello.router.handle ("/hello.{format}/{name}", ra, Void)
hello.router.handle ("/hello/{name}", ra, Void)
create ra.make (agent handle_anonymous_hello)
hello.router.handle ("/hello", ra, Void)
hello.router.handle ("/hello.{format}", ra, Void)
--| Various various route, directly on the "router"
map_uri_template_agent ("/method/any", agent handle_method_any, Void)
map_uri_template_agent ("/method/guess", agent handle_method_get_or_post, <<"GET", "POST">>)
map_uri_template_agent ("/method/custom", agent handle_method_get, <<"GET">>)
map_uri_template_agent ("/method/custom", agent handle_method_post, <<"POST">>)
end
document_root: READABLE_STRING_8
local
e: EXECUTION_ENVIRONMENT
dn: DIRECTORY_NAME
once
create e
create dn.make_from_string (e.current_working_directory)
dn.extend ("htdocs")
Result := dn.string
if Result[Result.count] = Operating_environment.directory_separator then
Result := Result.substring (1, Result.count - 1)
end
end
feature -- Execution
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
local
l_url: STRING
do
l_url := req.absolute_script_url ("/home")
res.redirect_now_with_content (l_url, "You are now being redirected to " + l_url, {HTTP_MIME_TYPES}.text_html)
end
execute_refresh (req: WSF_REQUEST; res: WSF_RESPONSE) --ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT;
local
h: HTTP_HEADER
l_url: STRING
e: EXECUTION_ENVIRONMENT
n: INTEGER
i: INTEGER
s: STRING_8
do
l_url := req.absolute_script_url ("/home")
n := 3
create h.make
h.put_refresh (l_url, 5)
h.put_location (l_url)
h.put_content_type_text_plain
h.put_transfer_encoding_chunked
-- h.put_content_length (0)
-- res.set_status_code ({HTTP_STATUS_CODE}.moved_permanently)
res.set_status_code ({HTTP_STATUS_CODE}.ok)
res.put_header_text (h.string)
from
create e
create s.make (255)
until
n = 0
loop
if n > 1 then
s.append ("%NRedirected to " + l_url + " in " + n.out + " seconds :%N")
else
s.append ("%NRedirected to " + l_url + " in 1 second :%N")
end
res.put_chunk (s, Void); s.wipe_out
from
i := 1
until
i = 1001
loop
s.append_character ('.')
if i \\ 100 = 0 then
s.append_character ('%N')
end
res.put_chunk (s, Void); s.wipe_out
e.sleep (1_000_000)
i := i + 1
end
n := n - 1
end
s.append ("%NYou are now being redirected...%N")
res.put_chunk (s, Void); s.wipe_out
res.put_chunk_end
end
execute_home (req: WSF_REQUEST; res: WSF_RESPONSE) -- ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT;
local
l_body: STRING_8
do
create l_body.make (255)
l_body.append ("<html><body>Hello World ?!%N")
l_body.append ("<h3>Please try the following links</h3><ul>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/") + "%">default</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/refresh") + "%">redirect using refresh and chunked encoding</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello") + "%">/hello</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello.html/Joce") + "%">/hello.html/Joce</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello.json/Joce") + "%">/hello.json/Joce</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce.html") + "%">/hello/Joce.html</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce.xml") + "%">/hello/Joce.xml</a></li>%N")
l_body.append ("<li><a href=%""+ req.script_url ("/hello/Joce") + "%">/hello/Joce</a></li>%N")
l_body.append ("</ul>%N")
if attached req.item ("REQUEST_COUNT") as rqc then
l_body.append ("request #"+ rqc.as_string.url_encoded_value + "%N")
end
l_body.append ("</body></html>%N")
res.put_header ({HTTP_STATUS_CODE}.ok, <<["Content-Type", "text/html"], ["Content-Length", l_body.count.out]>>)
res.put_string (l_body)
end
execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE; a_name: detachable READABLE_STRING_32)
local
l_response_content_type: detachable STRING
h: HTTP_HEADER
content_type_supported: ARRAY [STRING]
l_body: STRING_8
l_format: detachable READABLE_STRING_GENERAL
l_http_format_constants: HTTP_FORMAT_CONSTANTS
do
if a_name /= Void then
l_body := "Hello %"" + a_name + "%" !%N"
else
l_body := "Hello anonymous visitor !%N"
end
content_type_supported := <<{HTTP_MIME_TYPES}.application_json, {HTTP_MIME_TYPES}.text_html, {HTTP_MIME_TYPES}.text_xml, {HTTP_MIME_TYPES}.text_plain>>
if attached {WSF_STRING} req.path_parameter ("format") as s_format then
l_format := s_format.value
end
if l_format = Void then
across
content_type_supported as ic
until
l_format /= Void
loop
if req.is_content_type_accepted (ic.item) then
l_format := ic.item
end
end
end
if l_format /= Void then
create l_http_format_constants
inspect
l_http_format_constants.format_id (l_format)
when {HTTP_FORMAT_CONSTANTS}.json then
l_response_content_type := {HTTP_MIME_TYPES}.application_json
l_body := "{%N%"application%": %"/hello%",%N %"message%": %"" + l_body + "%" %N}"
when {HTTP_FORMAT_CONSTANTS}.html then
l_response_content_type := {HTTP_MIME_TYPES}.text_html
when {HTTP_FORMAT_CONSTANTS}.xml then
l_response_content_type := {HTTP_MIME_TYPES}.text_xml
l_body := "<response><application>/hello</application><message>" + l_body + "</message></response>%N"
when {HTTP_FORMAT_CONSTANTS}.text then
l_response_content_type := {HTTP_MIME_TYPES}.text_plain
else
l_response_content_type := Void
end
end
if l_response_content_type /= Void then
create h.make
h.put_content_type (l_response_content_type)
h.put_content_length (l_body.count)
res.set_status_code ({HTTP_STATUS_CODE}.ok)
res.put_header_text (h.string)
res.put_string (l_body)
else
res.send (create {WSF_PRECONDITION_FAILED_MESSAGE}.make (req)) -- FIXME: better error message!
end
end
string_path_parameter (req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable STRING_32
do
if attached {WSF_STRING} req.path_parameter (a_name) as s then
Result := s.value
end
end
handle_hello (req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, string_path_parameter (req, "name"))
end
handle_anonymous_hello (req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, string_path_parameter (req, "name"))
end
handle_method_any (req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, req.request_method)
end
handle_method_get (req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, "GET")
end
handle_method_post (req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, "POST")
end
handle_method_get_or_post (req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute_hello (req, res, "GET or POST")
end
note
copyright: "2011-2016, 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