Compare commits
59 Commits
2012-03-14
...
v0.1.b1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34c6288032 | ||
|
|
21b03a05fd | ||
|
|
0bd2d16c12 | ||
|
|
e6a727ee42 | ||
|
|
1403cc5c09 | ||
|
|
3bbf356f19 | ||
|
|
b541efcc8f | ||
|
|
082def2b70 | ||
|
|
79607600e6 | ||
|
|
0b6b7f793c | ||
|
|
badc2458c4 | ||
|
|
d4208c59f3 | ||
|
|
4bafa5b3c0 | ||
|
|
c89b19371e | ||
|
|
10ebc12852 | ||
|
|
593e48ec5b | ||
|
|
11b15ec5b7 | ||
|
|
ff713a42ab | ||
|
|
155c45be6c | ||
|
|
09fa1adaab | ||
|
|
425c276051 | ||
|
|
0040e4b0d0 | ||
|
|
b862065c04 | ||
|
|
874677ab7a | ||
|
|
ed200b93dd | ||
|
|
bcccfb22ed | ||
|
|
5c98d7ba4e | ||
|
|
40c6aff423 | ||
|
|
ac9cbb0bd2 | ||
|
|
95c3bbf6e5 | ||
|
|
b955912dc2 | ||
|
|
50223b12f7 | ||
|
|
6c7ba93062 | ||
|
|
743f26c376 | ||
|
|
d256ec3944 | ||
|
|
482f8e41e7 | ||
|
|
9eef812795 | ||
|
|
86fcaa2835 | ||
|
|
897aeb3132 | ||
|
|
48acdea73c | ||
|
|
cbaae12156 | ||
|
|
8344607eb6 | ||
|
|
71d5dc4795 | ||
|
|
3f0b745ecc | ||
|
|
3432e2d8b2 | ||
|
|
fea0f115a0 | ||
|
|
84a12447db | ||
|
|
876f9e02b7 | ||
|
|
e5323dd208 | ||
|
|
77834a3dd8 | ||
|
|
4906345a62 | ||
|
|
487487ad44 | ||
|
|
ef5ba19c46 | ||
|
|
b05ff01262 | ||
|
|
9f1940c46d | ||
|
|
f69ff42564 | ||
|
|
eb3e9f2186 | ||
|
|
03b10bdc14 | ||
|
|
46eb92ac37 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
EIFGENs
|
||||
tests/temp/
|
||||
.svn/
|
||||
*.swp
|
||||
|
||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,12 +1,12 @@
|
||||
[submodule "doc/wiki"]
|
||||
path = doc/wiki
|
||||
url = https://github.com/Eiffel-World/Eiffel-Web-Framework.wiki.git
|
||||
url = https://github.com/EiffelWebFramework/EWF.wiki.git
|
||||
[submodule "contrib/library/server/nino"]
|
||||
path = contrib/library/server/nino
|
||||
url = https://github.com/Eiffel-World/EiffelWebNino.git
|
||||
[submodule "contrib/library/text/parser/json"]
|
||||
path = contrib/library/text/parser/json
|
||||
url = https://github.com/Eiffel-World/ejson-svn.git
|
||||
url = https://github.com/Eiffel-World/json.git
|
||||
[submodule "contrib/ise_library/cURL"]
|
||||
path = contrib/ise_library/cURL
|
||||
url = https://github.com/EiffelSoftware/mirror-Eiffel-cURL.git
|
||||
|
||||
10
README.md
10
README.md
@@ -5,11 +5,11 @@
|
||||
|
||||
Official project site for Eiffel Web Framework:
|
||||
|
||||
* http://eiffel-world.github.com/Eiffel-Web-Framework/
|
||||
* http://eiffelwebframework.github.com/EWF/
|
||||
|
||||
For more information please have a look at the related wiki:
|
||||
|
||||
* https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki
|
||||
* https://github.com/EiffelWebFramework/EWF/wiki
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -20,10 +20,10 @@ For more information please have a look at the related wiki:
|
||||
## How to get the source code?
|
||||
|
||||
Using git version >= 1.6.5
|
||||
* git clone --recursive https://github.com/Eiffel-World/Eiffel-Web-Framework.git
|
||||
* git clone --recursive https://github.com/EiffelWebFramework/EWF.git
|
||||
|
||||
Otherwise, try
|
||||
* git clone https://github.com/Eiffel-World/Eiffel-Web-Framework.git
|
||||
* git clone https://github.com/EiffelWebFramework/EWF.git
|
||||
* cd Eiffel-Web-Framework
|
||||
* git submodule update --init
|
||||
* git submodule foreach --recursive git checkout master
|
||||
@@ -77,4 +77,4 @@ An alternative to the last 2 instructions is to use the script from tools folder
|
||||
|
||||
|
||||
For more information please have a look at the related wiki:
|
||||
* https://github.com/Eiffel-World/Eiffel-Web-Framework/wiki
|
||||
* https://github.com/EiffelWebFramework/EWF/wiki
|
||||
|
||||
Submodule contrib/library/text/parser/json updated: 769bb7d161...c873d62efa
@@ -11,6 +11,7 @@
|
||||
</option>
|
||||
<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="wsf_extension" location="..\..\..\..\..\library\server\wsf_extension\wsf_extension-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\..\..\..\library\protocol\http\http-safe.ecf"/>
|
||||
<library name="uri_template" location="..\..\..\..\..\library\protocol\uri_template\uri_template-safe.ecf"/>
|
||||
<cluster name="contrib" location=".\src\contrib\" recursive="true">
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<option warning="true" full_class_checking="true"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="wsf" location="..\..\..\..\..\library\server\wsf\wsf.ecf"/>
|
||||
<library name="wsf_extension" location="..\..\..\..\..\library\server\wsf_extension\wsf_extension.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\..\..\..\library\protocol\http\http.ecf"/>
|
||||
<library name="uri_template" location="..\..\..\..\..\library\protocol\uri_template\uri_template.ecf"/>
|
||||
<cluster name="contrib" location=".\src\contrib\" recursive="true">
|
||||
|
||||
@@ -34,6 +34,13 @@ feature -- Access
|
||||
do
|
||||
end
|
||||
|
||||
resource_value (ctx: C): detachable READABLE_STRING_32
|
||||
do
|
||||
if attached {WSF_STRING} ctx.item ("resource") as s then
|
||||
Result := s.string
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
@@ -50,8 +57,7 @@ feature -- Execution
|
||||
create s.make_empty
|
||||
|
||||
if
|
||||
attached {WSF_STRING} ctx.path_parameter ("resource") as l_resource_value and then
|
||||
attached l_resource_value.string as l_resource
|
||||
attached resource_value (ctx) as l_resource
|
||||
then
|
||||
from
|
||||
hdl_cursor := router.new_cursor
|
||||
@@ -309,7 +315,7 @@ feature -- Access
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -8,7 +8,7 @@ class
|
||||
REST_REQUEST_AGENT_HANDLER [C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
inherit
|
||||
REQUEST_AGENT_HANDLER [C]
|
||||
WSF_AGENT_HANDLER [C]
|
||||
rename
|
||||
execute as execute_application
|
||||
end
|
||||
|
||||
@@ -8,7 +8,9 @@ deferred class
|
||||
REST_REQUEST_HANDLER [C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
inherit
|
||||
REQUEST_HANDLER [C]
|
||||
WSF_HANDLER [C]
|
||||
|
||||
WSF_HANDLER_HELPER
|
||||
|
||||
feature -- Access
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ deferred class
|
||||
REST_REQUEST_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
REQUEST_HANDLER_CONTEXT
|
||||
WSF_HANDLER_CONTEXT
|
||||
|
||||
feature -- Accept: Content-Type
|
||||
|
||||
@@ -73,7 +73,7 @@ feature -- Format
|
||||
request_accepted_format (a_format_variable_name: detachable READABLE_STRING_8; a_supported_content_types: detachable ARRAY [READABLE_STRING_8]): detachable READABLE_STRING_8
|
||||
-- Format id for the request based on {HTTP_FORMAT_CONSTANTS}
|
||||
do
|
||||
if a_format_variable_name /= Void and then attached string_parameter (a_format_variable_name) as ctx_format then
|
||||
if a_format_variable_name /= Void and then attached string_item (a_format_variable_name) as ctx_format then
|
||||
Result := ctx_format.as_string_8
|
||||
else
|
||||
Result := request_format_from_content_type (request_accepted_content_type (a_supported_content_types))
|
||||
|
||||
@@ -8,7 +8,7 @@ deferred class
|
||||
REST_REQUEST_ROUTER [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
inherit
|
||||
REQUEST_ROUTER [H, C]
|
||||
WSF_ROUTER [H, C]
|
||||
|
||||
;note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
|
||||
@@ -8,7 +8,7 @@ deferred class
|
||||
REST_SERVICE_I [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_HANDLER_CONTEXT]
|
||||
|
||||
inherit
|
||||
ROUTED_SERVICE_I [H, C]
|
||||
WSF_ROUTED_SERVICE_I [H, C]
|
||||
redefine
|
||||
router
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {REQUEST_URI_HANDLER_CONTEXT}."
|
||||
description: "Summary description for {WSF_URI_HANDLER_CONTEXT}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
@@ -8,7 +8,7 @@ class
|
||||
REST_REQUEST_URI_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
REQUEST_URI_HANDLER_CONTEXT
|
||||
WSF_URI_HANDLER_CONTEXT
|
||||
|
||||
REST_REQUEST_HANDLER_CONTEXT
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class
|
||||
REST_REQUEST_URI_ROUTER_I [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_URI_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
REQUEST_URI_ROUTER_I [H, C]
|
||||
WSF_URI_ROUTER_I [H, C]
|
||||
|
||||
REST_REQUEST_ROUTER [H, C]
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {REQUEST_ROUTING_HANDLER}."
|
||||
description: "Summary description for {WSF_ROUTING_HANDLER }."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
@@ -9,7 +9,7 @@ class
|
||||
C -> REST_REQUEST_URI_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
REQUEST_URI_ROUTING_HANDLER_I [H, C]
|
||||
WSF_URI_ROUTING_HANDLER_I [H, C]
|
||||
redefine
|
||||
router,
|
||||
execute
|
||||
@@ -38,7 +38,7 @@ feature -- Execution
|
||||
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
Precursor {REQUEST_URI_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
Precursor {WSF_URI_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
end
|
||||
|
||||
execute_application (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {REQUEST_URI_TEMPLATE_HANDLER_CONTEXT}."
|
||||
description: "Summary description for {WSF_URI_TEMPLATE_HANDLER_CONTEXT}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
@@ -8,7 +8,7 @@ class
|
||||
REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT
|
||||
|
||||
inherit
|
||||
REQUEST_URI_TEMPLATE_HANDLER_CONTEXT
|
||||
WSF_URI_TEMPLATE_HANDLER_CONTEXT
|
||||
|
||||
REST_REQUEST_HANDLER_CONTEXT
|
||||
|
||||
@@ -16,7 +16,7 @@ create
|
||||
make
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -8,7 +8,7 @@ class
|
||||
REST_REQUEST_URI_TEMPLATE_ROUTER_I [H -> REST_REQUEST_HANDLER [C], C -> REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
REQUEST_URI_TEMPLATE_ROUTER_I [H, C]
|
||||
WSF_URI_TEMPLATE_ROUTER_I [H, C]
|
||||
|
||||
REST_REQUEST_ROUTER [H, C]
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {REQUEST_ROUTING_HANDLER}."
|
||||
description: "Summary description for {WSF_ROUTING_HANDLER }."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
@@ -9,7 +9,7 @@ class
|
||||
C -> REST_REQUEST_URI_TEMPLATE_HANDLER_CONTEXT create make end]
|
||||
|
||||
inherit
|
||||
REQUEST_URI_TEMPLATE_ROUTING_HANDLER_I [H, C]
|
||||
WSF_URI_TEMPLATE_ROUTING_HANDLER_I [H, C]
|
||||
redefine
|
||||
router,
|
||||
execute
|
||||
@@ -40,7 +40,7 @@ feature -- Execution
|
||||
execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
pre_execute (ctx, req, res)
|
||||
Precursor {REQUEST_URI_TEMPLATE_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
Precursor {WSF_URI_TEMPLATE_ROUTING_HANDLER_I} (ctx, req, res)
|
||||
post_execute (ctx, req, res)
|
||||
end
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ feature -- Execution
|
||||
s.append_string (" format=" + l_format + "%N")
|
||||
end
|
||||
|
||||
if attached ctx.string_parameter ("op") as l_op then
|
||||
if attached ctx.string_item ("op") as l_op then
|
||||
s.append_string (" op=" + l_op)
|
||||
if l_op.same_string ("crash") then
|
||||
(create {DEVELOPER_EXCEPTION}).raise
|
||||
|
||||
@@ -50,7 +50,6 @@ feature {NONE} -- Handlers
|
||||
|
||||
create gh.make (4)
|
||||
router.map ("/test", gh)
|
||||
gh.map_default (h)
|
||||
-- gh.map ("/test", h)
|
||||
gh.map ("/test/{op}", h)
|
||||
gh.map ("/test.{format}", h)
|
||||
|
||||
@@ -10,7 +10,7 @@ feature -- Access
|
||||
local
|
||||
cgi: WGI_CGI_CONNECTOR
|
||||
do
|
||||
create cgi.make (Current)
|
||||
create cgi.make (to_wgi_service)
|
||||
cgi.launch
|
||||
end
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ feature -- Access
|
||||
local
|
||||
libfcgi: WGI_LIBFCGI_CONNECTOR
|
||||
do
|
||||
create libfcgi.make (Current)
|
||||
create libfcgi.make (to_wgi_service)
|
||||
libfcgi.launch
|
||||
end
|
||||
end
|
||||
|
||||
gateway_name: STRING = "libFCGI"
|
||||
|
||||
@@ -20,7 +20,7 @@ feature -- Access
|
||||
do
|
||||
(create {EXCEPTIONS}).die (a_code)
|
||||
end
|
||||
|
||||
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
|
||||
@@ -18,7 +18,7 @@ feature -- Access
|
||||
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")
|
||||
end
|
||||
create app.make_custom (agent wgi_execute, base_url)
|
||||
create app.make_custom (to_wgi_service, base_url)
|
||||
app.force_single_threaded
|
||||
|
||||
app.listen (port_number)
|
||||
|
||||
@@ -84,7 +84,7 @@ feature -- Helpers
|
||||
end
|
||||
rep_data.set_message (s)
|
||||
end
|
||||
rep_data.send (res)
|
||||
res.send (rep_data)
|
||||
rep_data.recycle
|
||||
end
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<library name="json" location="..\..\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="uri_template" location="..\..\library\protocol\uri_template\uri_template-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="false"/>
|
||||
<library name="wsf_extension" location="..\..\library\server\wsf_extension\wsf_extension-safe.ecf" readonly="false"/>
|
||||
<cluster name="src" location="src\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -5,10 +5,10 @@ note
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ORDER_HANDLER [C -> REQUEST_HANDLER_CONTEXT]
|
||||
ORDER_HANDLER [C -> WSF_HANDLER_CONTEXT]
|
||||
inherit
|
||||
REQUEST_HANDLER [C]
|
||||
REQUEST_RESOURCE_HANDLER_HELPER [C]
|
||||
WSF_HANDLER [C]
|
||||
WSF_RESOURCE_HANDLER_HELPER [C]
|
||||
redefine
|
||||
do_get,
|
||||
do_post,
|
||||
@@ -82,7 +82,6 @@ feature -- HTTP Methods
|
||||
do
|
||||
create h.make
|
||||
create etag_utils
|
||||
h.put_status ({HTTP_STATUS_CODE}.ok)
|
||||
h.put_content_type_application_json
|
||||
if attached {JSON_VALUE} json.value (l_order) as jv then
|
||||
l_msg := jv.representation
|
||||
@@ -166,7 +165,6 @@ feature -- HTTP Methods
|
||||
json.add_converter(joc)
|
||||
|
||||
create h.make
|
||||
h.put_status ({HTTP_STATUS_CODE}.ok)
|
||||
h.put_content_type_application_json
|
||||
if attached req.request_time as time then
|
||||
h.add_header ("Date:" +time.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
@@ -212,10 +210,9 @@ feature -- HTTP Methods
|
||||
h : HTTP_HEADER
|
||||
do
|
||||
create h.make
|
||||
h.put_status ({HTTP_STATUS_CODE}.no_content)
|
||||
h.put_content_type_application_json
|
||||
if attached req.request_time as time then
|
||||
h.put_utc_date (time)
|
||||
h.put_utc_date (time)
|
||||
end
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.no_content)
|
||||
res.put_header_text (h.string)
|
||||
@@ -254,7 +251,6 @@ feature -- HTTP Methods
|
||||
create joc.make
|
||||
json.add_converter(joc)
|
||||
|
||||
h.put_status ({HTTP_STATUS_CODE}.created)
|
||||
h.put_content_type_application_json
|
||||
if attached {JSON_VALUE} json.value (l_order) as jv then
|
||||
l_msg := jv.representation
|
||||
|
||||
@@ -10,9 +10,11 @@ class
|
||||
inherit
|
||||
ANY
|
||||
|
||||
URI_TEMPLATE_ROUTED_SERVICE
|
||||
WSF_URI_TEMPLATE_ROUTED_SERVICE
|
||||
|
||||
ROUTED_SERVICE_HELPER
|
||||
WSF_HANDLER_HELPER
|
||||
|
||||
WSF_DEFAULT_SERVICE
|
||||
|
||||
create
|
||||
make
|
||||
@@ -20,13 +22,13 @@ create
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
local
|
||||
s: DEFAULT_SERVICE_LAUNCHER
|
||||
do
|
||||
initialize_router
|
||||
create s.make_and_launch_with_options (agent execute, <<["port", 9090]>>)
|
||||
set_service_option ("port", 9090)
|
||||
make_and_launch
|
||||
end
|
||||
|
||||
|
||||
create_router
|
||||
do
|
||||
create router.make (2)
|
||||
@@ -34,7 +36,7 @@ feature {NONE} -- Initialization
|
||||
|
||||
setup_router
|
||||
local
|
||||
order_handler: ORDER_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
order_handler: ORDER_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
do
|
||||
create order_handler
|
||||
router.map_with_request_methods ("/order", order_handler, <<"POST">>)
|
||||
@@ -56,7 +58,6 @@ feature -- Execution
|
||||
req.input.read_string (req.content_length_value.as_integer_32)
|
||||
end
|
||||
create h.make
|
||||
h.put_status ({HTTP_STATUS_CODE}.method_not_allowed)
|
||||
h.put_content_type_text_plain
|
||||
l_api_doc := "%NPlease check the API%NURI:/order METHOD: POST%NURI:/order/{orderid} METHOD: GET, PUT, DELETE%N"
|
||||
l_description := req.request_method + req.request_uri + " is not allowed" + "%N" + l_api_doc
|
||||
|
||||
@@ -6,19 +6,14 @@ note
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_SERVICE
|
||||
|
||||
create
|
||||
make
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Run application.
|
||||
local
|
||||
s: DEFAULT_SERVICE_LAUNCHER
|
||||
do
|
||||
create s.make_and_launch (agent execute)
|
||||
end
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
-- To send a response we need to setup, the status code and
|
||||
|
||||
@@ -1,20 +1,48 @@
|
||||
<?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="simple" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486">
|
||||
<target name="simple">
|
||||
<root class="APPLICATION" feature="make"/>
|
||||
|
||||
<target name="common" abstract="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf"/>
|
||||
<library name="http" location="..\..\library\protocol\http\http-safe.ecf"/>
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||
<cluster name="simple" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
|
||||
<target name="simple_nino" extends="common">
|
||||
<root class="APPLICATION" feature="make_and_launch"/>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf"/>
|
||||
<cluster name="simple" location=".\" recursive="true"/>
|
||||
</target>
|
||||
|
||||
<target name="simple_cgi" extends="common">
|
||||
<root class="APPLICATION" feature="make_and_launch"/>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="default_cgi" location="..\..\library\server\wsf\default\cgi-safe.ecf"/>
|
||||
<cluster name="simple" location=".\" recursive="true"/>
|
||||
</target>
|
||||
|
||||
<target name="simple_libfcgi" extends="common">
|
||||
<root class="APPLICATION" feature="make_and_launch"/>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="default_libfcgi" location="..\..\library\server\wsf\default\libfcgi-safe.ecf"/>
|
||||
<cluster name="simple" location=".\" recursive="true"/>
|
||||
</target>
|
||||
|
||||
<target name="simple" extends="simple_nino">
|
||||
</target>
|
||||
|
||||
</system>
|
||||
|
||||
@@ -6,19 +6,14 @@ note
|
||||
class
|
||||
SERVICE_FILE
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_SERVICE
|
||||
|
||||
create
|
||||
make
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Run application.
|
||||
local
|
||||
s: DEFAULT_SERVICE_LAUNCHER
|
||||
do
|
||||
create s.make_and_launch (agent execute)
|
||||
end
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
f: WSF_FILE_RESPONSE
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?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="service_file" uuid="C28C4F53-9963-46C0-A080-8F13E94E7486">
|
||||
<target name="service_file">
|
||||
<root class="SERVICE_FILE" feature="make"/>
|
||||
<root class="SERVICE_FILE" feature="make_and_launch"/>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
|
||||
@@ -10,9 +10,9 @@ class
|
||||
inherit
|
||||
ANY
|
||||
|
||||
URI_TEMPLATE_ROUTED_SERVICE
|
||||
WSF_URI_TEMPLATE_ROUTED_SERVICE
|
||||
|
||||
ROUTED_SERVICE_HELPER
|
||||
WSF_DEFAULT_SERVICE
|
||||
|
||||
create
|
||||
make
|
||||
@@ -21,13 +21,14 @@ feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize Current
|
||||
local
|
||||
s: DEFAULT_SERVICE_LAUNCHER
|
||||
do
|
||||
initialize_router
|
||||
create s.make_and_launch (agent execute)
|
||||
-- Use the following line to use particular port number (as 9090) with Nino connector
|
||||
-- create s.make_and_launch_with_options (agent execute, <<["port", 9090]>>)
|
||||
|
||||
|
||||
-- To use particular port number (as 9090) with Nino connector
|
||||
-- Uncomment the following line
|
||||
-- set_service_option ("port", 9090)
|
||||
make_and_launch
|
||||
end
|
||||
|
||||
create_router
|
||||
@@ -39,7 +40,7 @@ feature {NONE} -- Initialization
|
||||
setup_router
|
||||
-- Setup router
|
||||
local
|
||||
www: REQUEST_FILE_SYSTEM_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
www: WSF_FILE_SYSTEM_HANDLER [WSF_URI_TEMPLATE_HANDLER_CONTEXT]
|
||||
do
|
||||
router.map_agent ("/upload{?nb}", agent execute_upload)
|
||||
|
||||
@@ -84,13 +85,13 @@ feature -- Execution
|
||||
res.redirect_now_with_content (req.script_url ("/"), "Redirection to " + req.script_url ("/"), "text/html")
|
||||
end
|
||||
|
||||
execute_not_found (uri: READABLE_STRING_8; ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_not_found (uri: READABLE_STRING_8; ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- `uri' is not found, redirect to default page
|
||||
do
|
||||
res.redirect_now_with_content (req.script_url ("/"), uri + ": not found.%NRedirection to " + req.script_url ("/"), "text/html")
|
||||
end
|
||||
|
||||
execute_upload (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute_upload (ctx: WSF_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Upload page is requested, either GET or POST
|
||||
-- On GET display the web form to upload file, by passing ?nb=5 you can upload 5 images
|
||||
-- On POST display the uploaded files
|
||||
@@ -128,7 +129,7 @@ feature -- Execution
|
||||
n := n - 1
|
||||
end
|
||||
l_body.append (" <input type=%"submit%" value=%"Upload%"/>%N</form>")
|
||||
page.send_to (res)
|
||||
res.send (page)
|
||||
else
|
||||
create l_body.make (255)
|
||||
l_body.append ("<h1>EWF: Uploaded files</h1>%N")
|
||||
@@ -156,7 +157,7 @@ feature -- Execution
|
||||
page.set_title ("EWF: uploaded image")
|
||||
page.add_style ("../style.css", "all")
|
||||
page.set_body (l_body)
|
||||
page.send_to (res)
|
||||
res.send (page)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
10
library/client/http_client/license.lic
Normal file
10
library/client/http_client/license.lic
Normal file
@@ -0,0 +1,10 @@
|
||||
${NOTE_KEYWORD}
|
||||
copyright: "2011-${YEAR}, Jocelyn Fiat, Javier Velilla, 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
|
||||
]"
|
||||
@@ -13,4 +13,14 @@ feature -- Status
|
||||
deferred
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
|
||||
@@ -34,4 +34,14 @@ feature -- Auth type
|
||||
Auth_type_any: INTEGER = 3
|
||||
Auth_type_anysafe: INTEGER = 4
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
|
||||
@@ -92,6 +92,11 @@ feature -- Authentication
|
||||
Result := session.credentials
|
||||
end
|
||||
|
||||
proxy: detachable TUPLE [host: READABLE_STRING_8; port: INTEGER]
|
||||
do
|
||||
Result := session.proxy
|
||||
end
|
||||
|
||||
feature -- Settings
|
||||
|
||||
timeout: INTEGER
|
||||
@@ -131,6 +136,12 @@ feature -- Settings
|
||||
Result := session.default_response_charset
|
||||
end
|
||||
|
||||
is_insecure: BOOLEAN
|
||||
-- Allow connections to SSL sites without certs
|
||||
do
|
||||
Result := session.is_insecure
|
||||
end
|
||||
|
||||
feature {NONE} -- Utilities
|
||||
|
||||
append_parameters_to_url (a_url: STRING; a_parameters: detachable ARRAY [detachable TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
|
||||
@@ -198,4 +209,14 @@ feature {NONE} -- Utilities: encoding
|
||||
Result.replace_substring_all ("\\", "\")
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
|
||||
@@ -101,4 +101,14 @@ feature -- Element change
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
|
||||
@@ -164,4 +164,14 @@ feature {NONE} -- Implementation
|
||||
internal_headers: detachable ARRAYED_LIST [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]]
|
||||
-- Internal cached value for the headers
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
|
||||
@@ -105,6 +105,12 @@ feature -- Settings
|
||||
default_response_charset: detachable READABLE_STRING_8
|
||||
-- Default encoding of responses. Used if no charset is provided by the host.
|
||||
|
||||
is_insecure: BOOLEAN
|
||||
-- Allow connections to SSL sites without certs
|
||||
|
||||
proxy: detachable TUPLE [host: READABLE_STRING_8; port: INTEGER]
|
||||
-- Proxy information [`host' and `port']
|
||||
|
||||
feature -- Access
|
||||
|
||||
base_url: READABLE_STRING_8
|
||||
@@ -132,9 +138,9 @@ feature -- Change
|
||||
base_url := u
|
||||
end
|
||||
|
||||
set_timeout (n: like timeout)
|
||||
set_timeout (n_seconds: like timeout)
|
||||
do
|
||||
timeout := n
|
||||
timeout := n_seconds
|
||||
end
|
||||
|
||||
set_connect_timeout (n: like connect_timeout)
|
||||
@@ -147,6 +153,11 @@ feature -- Change
|
||||
add_header ("User-Agent", v)
|
||||
end
|
||||
|
||||
set_is_insecure (b: BOOLEAN)
|
||||
do
|
||||
is_insecure := b
|
||||
end
|
||||
|
||||
add_header (k: READABLE_STRING_8; v: READABLE_STRING_8)
|
||||
do
|
||||
headers.force (v, k)
|
||||
@@ -203,4 +214,23 @@ feature -- Change
|
||||
max_redirects := n
|
||||
end
|
||||
|
||||
set_proxy (a_host: detachable READABLE_STRING_8; a_port: INTEGER)
|
||||
do
|
||||
if a_host = Void then
|
||||
proxy := Void
|
||||
else
|
||||
proxy := [a_host, a_port]
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
|
||||
@@ -81,11 +81,11 @@ feature {NONE} -- Implementation
|
||||
|
||||
note
|
||||
library: "cURL: Library of reusable components for Eiffel."
|
||||
copyright: "Copyright (c) 1984-2006, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
356 Storke Road, Goleta, CA 93117 USA
|
||||
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
|
||||
|
||||
@@ -27,4 +27,14 @@ feature -- Status
|
||||
create Result.make (a_base_url)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
|
||||
@@ -54,6 +54,7 @@ feature -- Execution
|
||||
curl_easy: CURL_EASY_EXTERNALS
|
||||
curl_handle: POINTER
|
||||
ctx: like context
|
||||
l_proxy: like proxy
|
||||
do
|
||||
ctx := context
|
||||
curl := session.curl
|
||||
@@ -83,7 +84,14 @@ feature -- Execution
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_header, 1)
|
||||
|
||||
--| PROXY ...
|
||||
if ctx /= Void and then attached ctx.proxy as l_proxy then
|
||||
|
||||
if ctx /= Void then
|
||||
l_proxy := ctx.proxy
|
||||
end
|
||||
if l_proxy = Void then
|
||||
l_proxy := proxy
|
||||
end
|
||||
if l_proxy /= Void then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_proxyport, l_proxy.port)
|
||||
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_proxy, l_proxy.host)
|
||||
end
|
||||
@@ -104,6 +112,12 @@ feature -- Execution
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_followlocation, 0)
|
||||
end
|
||||
|
||||
--| SSL
|
||||
if is_insecure then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_ssl_verifyhost, 0)
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_ssl_verifypeer, 0)
|
||||
end
|
||||
|
||||
if request_method.is_case_insensitive_equal ("GET") then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpget, 1)
|
||||
elseif request_method.is_case_insensitive_equal ("POST") then
|
||||
@@ -253,4 +267,14 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
end
|
||||
end
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
|
||||
@@ -121,4 +121,14 @@ feature {LIBCURL_HTTP_CLIENT_REQUEST} -- Curl implementation
|
||||
-- cURL easy externals
|
||||
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
${NOTE_KEYWORD}
|
||||
copyright: "2011-${YEAR}, Eiffel Software and others"
|
||||
copyright: "2011-${YEAR}, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
${NOTE_KEYWORD}
|
||||
copyright: "2011-${YEAR}, Javier Velilla, Jocelyn Fiat and others"
|
||||
copyright: "2011-${YEAR}, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
${NOTE_KEYWORD}
|
||||
copyright: "2011-${YEAR}, Eiffel Software and others"
|
||||
copyright: "2011-${YEAR}, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
32
library/protocol/http/src/http_content_type.e
Normal file
32
library/protocol/http/src/http_content_type.e
Normal file
@@ -0,0 +1,32 @@
|
||||
note
|
||||
description: "[
|
||||
This class is to represent the CONTENT_TYPE value
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HTTP_CONTENT_TYPE
|
||||
|
||||
inherit
|
||||
HTTP_MEDIA_TYPE
|
||||
|
||||
create
|
||||
make,
|
||||
make_from_string
|
||||
|
||||
convert
|
||||
make_from_string ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
|
||||
string: {READABLE_STRING_8}
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, 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
|
||||
@@ -12,7 +12,6 @@ note
|
||||
(or HTTP_CONSTANTS which groups them for convenience)
|
||||
|
||||
Note the return status code is not part of the HTTP header
|
||||
However you can set the "Status: " header line if you want
|
||||
]"
|
||||
legal: "See notice at end of class."
|
||||
status: "See notice at end of class."
|
||||
@@ -25,16 +24,12 @@ class
|
||||
inherit
|
||||
ANY
|
||||
|
||||
HTTP_STATUS_CODE_MESSAGES --| useful for `put_status'
|
||||
export
|
||||
{NONE} all
|
||||
end
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_count,
|
||||
make_from_array,
|
||||
make_from_header
|
||||
make_from_header,
|
||||
make_from_raw_header_data
|
||||
|
||||
convert
|
||||
make_from_array ({ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]]}),
|
||||
@@ -72,6 +67,27 @@ feature {NONE} -- Initialization
|
||||
append_header_object (a_header)
|
||||
end
|
||||
|
||||
make_from_raw_header_data (h: READABLE_STRING_8)
|
||||
-- Create Current from raw header data
|
||||
local
|
||||
line : detachable STRING
|
||||
lines: LIST [READABLE_STRING_8]
|
||||
do
|
||||
lines := h.split ('%N')
|
||||
make_with_count (lines.count)
|
||||
across
|
||||
lines as c
|
||||
loop
|
||||
line := c.item
|
||||
if not line.is_empty then
|
||||
if line [line.count] = '%R' then
|
||||
line.remove_tail (1)
|
||||
end
|
||||
add_header (line)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Recycle
|
||||
|
||||
recycle
|
||||
@@ -106,6 +122,21 @@ feature -- Access
|
||||
result_has_single_ending_cr_lf: Result.count >= 4 implies not Result.substring (Result.count - 3, Result.count).same_string ("%R%N%R%N")
|
||||
end
|
||||
|
||||
to_name_value_iterable: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]
|
||||
local
|
||||
res: ARRAYED_LIST [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]
|
||||
do
|
||||
create res.make (headers.count)
|
||||
across
|
||||
headers as c
|
||||
loop
|
||||
if attached header_name_value (c.item) as tu then
|
||||
res.extend (tu)
|
||||
end
|
||||
end
|
||||
Result := res
|
||||
end
|
||||
|
||||
feature -- Header: filling
|
||||
|
||||
append_array (a_headers: ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]])
|
||||
@@ -128,7 +159,7 @@ feature -- Header: filling
|
||||
loop
|
||||
add_header (c.item.string)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Header change: general
|
||||
|
||||
@@ -147,7 +178,7 @@ feature -- Header change: general
|
||||
require
|
||||
h_not_empty: not h.is_empty
|
||||
do
|
||||
force_header_by_name (header_name (h), h)
|
||||
force_header_by_name (header_name_colon (h), h)
|
||||
end
|
||||
|
||||
add_header_key_value (k,v: READABLE_STRING_8)
|
||||
@@ -162,22 +193,6 @@ feature -- Header change: general
|
||||
put_header (k + colon_space + v)
|
||||
end
|
||||
|
||||
feature -- Status related
|
||||
|
||||
put_status (c: INTEGER)
|
||||
-- Put "Status: " header
|
||||
-- Rarely used
|
||||
local
|
||||
s: STRING
|
||||
do
|
||||
create s.make_from_string (c.out)
|
||||
if attached http_status_code_message (c) as msg then
|
||||
s.append_character (' ')
|
||||
s.append (msg)
|
||||
end
|
||||
put_header_key_value ("Status", s)
|
||||
end
|
||||
|
||||
feature -- Content related header
|
||||
|
||||
put_content_type (t: READABLE_STRING_8)
|
||||
@@ -191,26 +206,76 @@ feature -- Content related header
|
||||
add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t)
|
||||
end
|
||||
|
||||
put_content_type_with_parameters (t: READABLE_STRING_8; a_params: detachable ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
if a_params /= Void and then not a_params.is_empty then
|
||||
create s.make_from_string (t)
|
||||
across
|
||||
a_params as p
|
||||
loop
|
||||
if attached p.item as nv then
|
||||
s.append_character (';')
|
||||
s.append_character (' ')
|
||||
s.append (nv.name)
|
||||
s.append_character ('=')
|
||||
s.append_character ('%"')
|
||||
s.append (nv.value)
|
||||
s.append_character ('%"')
|
||||
end
|
||||
end
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, s)
|
||||
else
|
||||
put_content_type (t)
|
||||
end
|
||||
end
|
||||
|
||||
add_content_type_with_parameters (t: READABLE_STRING_8; a_params: detachable ARRAY [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
if a_params /= Void and then not a_params.is_empty then
|
||||
create s.make_from_string (t)
|
||||
across
|
||||
a_params as p
|
||||
loop
|
||||
if attached p.item as nv then
|
||||
s.append_character (';')
|
||||
s.append_character (' ')
|
||||
s.append (nv.name)
|
||||
s.append_character ('=')
|
||||
s.append_character ('%"')
|
||||
s.append (nv.value)
|
||||
s.append_character ('%"')
|
||||
end
|
||||
end
|
||||
add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, s)
|
||||
else
|
||||
add_content_type (t)
|
||||
end
|
||||
end
|
||||
|
||||
put_content_type_with_charset (t: READABLE_STRING_8; c: READABLE_STRING_8)
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; charset=" + c + "")
|
||||
put_content_type_with_parameters (t, <<["charset", c]>>)
|
||||
end
|
||||
|
||||
add_content_type_with_charset (t: READABLE_STRING_8; c: READABLE_STRING_8)
|
||||
-- same as `put_content_type_with_charset', but allow multiple definition of "Content-Type"
|
||||
do
|
||||
add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; charset=" + c + "")
|
||||
add_content_type_with_parameters (t, <<["charset", c]>>)
|
||||
end
|
||||
|
||||
put_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8)
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; name=%"" + n + "%"")
|
||||
put_content_type_with_parameters (t, <<["name", n]>>)
|
||||
end
|
||||
|
||||
add_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8)
|
||||
-- same as `put_content_type_with_name', but allow multiple definition of "Content-Type"
|
||||
do
|
||||
add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; name=%"" + n + "%"")
|
||||
add_content_type_with_parameters (t, <<["name", n]>>)
|
||||
end
|
||||
|
||||
put_content_length (n: INTEGER)
|
||||
@@ -309,6 +374,7 @@ feature -- Content-type helpers
|
||||
put_content_type_multipart_form_data do put_content_type ({HTTP_MIME_TYPES}.multipart_form_data) end
|
||||
put_content_type_multipart_signed do put_content_type ({HTTP_MIME_TYPES}.multipart_signed) end
|
||||
put_content_type_multipart_encrypted do put_content_type ({HTTP_MIME_TYPES}.multipart_encrypted) end
|
||||
put_content_type_application_x_www_form_encoded do put_content_type ({HTTP_MIME_TYPES}.application_x_www_form_encoded) end
|
||||
|
||||
feature -- Date
|
||||
|
||||
@@ -500,7 +566,7 @@ feature {NONE} -- Implementation: Header
|
||||
force_header_by_name (n: detachable READABLE_STRING_8; h: READABLE_STRING_8)
|
||||
-- Add header `h' or replace existing header of same header name `n'
|
||||
require
|
||||
h_has_name_n: (n /= Void and attached header_name (h) as hn) implies n.same_string (hn)
|
||||
h_has_name_n: (n /= Void and attached header_name_colon (h) as hn) implies n.same_string (hn)
|
||||
local
|
||||
l_headers: like headers
|
||||
do
|
||||
@@ -523,7 +589,7 @@ feature {NONE} -- Implementation: Header
|
||||
end
|
||||
end
|
||||
|
||||
header_name (h: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
header_name_colon (h: READABLE_STRING_8): detachable STRING_8
|
||||
-- If any, header's name with colon
|
||||
--| ex: for "Foo-bar: something", this will return "Foo-bar:"
|
||||
local
|
||||
@@ -552,6 +618,36 @@ feature {NONE} -- Implementation: Header
|
||||
Result := s
|
||||
end
|
||||
|
||||
header_name_value (h: READABLE_STRING_8): detachable TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]
|
||||
-- If any, header's [name,value]
|
||||
--| ex: for "Foo-bar: something", this will return ["Foo-bar", "something"]
|
||||
local
|
||||
s: detachable STRING_8
|
||||
i,n: INTEGER
|
||||
c: CHARACTER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
n := h.count
|
||||
create s.make (10)
|
||||
until
|
||||
i > n or c = ':' or s = Void
|
||||
loop
|
||||
c := h[i]
|
||||
inspect c
|
||||
when ':' then
|
||||
when '-', 'a' .. 'z', 'A' .. 'Z' then
|
||||
s.extend (c)
|
||||
else
|
||||
s := Void
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
if s /= Void then
|
||||
Result := [s, h.substring (i, n)]
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
append_line_to (s: READABLE_STRING_8; h: STRING_8)
|
||||
@@ -566,7 +662,7 @@ feature {NONE} -- Implementation
|
||||
h.append_character ('%N')
|
||||
end
|
||||
|
||||
date_to_rfc1123_http_date_format (dt: DATE_TIME): READABLE_STRING_8
|
||||
date_to_rfc1123_http_date_format (dt: DATE_TIME): STRING_8
|
||||
-- String representation of `dt' using the RFC 1123
|
||||
do
|
||||
Result := dt.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT"
|
||||
@@ -581,7 +677,7 @@ feature {NONE} -- Constants
|
||||
semi_colon_space: STRING = "; "
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -231,6 +231,9 @@ feature -- Request or Response header name
|
||||
-- Implementation-specific headers that may have various effects anywhere along the request-response chain.
|
||||
--| Example: Pragma: no-cache
|
||||
|
||||
header_status: STRING = "Status"
|
||||
-- CGI program can use this to return the HTTP status code to the client.
|
||||
|
||||
header_via: STRING = "Via"
|
||||
-- Request: Informs the server of proxies through which the request was sent.
|
||||
-- Response: Informs the client of proxies through which the response was sent.
|
||||
@@ -245,7 +248,7 @@ feature -- MIME related
|
||||
header_content_transfer_encoding: STRING = "Content-Transfer-Encoding"
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
350
library/protocol/http/src/http_media_type.e
Normal file
350
library/protocol/http/src/http_media_type.e
Normal file
@@ -0,0 +1,350 @@
|
||||
note
|
||||
description: "[
|
||||
This class is to represent a media type
|
||||
|
||||
the Internet Media Type [9] of the attached entity if the type
|
||||
was provided via a "Content-type" field in the wgi_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
|
||||
application/x-www-form-urlencoded; charset=UTF8
|
||||
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
HTTP_MEDIA_TYPE
|
||||
|
||||
inherit
|
||||
DEBUG_OUTPUT
|
||||
|
||||
create
|
||||
make,
|
||||
make_from_string
|
||||
|
||||
convert
|
||||
make_from_string ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
|
||||
string: {READABLE_STRING_8}
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_type, a_subtype: READABLE_STRING_8)
|
||||
-- Create Current based on `a_type/a_subtype'
|
||||
require
|
||||
not a_type.is_empty
|
||||
not a_subtype.is_empty
|
||||
do
|
||||
type := a_type
|
||||
subtype := a_subtype
|
||||
ensure
|
||||
has_no_error: not has_error
|
||||
end
|
||||
|
||||
make_from_string (s: READABLE_STRING_8)
|
||||
-- Create Current from `s'
|
||||
-- if `s' does not respect the expected syntax, has_error is True
|
||||
local
|
||||
t: STRING_8
|
||||
i,n: INTEGER
|
||||
p: INTEGER
|
||||
do
|
||||
-- Ignore starting space (should not be any)
|
||||
from
|
||||
i := 1
|
||||
n := s.count
|
||||
until
|
||||
i > n or not s[i].is_space
|
||||
loop
|
||||
i := i + 1
|
||||
end
|
||||
if i < n then
|
||||
-- Look for semi colon as parameter separation
|
||||
p := s.index_of (';', i)
|
||||
if p > 0 then
|
||||
t := s.substring (i, p - 1)
|
||||
i := p + 1
|
||||
p := s.index_of (';', i)
|
||||
if p = 0 then
|
||||
add_parameter_from_string (s, i, n)
|
||||
i := n
|
||||
else
|
||||
add_parameter_from_string (s, i, p - 1)
|
||||
i := p + 1
|
||||
end
|
||||
else
|
||||
t := s.substring (i, n)
|
||||
end
|
||||
-- Remove eventual trailing space
|
||||
t.right_adjust
|
||||
|
||||
-- Extract type and subtype
|
||||
p := t.index_of ('/', 1)
|
||||
if p = 0 then
|
||||
has_error := True
|
||||
type := t
|
||||
subtype := ""
|
||||
else
|
||||
subtype := t.substring (p + 1, t.count)
|
||||
type := t
|
||||
t.keep_head (p - 1)
|
||||
end
|
||||
else
|
||||
has_error := True
|
||||
type := ""
|
||||
subtype := type
|
||||
end
|
||||
ensure
|
||||
not has_error implies (create {HTTP_CONTENT_TYPE}.make_from_string (string)).same_string (string)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_error: BOOLEAN
|
||||
-- Current has error?
|
||||
--| Mainly in relation with `make_from_string'
|
||||
|
||||
feature -- Access
|
||||
|
||||
type: READABLE_STRING_8
|
||||
-- Main type
|
||||
|
||||
subtype: READABLE_STRING_8
|
||||
-- Sub type
|
||||
|
||||
has_parameter (a_name: READABLE_STRING_8): BOOLEAN
|
||||
-- Has Current a parameter?
|
||||
do
|
||||
if attached parameters as plst then
|
||||
Result := plst.has (a_name)
|
||||
end
|
||||
end
|
||||
|
||||
parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- Value for eventual parameter named `a_name'.
|
||||
do
|
||||
if attached parameters as plst then
|
||||
Result := plst.item (a_name)
|
||||
end
|
||||
end
|
||||
|
||||
parameters: detachable HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
-- Parameters
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
string: READABLE_STRING_8
|
||||
-- String representation of type/subtype; attribute=value
|
||||
local
|
||||
res: like internal_string
|
||||
do
|
||||
res := internal_string
|
||||
if res = Void then
|
||||
create res.make_from_string (simple_type)
|
||||
if attached parameters as plst then
|
||||
across
|
||||
plst as p
|
||||
loop
|
||||
res.append_character (';')
|
||||
res.append_character (' ')
|
||||
res.append (p.key)
|
||||
res.append_character ('=')
|
||||
res.append_character ('%"')
|
||||
res.append (p.item)
|
||||
res.append_character ('%"')
|
||||
end
|
||||
end
|
||||
internal_string := res
|
||||
end
|
||||
Result := res
|
||||
end
|
||||
|
||||
simple_type: READABLE_STRING_8
|
||||
-- String representation of type/subtype
|
||||
local
|
||||
res: like internal_simple_type
|
||||
s: like subtype
|
||||
do
|
||||
res := internal_simple_type
|
||||
if res = Void then
|
||||
create res.make_from_string (type)
|
||||
s := subtype
|
||||
if not s.is_empty then
|
||||
check has_error: has_error end
|
||||
-- Just in case not is_valid, we keep in `type' the original string
|
||||
res.append_character ('/')
|
||||
res.append (s)
|
||||
end
|
||||
internal_simple_type := res
|
||||
end
|
||||
Result := res
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
same_as (other: HTTP_CONTENT_TYPE): BOOLEAN
|
||||
-- Current has same type/subtype and parameters as `other'?
|
||||
local
|
||||
plst,oplst: like parameters
|
||||
do
|
||||
Result := other.type.same_string (other.type) and then
|
||||
other.subtype.same_string (other.subtype)
|
||||
if Result then
|
||||
plst := parameters
|
||||
oplst := other.parameters
|
||||
if plst = oplst then
|
||||
elseif plst = Void then
|
||||
Result := False -- since oplst /= Void
|
||||
elseif oplst /= Void and then plst.count = oplst.count then
|
||||
across
|
||||
plst as p
|
||||
until
|
||||
not Result
|
||||
loop
|
||||
Result := attached oplst.item (p.key) as op_value and then p.item.same_string (op_value)
|
||||
end
|
||||
else
|
||||
Result := False
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
same_simple_type (s: READABLE_STRING_8): BOOLEAN
|
||||
-- Current has same type/subtype string representation as `s'?
|
||||
do
|
||||
Result := simple_type.same_string (s)
|
||||
end
|
||||
|
||||
same_string (s: READABLE_STRING_8): BOOLEAN
|
||||
-- Current has same string representation as `s'?
|
||||
do
|
||||
Result := string.same_string (s)
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
add_parameter (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8)
|
||||
-- Set parameter for `a_name' to `a_value'
|
||||
local
|
||||
plst: like parameters
|
||||
do
|
||||
plst := parameters
|
||||
if plst = Void then
|
||||
create plst.make (1)
|
||||
parameters := plst
|
||||
end
|
||||
plst.force (a_value, a_name)
|
||||
internal_string := Void
|
||||
end
|
||||
|
||||
remove_parameter (a_name: READABLE_STRING_8)
|
||||
-- Remove parameter named `a_name'
|
||||
do
|
||||
if attached parameters as plst then
|
||||
plst.prune (a_name)
|
||||
if plst.is_empty then
|
||||
parameters := Void
|
||||
end
|
||||
end
|
||||
internal_string := Void
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
add_parameter_from_string (s: READABLE_STRING_8; start_index, end_index: INTEGER)
|
||||
-- Add parameter from string " attribute=value "
|
||||
local
|
||||
pn,pv: STRING_8
|
||||
i: INTEGER
|
||||
p: INTEGER
|
||||
err: BOOLEAN
|
||||
do
|
||||
-- Skip spaces
|
||||
from
|
||||
i := start_index
|
||||
until
|
||||
i > end_index or not s[i].is_space
|
||||
loop
|
||||
i := i + 1
|
||||
end
|
||||
if i < end_index then
|
||||
p := s.index_of ('=', i)
|
||||
if p > 0 and p < end_index then
|
||||
pn := s.substring (i, p - 1)
|
||||
pv := s.substring (p + 1, end_index)
|
||||
pv.right_adjust
|
||||
if pv.count > 0 and pv [1] = '%"' then
|
||||
if pv [pv.count] = '%"' then
|
||||
pv := pv.substring (2, pv.count - 1)
|
||||
else
|
||||
err := True
|
||||
-- missing closing double quote.
|
||||
end
|
||||
end
|
||||
if not err then
|
||||
add_parameter (pn, pv)
|
||||
end
|
||||
else
|
||||
-- expecting: attribute "=" value
|
||||
err := True
|
||||
end
|
||||
end
|
||||
has_error := has_error or err
|
||||
end
|
||||
|
||||
feature {NONE} -- Internal
|
||||
|
||||
internal_string: detachable STRING_8
|
||||
|
||||
internal_simple_type: detachable STRING_8
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
if type /= Void and subtype /= Void then
|
||||
Result := type + "/" + subtype
|
||||
if attached parameters as plst then
|
||||
across
|
||||
plst as p
|
||||
loop
|
||||
Result.append ("; " + p.key + "=" + "%"" + p.item + "%"")
|
||||
end
|
||||
end
|
||||
else
|
||||
Result := ""
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
type_and_subtype_not_empty: not has_error implies not type.is_empty and not subtype.is_empty
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, 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
|
||||
@@ -94,7 +94,7 @@ feature -- 5xx : Server Error
|
||||
user_access_denied: INTEGER = 530
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -148,7 +148,7 @@ feature -- Status messages
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
${NOTE_KEYWORD}
|
||||
copyright: "2011-${YEAR}, Eiffel Software and others"
|
||||
copyright: "2011-${YEAR}, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -176,6 +176,13 @@ feature -- Builder
|
||||
end
|
||||
end
|
||||
|
||||
expanded_string_with_base_url (a_base_url: READABLE_STRING_8; a_ht: HASH_TABLE [detachable ANY, STRING]): STRING
|
||||
-- Expanded template using variable from `a_ht'
|
||||
-- with based url
|
||||
do
|
||||
Result := a_base_url + expanded_string (a_ht)
|
||||
end
|
||||
|
||||
feature -- Match
|
||||
|
||||
match (a_uri: READABLE_STRING_8): detachable URI_TEMPLATE_MATCH_RESULT
|
||||
@@ -506,7 +513,7 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -94,7 +94,7 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
|
||||
;note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -42,13 +42,13 @@ feature -- Execution
|
||||
do
|
||||
if not rescued then
|
||||
create req.make ((create {EXECUTION_ENVIRONMENT}).starting_environment_variables, create {WGI_CGI_INPUT_STREAM}.make, Current)
|
||||
create res.make (create {WGI_CGI_OUTPUT_STREAM}.make)
|
||||
create res.make (create {WGI_CGI_OUTPUT_STREAM}.make, create {WGI_CGI_ERROR_STREAM}.make)
|
||||
service.execute (req, res)
|
||||
else
|
||||
if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then
|
||||
if res /= Void then
|
||||
if not res.status_is_set then
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void)
|
||||
end
|
||||
if res.message_writable then
|
||||
res.put_string ("<pre>" + l_trace + "</pre>")
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
note
|
||||
description: "Summary description for WGI_CGI_ERROR_STREAM."
|
||||
legal: "See notice at end of class."
|
||||
status: "See notice at end of class."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WGI_CGI_ERROR_STREAM
|
||||
|
||||
inherit
|
||||
WGI_ERROR_STREAM
|
||||
|
||||
CONSOLE
|
||||
rename
|
||||
make as console_make
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
make_open_stdout ("stderr")
|
||||
end
|
||||
|
||||
feature -- Error
|
||||
|
||||
put_error (a_message: READABLE_STRING_8)
|
||||
do
|
||||
put_readable_string_8 (a_message)
|
||||
end
|
||||
|
||||
put_readable_string_8 (s: READABLE_STRING_8)
|
||||
-- Write `s' at end of default output.
|
||||
local
|
||||
ext: C_STRING
|
||||
do
|
||||
if s.count > 0 then
|
||||
create ext.make (s)
|
||||
console_ps (file_pointer, ext.managed_data.item, s.count)
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
@@ -36,21 +36,24 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Status writing
|
||||
|
||||
put_status_line (a_code: INTEGER)
|
||||
-- Put status code line for `a_code'
|
||||
--| Note this is a default implementation, and could be redefined
|
||||
--| for instance in relation to NPH CGI script
|
||||
put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
|
||||
-- <Precursor>
|
||||
local
|
||||
s: STRING
|
||||
m: detachable READABLE_STRING_8
|
||||
do
|
||||
if a_code /= 200 then
|
||||
create s.make (16)
|
||||
s.append ("Status:")
|
||||
s.append_character (' ')
|
||||
s.append_integer (a_code)
|
||||
if attached http_status_code_message (a_code) as l_status_message then
|
||||
m := a_reason_phrase
|
||||
if m = Void then
|
||||
m := http_status_code_message (a_code)
|
||||
end
|
||||
if m /= Void then
|
||||
s.append_character (' ')
|
||||
s.append_string (l_status_message)
|
||||
s.append_string (m)
|
||||
end
|
||||
put_header_line (s)
|
||||
end
|
||||
|
||||
@@ -20,8 +20,8 @@ feature {NONE} -- Initialization
|
||||
do
|
||||
service := a_service
|
||||
create fcgi.make
|
||||
create {WGI_LIBFCGI_INPUT_STREAM} input.make (fcgi)
|
||||
create {WGI_LIBFCGI_OUTPUT_STREAM} output.make (fcgi)
|
||||
create input.make (fcgi)
|
||||
create output.make (fcgi)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
@@ -63,13 +63,13 @@ feature -- Execution
|
||||
do
|
||||
if not rescued then
|
||||
create req.make (vars, a_input, Current)
|
||||
create res.make (a_output)
|
||||
create res.make (a_output, a_output)
|
||||
service.execute (req, res)
|
||||
else
|
||||
if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then
|
||||
if res /= Void then
|
||||
if not res.status_is_set then
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void)
|
||||
end
|
||||
if res.message_writable then
|
||||
res.put_string ("<pre>" + l_trace + "</pre>")
|
||||
@@ -84,10 +84,10 @@ feature -- Execution
|
||||
|
||||
feature -- Input/Output
|
||||
|
||||
input: WGI_INPUT_STREAM
|
||||
input: WGI_LIBFCGI_INPUT_STREAM
|
||||
-- Input from client (from httpd server via FCGI)
|
||||
|
||||
output: WGI_OUTPUT_STREAM
|
||||
output: WGI_LIBFCGI_OUTPUT_STREAM
|
||||
-- Output to client (via httpd server/fcgi)
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
@@ -75,6 +75,7 @@ feature -- Access
|
||||
|
||||
last_string: STRING
|
||||
-- Last string read
|
||||
-- <Precursor>
|
||||
|
||||
last_character: CHARACTER_8
|
||||
-- Last item read
|
||||
|
||||
@@ -11,6 +11,8 @@ class
|
||||
inherit
|
||||
WGI_OUTPUT_STREAM
|
||||
|
||||
WGI_ERROR_STREAM
|
||||
|
||||
HTTP_STATUS_CODE_MESSAGES
|
||||
export
|
||||
{NONE} all
|
||||
@@ -38,23 +40,24 @@ feature -- Status report
|
||||
|
||||
feature -- Status writing
|
||||
|
||||
put_status_line (a_code: INTEGER)
|
||||
-- Put status code line for `a_code'
|
||||
--| Note this is a default implementation, and could be redefined
|
||||
--| for instance in relation to NPH CGI script
|
||||
put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
|
||||
-- <Precursor>
|
||||
local
|
||||
s: STRING
|
||||
m: detachable READABLE_STRING_8
|
||||
do
|
||||
--| Do not send any Status line back to the FastCGI client
|
||||
--| According to http://www.fastcgi.com/docs/faq.html#httpstatus
|
||||
if a_code /= 200 then
|
||||
create s.make (16)
|
||||
s.append ("Status:")
|
||||
s.append_character (' ')
|
||||
s.append_integer (a_code)
|
||||
if attached http_status_code_message (a_code) as l_status_message then
|
||||
m := a_reason_phrase
|
||||
if m = Void then
|
||||
m := http_status_code_message (a_code)
|
||||
end
|
||||
if m /= Void then
|
||||
s.append_character (' ')
|
||||
s.append_string (l_status_message)
|
||||
s.append_string (m)
|
||||
end
|
||||
put_header_line (s)
|
||||
end
|
||||
@@ -68,6 +71,12 @@ feature -- Basic operation
|
||||
fcgi.put_string (s)
|
||||
end
|
||||
|
||||
put_character (c: CHARACTER_8)
|
||||
-- Send `c' to http client
|
||||
do
|
||||
fcgi.put_string (c.out)
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
flush
|
||||
@@ -75,6 +84,13 @@ feature -- Basic operations
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Error
|
||||
|
||||
put_error (a_message: READABLE_STRING_8)
|
||||
do
|
||||
fcgi.put_error (a_message)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
fcgi: FCGI
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
${NOTE_KEYWORD}
|
||||
copyright: "2011-${YEAR}, Eiffel Software and others"
|
||||
copyright: "2011-${YEAR}, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -8,17 +8,33 @@ class
|
||||
|
||||
create
|
||||
make,
|
||||
make_custom
|
||||
make_custom,
|
||||
make_with_callback,
|
||||
make_custom_with_callback
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
make (a_callback: like {WGI_AGENT_SERVICE}.callback)
|
||||
make (a_service: WGI_SERVICE)
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
make_custom (a_callback, Void)
|
||||
make_custom (a_service, Void)
|
||||
end
|
||||
|
||||
make_custom (a_callback: like {WGI_AGENT_SERVICE}.callback; a_base_url: detachable STRING)
|
||||
make_custom (a_service: WGI_SERVICE; a_base_url: detachable STRING)
|
||||
-- Initialize `Current'.
|
||||
require
|
||||
base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/")
|
||||
do
|
||||
create connector.make_with_base (a_service, a_base_url)
|
||||
end
|
||||
|
||||
make_with_callback (a_callback: like {WGI_AGENT_SERVICE}.callback)
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
make_custom_with_callback (a_callback, Void)
|
||||
end
|
||||
|
||||
make_custom_with_callback (a_callback: like {WGI_AGENT_SERVICE}.callback; a_base_url: detachable STRING)
|
||||
-- Initialize `Current'.
|
||||
require
|
||||
base_url_starts_with_slash: (a_base_url /= Void and then not a_base_url.is_empty) implies a_base_url.starts_with ("/")
|
||||
@@ -26,7 +42,7 @@ feature {NONE} -- Implementation
|
||||
app: WGI_AGENT_SERVICE
|
||||
do
|
||||
create app.make (a_callback)
|
||||
create connector.make_with_base (app, a_base_url)
|
||||
make_custom (app, a_base_url)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
@@ -88,7 +104,7 @@ feature -- Server
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {WGI_NINO_CONNECTOR}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
@@ -120,14 +119,14 @@ feature -- Server
|
||||
res: detachable WGI_NINO_RESPONSE_STREAM
|
||||
do
|
||||
create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_socket), Current)
|
||||
create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket))
|
||||
create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket), Void)
|
||||
req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text)
|
||||
service.execute (req, res)
|
||||
res.commit
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -36,21 +36,27 @@ feature -- Input
|
||||
read_character
|
||||
-- Read the next character in input stream.
|
||||
-- Make the result available in `last_character'.
|
||||
local
|
||||
src: like source
|
||||
do
|
||||
if source.socket_ok then
|
||||
source.read_character
|
||||
last_character := source.last_character
|
||||
src := source
|
||||
if src.socket_ok then
|
||||
src.read_character
|
||||
last_character := src.last_character
|
||||
else
|
||||
last_character := '%U'
|
||||
end
|
||||
end
|
||||
|
||||
read_string (nb: INTEGER)
|
||||
local
|
||||
src: like source
|
||||
do
|
||||
src := source
|
||||
last_string.wipe_out
|
||||
if source.socket_ok then
|
||||
source.read_stream_thread_aware (nb)
|
||||
last_string.append_string (source.last_string)
|
||||
if src.socket_ok then
|
||||
src.read_stream_thread_aware (nb)
|
||||
last_string.append_string (src.last_string)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -58,7 +64,7 @@ feature -- Access
|
||||
|
||||
last_string: STRING_8
|
||||
-- Last string read
|
||||
-- (Note: this query always return the same object.
|
||||
-- (Note: this query *might* return the same object.
|
||||
-- Therefore a clone should be used if the result
|
||||
-- is to be kept beyond the next call to this feature.
|
||||
-- However `last_string' is not shared between input objects.)
|
||||
@@ -81,7 +87,7 @@ feature -- Status report
|
||||
end
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -10,9 +10,6 @@ class
|
||||
|
||||
inherit
|
||||
WGI_OUTPUT_STREAM
|
||||
redefine
|
||||
put_character_8
|
||||
end
|
||||
|
||||
HTTP_STATUS_CODE_MESSAGES
|
||||
export
|
||||
@@ -40,20 +37,23 @@ feature {WGI_NINO_CONNECTOR, WGI_SERVICE} -- Nino
|
||||
|
||||
feature -- Status writing
|
||||
|
||||
put_status_line (a_code: INTEGER)
|
||||
-- Put status code line for `a_code'
|
||||
--| Note this is a default implementation, and could be redefined
|
||||
--| for instance in relation to NPH CGI script
|
||||
put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
|
||||
-- <Precursor>
|
||||
local
|
||||
s: STRING
|
||||
m: detachable READABLE_STRING_8
|
||||
do
|
||||
create s.make (16)
|
||||
s.append ({HTTP_CONSTANTS}.http_version_1_1)
|
||||
s.append_character (' ')
|
||||
s.append_integer (a_code)
|
||||
if attached http_status_code_message (a_code) as l_status_message then
|
||||
m := a_reason_phrase
|
||||
if m = Void then
|
||||
m := http_status_code_message (a_code)
|
||||
end
|
||||
if m /= Void then
|
||||
s.append_character (' ')
|
||||
s.append_string (l_status_message)
|
||||
s.append_string (m)
|
||||
end
|
||||
put_header_line (s)
|
||||
end
|
||||
@@ -66,7 +66,7 @@ feature -- Output
|
||||
target.put_readable_string_8 (s)
|
||||
end
|
||||
|
||||
put_character_8 (c: CHARACTER_8)
|
||||
put_character (c: CHARACTER_8)
|
||||
do
|
||||
target.put_character (c)
|
||||
end
|
||||
@@ -86,7 +86,7 @@ feature -- Basic operations
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -21,19 +21,24 @@ create
|
||||
feature -- Header output operation
|
||||
|
||||
put_header_text (a_text: READABLE_STRING_8)
|
||||
local
|
||||
o: like output
|
||||
do
|
||||
write (a_text)
|
||||
o := output
|
||||
o.put_string (a_text)
|
||||
|
||||
-- Nino does not support persistent connection for now
|
||||
write ("Connection: close")
|
||||
write (crlf)
|
||||
o.put_string ("Connection: close")
|
||||
o.put_crlf
|
||||
|
||||
-- end of headers
|
||||
write (crlf)
|
||||
o.put_crlf
|
||||
|
||||
header_committed := True
|
||||
end
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -14,9 +14,8 @@ create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_service: like service)
|
||||
make
|
||||
do
|
||||
service := a_service
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
@@ -27,42 +26,14 @@ feature -- Access
|
||||
Version: STRING_8 = "0.1"
|
||||
-- Version of Current connector
|
||||
|
||||
feature {NONE} -- Access
|
||||
|
||||
service: WGI_SERVICE
|
||||
-- Gateway Service
|
||||
|
||||
feature -- Execution
|
||||
|
||||
launch
|
||||
local
|
||||
req: WGI_REQUEST_FROM_TABLE
|
||||
res: detachable WGI_RESPONSE_STREAM
|
||||
rescued: BOOLEAN
|
||||
do
|
||||
if not rescued then
|
||||
create req.make ((create {EXECUTION_ENVIRONMENT}).starting_environment_variables, create {WGI_NULL_INPUT_STREAM}.make, Current)
|
||||
create res.make (create {WGI_NULL_OUTPUT_STREAM}.make)
|
||||
service.execute (req, res)
|
||||
else
|
||||
if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then
|
||||
if res /= Void then
|
||||
if not res.status_is_set then
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
|
||||
end
|
||||
if res.message_writable then
|
||||
res.put_string ("<pre>" + l_trace + "</pre>")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue
|
||||
rescued := True
|
||||
retry
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
note
|
||||
description: "Summary description for WGI_NULL_FILE_INPUT_STREAM."
|
||||
legal: "See notice at end of class."
|
||||
status: "See notice at end of class."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WGI_NULL_FILE_INPUT_STREAM
|
||||
|
||||
inherit
|
||||
WGI_NULL_INPUT_STREAM
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (f: FILE)
|
||||
do
|
||||
file := f
|
||||
end
|
||||
|
||||
file: FILE
|
||||
|
||||
feature -- Input
|
||||
|
||||
read_character
|
||||
-- Read the next character in input stream.
|
||||
-- Make the result available in `last_character'
|
||||
do
|
||||
file.read_character
|
||||
end
|
||||
|
||||
read_string (nb: INTEGER)
|
||||
-- Read the next `nb' characters and
|
||||
-- make the string result available in `last_string'
|
||||
do
|
||||
file.read_stream (nb)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_string: STRING_8
|
||||
-- Last string read.
|
||||
--
|
||||
-- Note: this query *might* return the same object.
|
||||
-- Therefore a clone should be used if the result
|
||||
-- is to be kept beyond the next call to this feature.
|
||||
-- However `last_string' is not shared between file objects.)
|
||||
do
|
||||
Result := file.last_string
|
||||
end
|
||||
|
||||
last_character: CHARACTER_8
|
||||
-- Last item read.
|
||||
do
|
||||
Result := file.last_character
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_open_read: BOOLEAN
|
||||
-- Can items be read from input stream?
|
||||
do
|
||||
Result := file.is_open_read
|
||||
end
|
||||
|
||||
end_of_input: BOOLEAN
|
||||
-- Has the end of input stream been reached?
|
||||
do
|
||||
Result := file.end_of_file
|
||||
end
|
||||
|
||||
|
||||
invariant
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2012, 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
|
||||
@@ -5,31 +5,12 @@ note
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
deferred class
|
||||
WGI_NULL_INPUT_STREAM
|
||||
|
||||
inherit
|
||||
WGI_INPUT_STREAM
|
||||
undefine
|
||||
read_to_string
|
||||
end
|
||||
|
||||
CONSOLE
|
||||
rename
|
||||
make as console_make,
|
||||
read_stream as read_string,
|
||||
end_of_file as end_of_input
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
make_open_stdin ("stdin")
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
|
||||
@@ -36,21 +36,24 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Status writing
|
||||
|
||||
put_status_line (a_code: INTEGER)
|
||||
-- Put status code line for `a_code'
|
||||
--| Note this is a default implementation, and could be redefined
|
||||
--| for instance in relation to NPH NULL script
|
||||
put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
|
||||
-- <Precursor>
|
||||
local
|
||||
s: STRING
|
||||
m: detachable READABLE_STRING_8
|
||||
do
|
||||
if a_code /= 200 then
|
||||
create s.make (16)
|
||||
s.append ("Status:")
|
||||
s.append_character (' ')
|
||||
s.append_integer (a_code)
|
||||
if attached http_status_code_message (a_code) as l_status_message then
|
||||
m := a_reason_phrase
|
||||
if m = Void then
|
||||
m := http_status_code_message (a_code)
|
||||
end
|
||||
if m /= Void then
|
||||
s.append_character (' ')
|
||||
s.append_string (l_status_message)
|
||||
s.append_string (m)
|
||||
end
|
||||
put_header_line (s)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
note
|
||||
description: "Summary description for WGI_NULL_STRING_INPUT_STREAM."
|
||||
legal: "See notice at end of class."
|
||||
status: "See notice at end of class."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WGI_NULL_STRING_INPUT_STREAM
|
||||
|
||||
inherit
|
||||
WGI_NULL_INPUT_STREAM
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (s: READABLE_STRING_8)
|
||||
do
|
||||
body := s
|
||||
index := 1
|
||||
count := s.count
|
||||
last_string := ""
|
||||
end
|
||||
|
||||
body: READABLE_STRING_8
|
||||
|
||||
index: INTEGER
|
||||
|
||||
count: INTEGER
|
||||
|
||||
feature -- Input
|
||||
|
||||
read_character
|
||||
-- Read the next character in input stream.
|
||||
-- Make the result available in `last_character'
|
||||
do
|
||||
last_character := body[index]
|
||||
index := index + 1
|
||||
end
|
||||
|
||||
read_string (nb: INTEGER)
|
||||
-- Read the next `nb' characters and
|
||||
-- make the string result available in `last_string'
|
||||
local
|
||||
e: INTEGER
|
||||
do
|
||||
e := (index + nb).min (count)
|
||||
last_string := body.substring (index, e)
|
||||
index := e + 1
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_string: STRING_8
|
||||
|
||||
last_character: CHARACTER_8
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_open_read: BOOLEAN
|
||||
-- Can items be read from input stream?
|
||||
do
|
||||
Result := True
|
||||
end
|
||||
|
||||
end_of_input: BOOLEAN
|
||||
-- Has the end of input stream been reached?
|
||||
do
|
||||
Result := index > count
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
note
|
||||
copyright: "2011-2012, 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
|
||||
@@ -18,5 +18,7 @@
|
||||
<cluster name="specification_request" location="specification\request" recursive="true"/>
|
||||
<cluster name="specification_response" location="specification\response" recursive="true"/>
|
||||
<cluster name="specification_connector" location="specification\connector" recursive="true"/>
|
||||
<cluster name="specification_service" location="specification\service" recursive="true"/>
|
||||
<cluster name="specification_stream" location="specification\stream" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -18,5 +18,7 @@
|
||||
<cluster name="specification_request" location="specification\request" recursive="true"/>
|
||||
<cluster name="specification_response" location="specification\response" recursive="true"/>
|
||||
<cluster name="specification_connector" location="specification\connector" recursive="true"/>
|
||||
<cluster name="specification_service" location="specification\service" recursive="true"/>
|
||||
<cluster name="specification_stream" location="specification\stream" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -7,6 +7,9 @@ note
|
||||
class
|
||||
HELLO_WORLD
|
||||
|
||||
inherit
|
||||
WGI_SERVICE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
@@ -15,20 +18,20 @@ feature {NONE} -- Initialization
|
||||
make
|
||||
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_SERVICE}.make_custom (agent execute, "")).listen (port_number)
|
||||
(create {NINO_SERVICE}.make_custom (Current, "")).listen (port_number)
|
||||
end
|
||||
|
||||
execute (req: WGI_REQUEST; res: WGI_RESPONSE)
|
||||
do
|
||||
res.set_status_code (200)
|
||||
res.put_header_lines (<<["Content-Type", "text/plain"]>>)
|
||||
res.set_status_code (200, Void)
|
||||
res.put_header_text ("Content-Type: text/plain%R%N")
|
||||
res.put_string ("Hello World!%N")
|
||||
end
|
||||
|
||||
port_number: INTEGER = 8123
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
${NOTE_KEYWORD}
|
||||
copyright: "2011-${YEAR}, Eiffel Software and others"
|
||||
copyright: "2011-${YEAR}, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -20,7 +20,7 @@ feature -- Access
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -79,7 +79,7 @@ feature -- Extra names
|
||||
orig_path_info: STRING = "ORIG_PATH_INFO"
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -77,8 +77,7 @@ feature -- Access: Input
|
||||
|
||||
input: WGI_INPUT_STREAM
|
||||
-- Server input channel
|
||||
require
|
||||
is_not_chunked_input: not is_chunked_input
|
||||
--| Could also be Chunked input, but this is transparent
|
||||
deferred
|
||||
end
|
||||
|
||||
@@ -87,13 +86,6 @@ feature -- Access: Input
|
||||
deferred
|
||||
end
|
||||
|
||||
chunked_input: detachable WGI_CHUNKED_INPUT_STREAM
|
||||
-- Chunked server input channel
|
||||
require
|
||||
is_chunked_input: is_chunked_input
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Access: CGI meta variables
|
||||
|
||||
meta_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
@@ -626,7 +618,7 @@ invariant
|
||||
path_info_identical: path_info ~ meta_string_variable ({WGI_META_NAMES}.path_info)
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -42,14 +42,6 @@ feature -- Status report
|
||||
deferred
|
||||
end
|
||||
|
||||
feature {WGI_RESPONSE} -- Core output operation
|
||||
|
||||
write (s: READABLE_STRING_8)
|
||||
-- Send the string `s'
|
||||
-- this can be used for header and body
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
status_is_set: BOOLEAN
|
||||
@@ -57,15 +49,17 @@ feature -- Status setting
|
||||
deferred
|
||||
end
|
||||
|
||||
set_status_code (a_code: INTEGER)
|
||||
-- Set response status code
|
||||
set_status_code (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
|
||||
-- Set response status code with custom `a_reason_phrase' if precised
|
||||
-- Should be done before sending any data back to the client
|
||||
require
|
||||
a_code_positive: a_code > 0
|
||||
status_not_set: not status_committed
|
||||
header_not_committed: not header_committed
|
||||
deferred
|
||||
ensure
|
||||
status_code_set: status_code = a_code
|
||||
status_reason_phrase_set: status_reason_phrase = a_reason_phrase
|
||||
status_set: status_is_set
|
||||
end
|
||||
|
||||
@@ -74,6 +68,13 @@ feature -- Status setting
|
||||
deferred
|
||||
end
|
||||
|
||||
status_reason_phrase: detachable READABLE_STRING_8
|
||||
-- Custom status reason phrase for the Response (optional)
|
||||
deferred
|
||||
ensure
|
||||
Result /= Void implies status_is_set
|
||||
end
|
||||
|
||||
feature -- Header output operation
|
||||
|
||||
put_header_text (a_text: READABLE_STRING_8)
|
||||
@@ -81,29 +82,27 @@ feature -- Header output operation
|
||||
-- It should not contain the ending CR LF CR LF
|
||||
-- since it is the duty of `put_header_text' to write it.
|
||||
require
|
||||
a_text_has_single_ending_crlf: a_text.count > 2 implies not a_text.substring (a_text.count - 2, a_text.count).same_string ("%R%N")
|
||||
a_text_does_not_has_ending_crlf_crlf: a_text.count > 4 implies not a_text.substring (a_text.count - 4, a_text.count).same_string ("%R%N%R%N")
|
||||
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
|
||||
|
||||
put_header_lines (a_lines: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
|
||||
require
|
||||
status_set: status_is_set
|
||||
header_not_committed: not header_committed
|
||||
deferred
|
||||
ensure
|
||||
status_set: status_is_set
|
||||
status_committed: status_committed
|
||||
header_committed: header_committed
|
||||
message_writable: message_writable
|
||||
end
|
||||
|
||||
feature -- Output operation
|
||||
|
||||
put_character (c: CHARACTER_8)
|
||||
-- Send the character `c'
|
||||
require
|
||||
message_writable: message_writable
|
||||
deferred
|
||||
end
|
||||
|
||||
put_string (s: READABLE_STRING_8)
|
||||
-- Send the string `s'
|
||||
require
|
||||
@@ -123,8 +122,16 @@ feature -- Output operation
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Error reporting
|
||||
|
||||
put_error (a_message: READABLE_STRING_8)
|
||||
-- Report error described by `a_message'
|
||||
-- This might be used by the underlying connector
|
||||
deferred
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -26,7 +26,7 @@ feature {WGI_CONNECTOR} -- Execution
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
@@ -1,15 +1,298 @@
|
||||
note
|
||||
description: "Summary description for {WGI_CHUNKED_INPUT_STREAM}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred
|
||||
class
|
||||
WGI_CHUNKED_INPUT_STREAM
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
inherit
|
||||
WGI_INPUT_STREAM
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
make (an_input: like input)
|
||||
do
|
||||
create last_string.make_empty
|
||||
create last_chunk.make_empty
|
||||
last_chunk_size := 0
|
||||
index := 0
|
||||
chunk_lower := 0
|
||||
chunk_upper := 0
|
||||
create tmp_hex_chunk_size.make_empty
|
||||
input := an_input
|
||||
end
|
||||
|
||||
feature -- Input
|
||||
|
||||
read_character
|
||||
-- Read the next character in input stream.
|
||||
-- Make the result available in `last_character'
|
||||
do
|
||||
index := index + 1
|
||||
if index > chunk_upper then
|
||||
read_chunk
|
||||
if last_chunk = Void then
|
||||
read_trailer
|
||||
end
|
||||
end
|
||||
last_character := last_chunk.item (index)
|
||||
end
|
||||
|
||||
read_string (nb: INTEGER)
|
||||
-- Read the next `nb' characters and
|
||||
-- make the string result available in `last_string'
|
||||
local
|
||||
i: like index
|
||||
do
|
||||
last_string.wipe_out
|
||||
if last_chunk_size = 0 then
|
||||
read_chunk
|
||||
end
|
||||
from
|
||||
index := index + 1
|
||||
i := index
|
||||
until
|
||||
i - index + 1 = nb or last_chunk_size = 0
|
||||
loop
|
||||
if i + nb - 1 <= chunk_upper then
|
||||
last_string.append (last_chunk.substring (i, i + nb - 1))
|
||||
i := i + nb - 1
|
||||
else
|
||||
-- Need to read new chunk
|
||||
-- first get all available data from current chunk
|
||||
if i <= chunk_upper then
|
||||
last_string.append (last_chunk.substring (i, chunk_upper))
|
||||
i := chunk_upper
|
||||
end
|
||||
-- then continue
|
||||
read_chunk
|
||||
end
|
||||
end
|
||||
if last_chunk_size = 0 then
|
||||
read_trailer
|
||||
end
|
||||
index := i
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_string: STRING_8
|
||||
-- Last string read.
|
||||
--
|
||||
-- Note: this query *might* return the same object.
|
||||
-- Therefore a clone should be used if the result
|
||||
-- is to be kept beyond the next call to this feature.
|
||||
-- However `last_string' is not shared between file objects.)
|
||||
|
||||
last_character: CHARACTER_8
|
||||
-- Last item read.
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_open_read: BOOLEAN
|
||||
-- Can items be read from input stream?
|
||||
do
|
||||
Result := input.is_open_read
|
||||
end
|
||||
|
||||
end_of_input: BOOLEAN
|
||||
-- Has the end of input stream been reached?
|
||||
do
|
||||
Result := input.end_of_input
|
||||
end
|
||||
|
||||
--feature -- Input
|
||||
|
||||
-- data: STRING_8
|
||||
-- local
|
||||
-- d: like internal_data
|
||||
-- do
|
||||
-- d := internal_data
|
||||
-- if d = Void then
|
||||
-- d := fetched_data
|
||||
-- internal_data := d
|
||||
-- end
|
||||
-- Result := d
|
||||
-- end
|
||||
|
||||
feature {NONE} -- Parser
|
||||
|
||||
index, chunk_lower, chunk_upper: INTEGER
|
||||
last_chunk_size: INTEGER
|
||||
last_chunk: STRING_8
|
||||
|
||||
-- internal_data: detachable STRING_8
|
||||
|
||||
tmp_hex_chunk_size: STRING_8
|
||||
|
||||
-- fetched_data: STRING_8
|
||||
-- -- Read all the data in a chunked stream.
|
||||
-- -- Make the result available in `last_chunked'.
|
||||
-- -- Chunked-Body = *chunk
|
||||
-- -- last-chunk
|
||||
-- -- trailer
|
||||
-- -- CRLF
|
||||
-- -- chunk = chunk-size [ chunk-extension ] CRLF
|
||||
-- -- chunk-data CRLF
|
||||
-- -- chunk-size = 1*HEX
|
||||
-- -- last-chunk = 1*("0") [ chunk-extension ] CRLF
|
||||
-- -- chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
|
||||
-- -- chunk-ext-name = token
|
||||
-- -- chunk-ext-val = token | quoted-string
|
||||
-- -- chunk-data = chunk-size(OCTET)
|
||||
-- -- trailer = *(entity-header CRLF)
|
||||
-- local
|
||||
-- eoc: BOOLEAN
|
||||
-- s: STRING_8
|
||||
-- do
|
||||
-- from
|
||||
-- create s.make (1024)
|
||||
-- until
|
||||
-- eoc
|
||||
-- loop
|
||||
-- read_chunk
|
||||
-- if attached last_chunk as l_last_chunk then
|
||||
-- s.append (l_last_chunk)
|
||||
-- else
|
||||
-- eoc := True
|
||||
-- end
|
||||
-- if last_chunk_size = 0 then
|
||||
-- eoc := True
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- read_trailer
|
||||
|
||||
-- Result := s
|
||||
-- end
|
||||
|
||||
read_chunk
|
||||
do
|
||||
chunk_lower := chunk_upper + 1
|
||||
last_chunk.wipe_out
|
||||
last_chunk_size := 0
|
||||
read_chunk_size
|
||||
if last_chunk_size > 0 then
|
||||
chunk_upper := chunk_upper + last_chunk_size
|
||||
read_chunk_data
|
||||
end
|
||||
ensure
|
||||
attached last_chunk as l_last_chunk implies l_last_chunk.count = chunk_upper - chunk_lower
|
||||
end
|
||||
|
||||
read_chunk_data
|
||||
require
|
||||
last_chunk.is_empty
|
||||
last_chunk_size > 0
|
||||
local
|
||||
l_input: like input
|
||||
do
|
||||
l_input := input
|
||||
l_input.read_string (last_chunk_size)
|
||||
last_chunk := l_input.last_string
|
||||
ensure
|
||||
last_chunk_attached: attached last_chunk as el_last_chunk
|
||||
last_chunk_size_ok: el_last_chunk.count = last_chunk_size
|
||||
end
|
||||
|
||||
read_chunk_size
|
||||
require
|
||||
tmp_hex_chunk_size_is_empty: tmp_hex_chunk_size.is_empty
|
||||
local
|
||||
eol : BOOLEAN
|
||||
c: CHARACTER
|
||||
hex : HEXADECIMAL_STRING_TO_INTEGER_CONVERTER
|
||||
l_input: like input
|
||||
do
|
||||
l_input := input
|
||||
from
|
||||
l_input.read_character
|
||||
until
|
||||
eol
|
||||
loop
|
||||
c := l_input.last_character
|
||||
inspect c
|
||||
when '%R' then
|
||||
-- We are in the end of the line, we need to read the next character to start the next line.
|
||||
eol := True
|
||||
l_input.read_character
|
||||
when ';' then
|
||||
-- We are in an extension chunk data
|
||||
read_extension_chunk
|
||||
else
|
||||
tmp_hex_chunk_size.append_character (c)
|
||||
l_input.read_character
|
||||
end
|
||||
end
|
||||
if tmp_hex_chunk_size.same_string ("0") then
|
||||
last_chunk_size := 0
|
||||
else
|
||||
create hex.make
|
||||
hex.parse_string_with_type (tmp_hex_chunk_size, hex.type_integer)
|
||||
if hex.parse_successful then
|
||||
last_chunk_size := hex.parsed_integer
|
||||
else
|
||||
last_chunk_size := 0 -- ERROR ...
|
||||
end
|
||||
end
|
||||
tmp_hex_chunk_size.wipe_out
|
||||
end
|
||||
|
||||
read_extension_chunk
|
||||
local
|
||||
l_input: like input
|
||||
do
|
||||
l_input := input
|
||||
debug
|
||||
print (" Reading extension chunk ")
|
||||
end
|
||||
from
|
||||
l_input.read_character
|
||||
until
|
||||
l_input.last_character = '%R'
|
||||
loop
|
||||
debug
|
||||
print (l_input.last_character)
|
||||
end
|
||||
l_input.read_character
|
||||
end
|
||||
end
|
||||
|
||||
read_trailer
|
||||
local
|
||||
l_input: like input
|
||||
do
|
||||
l_input := input
|
||||
if not l_input.end_of_input then
|
||||
debug
|
||||
print (" Reading trailer ")
|
||||
end
|
||||
from
|
||||
l_input.read_character
|
||||
until
|
||||
l_input.last_character = '%R'
|
||||
loop
|
||||
debug
|
||||
print (l_input.last_character)
|
||||
end
|
||||
l_input.read_character
|
||||
end
|
||||
-- read the LF
|
||||
l_input.read_character
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
input: WGI_INPUT_STREAM
|
||||
-- Input Stream
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
32
library/server/ewsgi/specification/stream/wgi_error_stream.e
Normal file
32
library/server/ewsgi/specification/stream/wgi_error_stream.e
Normal file
@@ -0,0 +1,32 @@
|
||||
note
|
||||
description : "[
|
||||
Objects that represents the error stream
|
||||
]"
|
||||
specification: "EWSGI/connector 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
|
||||
WGI_ERROR_STREAM
|
||||
|
||||
feature -- Output
|
||||
|
||||
put_error (a_message: READABLE_STRING_8)
|
||||
-- Report error described by `a_message'
|
||||
-- This might be used by the underlying connector
|
||||
deferred
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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
|
||||
@@ -2,6 +2,7 @@ note
|
||||
description : "[
|
||||
Objects that represents the input stream
|
||||
]"
|
||||
specification: "EWSGI/connector 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$"
|
||||
@@ -10,25 +11,154 @@ note
|
||||
deferred class
|
||||
WGI_INPUT_STREAM
|
||||
|
||||
feature -- Input
|
||||
|
||||
read_character
|
||||
-- Read the next character in input stream.
|
||||
-- Make the result available in `last_character'
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
deferred
|
||||
end
|
||||
|
||||
read_string (nb: INTEGER)
|
||||
-- Read the next `nb' characters and
|
||||
-- make the string result available in `last_string'
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
nb_large_enough: nb > 0
|
||||
deferred
|
||||
ensure
|
||||
last_string_count_small_enough: not end_of_input implies last_string.count <= nb
|
||||
character_read: not end_of_input implies last_string.count > 0
|
||||
end
|
||||
|
||||
read_to_string (a_string: STRING; pos, nb: INTEGER): INTEGER
|
||||
-- Fill `a_string', starting at position `pos', with
|
||||
-- at most `nb' characters read from input stream.
|
||||
-- Return the number of characters actually read.
|
||||
-- (Note that even if at least `nb' characters are available
|
||||
-- in the input stream, there is no guarantee that they
|
||||
-- will all be read.)
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
a_string_not_void: a_string /= Void
|
||||
valid_position: a_string.valid_index (pos)
|
||||
nb_large_enough: nb > 0
|
||||
nb_small_enough: nb <= a_string.count - pos + 1
|
||||
local
|
||||
i, end_pos: INTEGER
|
||||
do
|
||||
end_pos := pos + nb - 1
|
||||
from
|
||||
i := pos
|
||||
until
|
||||
i > end_pos
|
||||
loop
|
||||
read_character
|
||||
if not end_of_input then
|
||||
a_string.put (last_character, i)
|
||||
i := i + 1
|
||||
else
|
||||
Result := i - pos - nb
|
||||
-- Jump out of the loop.
|
||||
i := end_pos + 1
|
||||
end
|
||||
end
|
||||
Result := Result + i - pos
|
||||
ensure
|
||||
nb_char_read_large_enough: Result >= 0
|
||||
nb_char_read_small_enough: Result <= nb
|
||||
character_read: not end_of_input implies Result > 0
|
||||
end
|
||||
|
||||
append_to_string (a_string: STRING; nb: INTEGER)
|
||||
-- Append at most `nb' characters read from input stream
|
||||
-- to `a_string'
|
||||
-- Set `last_appended_count' to the number of characters actually read.
|
||||
-- (Note that even if at least `nb' characters are available
|
||||
-- in the input stream, there is no guarantee that they
|
||||
-- will all be read.)
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
a_string_not_void: a_string /= Void
|
||||
nb_large_enough: nb > 0
|
||||
local
|
||||
i, end_pos: INTEGER
|
||||
l_count: INTEGER
|
||||
do
|
||||
from
|
||||
i := a_string.count + 1
|
||||
end_pos := i + nb - 1
|
||||
a_string.grow (end_pos)
|
||||
until
|
||||
i > end_pos
|
||||
loop
|
||||
read_character
|
||||
if not end_of_input then
|
||||
a_string.extend (last_character)
|
||||
i := i + 1
|
||||
else
|
||||
l_count := i - nb
|
||||
-- Jump out of the loop.
|
||||
i := end_pos + 1
|
||||
end
|
||||
end
|
||||
last_appended_count := l_count + i
|
||||
ensure
|
||||
nb_char_read_large_enough: last_appended_count >= 0
|
||||
nb_char_read_small_enough: last_appended_count <= nb
|
||||
character_read: not end_of_input implies last_appended_count > 0
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_string: STRING_8
|
||||
-- Last read string from stream
|
||||
-- Last string read.
|
||||
--
|
||||
-- Note: this query *might* return the same object.
|
||||
-- Therefore a clone should be used if the result
|
||||
-- is to be kept beyond the next call to this feature.
|
||||
-- However `last_string' is not shared between file objects.)
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
deferred
|
||||
ensure
|
||||
last_string_not_void: Result /= Void
|
||||
end
|
||||
|
||||
last_character: CHARACTER_8
|
||||
-- Last item read.
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operation
|
||||
last_appended_count: INTEGER
|
||||
-- Count of characters actually read by last `append_to_string' call.
|
||||
|
||||
read_stream (n: INTEGER)
|
||||
require
|
||||
n_positive: n > 0
|
||||
feature -- Status report
|
||||
|
||||
is_open_read: BOOLEAN
|
||||
-- Can items be read from input stream?
|
||||
deferred
|
||||
end
|
||||
|
||||
end_of_input: BOOLEAN
|
||||
-- Has the end of input stream been reached?
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
deferred
|
||||
ensure
|
||||
at_max_n: last_string.count <= n
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -2,6 +2,7 @@ note
|
||||
description : "[
|
||||
Objects that represents the output stream
|
||||
]"
|
||||
specification: "EWSGI/connector 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$"
|
||||
@@ -10,48 +11,89 @@ note
|
||||
deferred class
|
||||
WGI_OUTPUT_STREAM
|
||||
|
||||
feature -- Core operation
|
||||
feature -- Output
|
||||
|
||||
put_string (s: STRING_8)
|
||||
-- Write `s' into the output stream
|
||||
put_string (a_string: READABLE_STRING_8)
|
||||
-- Write `a_string' to output stream.
|
||||
require
|
||||
s_not_empty: s /= Void and then not s.is_empty
|
||||
is_open_write: is_open_write
|
||||
a_string_not_void: a_string /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
flush
|
||||
-- Flush the output stream
|
||||
put_substring (a_string: READABLE_STRING_8; s, e: INTEGER)
|
||||
-- Write substring of `a_string' between indexes
|
||||
-- `s' and `e' to output stream.
|
||||
--| Could be redefined for optimization
|
||||
require
|
||||
is_open_write: is_open_write
|
||||
a_string_not_void: a_string /= Void
|
||||
s_large_enough: s >= 1
|
||||
e_small_enough: e <= a_string.count
|
||||
valid_interval: s <= e + 1
|
||||
do
|
||||
if s <= e then
|
||||
put_string (a_string.substring (s, e))
|
||||
end
|
||||
end
|
||||
|
||||
put_character (c: CHARACTER_8)
|
||||
-- Write `c' to output stream.
|
||||
--| Could be redefined for optimization
|
||||
require
|
||||
is_open_write: is_open_write
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Specific output
|
||||
|
||||
put_header_line (s: READABLE_STRING_8)
|
||||
-- Send `s' to http client as header line
|
||||
do
|
||||
put_string (s)
|
||||
put_crlf
|
||||
end
|
||||
|
||||
put_crlf
|
||||
-- Send "%R%N" string
|
||||
do
|
||||
put_string (crlf)
|
||||
end
|
||||
|
||||
feature -- Status writing
|
||||
|
||||
put_status_line (a_code: INTEGER)
|
||||
put_status_line (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
|
||||
-- Put status code line for `a_code'
|
||||
-- with custom `a_reason_phrase' if precised
|
||||
--| Note this is a default implementation, and could be redefined
|
||||
--| for instance in relation to NPH CGI script
|
||||
require
|
||||
a_code_positive: a_code > 0
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operation
|
||||
feature -- Status report
|
||||
|
||||
put_substring (s: STRING; start_index, end_index: INTEGER)
|
||||
-- Write `s[start_index:end_index]' into the output stream
|
||||
is_open_write: BOOLEAN
|
||||
-- Can items be written to output stream?
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
flush
|
||||
-- Flush buffered data to disk.
|
||||
require
|
||||
s_not_empty: s /= Void and then not s.is_empty
|
||||
do
|
||||
put_string (s.substring (start_index, end_index))
|
||||
is_open_write: is_open_write
|
||||
deferred
|
||||
end
|
||||
|
||||
put_header_line (s: STRING)
|
||||
-- Send `s' to http client as header line
|
||||
do
|
||||
put_string (s)
|
||||
put_string ("%R%N")
|
||||
end
|
||||
feature -- Constant
|
||||
|
||||
crlf: STRING = "%R%N"
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {WGI_SERVICE}."
|
||||
legal: "See notice at end of class."
|
||||
status: "See notice at end of class."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WGI_SERVICE
|
||||
|
||||
feature {NONE} -- Execution
|
||||
|
||||
execute (req: WGI_REQUEST; res: WGI_RESPONSE)
|
||||
-- Execute the request
|
||||
-- See `req.input' for input stream
|
||||
-- `req.environment' for the Gateway environment
|
||||
-- and `res' for the output buffer
|
||||
require
|
||||
res_status_unset: not res.status_is_set
|
||||
deferred
|
||||
ensure
|
||||
res_status_set: res.status_is_set
|
||||
res_committed: res.message_committed
|
||||
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
|
||||
@@ -27,9 +27,18 @@ feature {NONE} -- Initialization
|
||||
input := a_input
|
||||
set_meta_variables (a_vars)
|
||||
update_path_info
|
||||
if attached http_transfer_encoding as l_transfer_encoding and then l_transfer_encoding.same_string ("chunked") then
|
||||
update_input
|
||||
end
|
||||
|
||||
update_input
|
||||
-- Update input, depending on Transfer-Encoding value.
|
||||
do
|
||||
if
|
||||
attached http_transfer_encoding as l_transfer_encoding and then
|
||||
l_transfer_encoding.same_string (once "chunked")
|
||||
then
|
||||
is_chunked_input := True
|
||||
create chunked_input.make (a_input)
|
||||
create {WGI_CHUNKED_INPUT_STREAM} input.make (input)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,9 +49,7 @@ feature -- Access: Input
|
||||
|
||||
input: WGI_INPUT_STREAM
|
||||
-- Server input channel
|
||||
|
||||
chunked_input: detachable WGI_CHUNKED_INPUT_STREAM
|
||||
-- Chunked server input channel
|
||||
--| Could be a chunked input as well
|
||||
|
||||
feature -- EWSGI access
|
||||
|
||||
@@ -244,8 +251,10 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO
|
||||
table: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
|
||||
l_query_string: like query_string
|
||||
l_request_uri: detachable STRING_32
|
||||
l_empty_string: like empty_string
|
||||
do
|
||||
create {STRING_8} empty_string.make_empty
|
||||
create {STRING_8} l_empty_string.make_empty
|
||||
empty_string := l_empty_string
|
||||
|
||||
create table.make (a_vars.count)
|
||||
table.compare_objects
|
||||
@@ -260,11 +269,11 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO
|
||||
end
|
||||
|
||||
--| QUERY_STRING
|
||||
l_query_string := meta_string_variable_or_default ({WGI_META_NAMES}.query_string, empty_string, False)
|
||||
l_query_string := meta_string_variable_or_default ({WGI_META_NAMES}.query_string, l_empty_string, False)
|
||||
query_string := l_query_string
|
||||
|
||||
--| REQUEST_METHOD
|
||||
request_method := meta_string_variable_or_default ({WGI_META_NAMES}.request_method, empty_string, False)
|
||||
request_method := meta_string_variable_or_default ({WGI_META_NAMES}.request_method, l_empty_string, False)
|
||||
|
||||
--| CONTENT_TYPE
|
||||
s := meta_string_variable ({WGI_META_NAMES}.content_type)
|
||||
@@ -278,10 +287,10 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO
|
||||
content_length := meta_string_variable ({WGI_META_NAMES}.content_length)
|
||||
|
||||
--| PATH_INFO
|
||||
path_info := meta_string_variable_or_default ({WGI_META_NAMES}.path_info, empty_string, False)
|
||||
path_info := meta_string_variable_or_default ({WGI_META_NAMES}.path_info, l_empty_string, False)
|
||||
|
||||
--| SERVER_NAME
|
||||
server_name := meta_string_variable_or_default ({WGI_META_NAMES}.server_name, empty_string, False)
|
||||
server_name := meta_string_variable_or_default ({WGI_META_NAMES}.server_name, l_empty_string, False)
|
||||
|
||||
--| SERVER_PORT
|
||||
s := meta_string_variable ({WGI_META_NAMES}.server_port)
|
||||
@@ -292,13 +301,13 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO
|
||||
end
|
||||
|
||||
--| SCRIPT_NAME
|
||||
script_name := meta_string_variable_or_default ({WGI_META_NAMES}.script_name, empty_string, False)
|
||||
script_name := meta_string_variable_or_default ({WGI_META_NAMES}.script_name, l_empty_string, False)
|
||||
|
||||
--| REMOTE_ADDR
|
||||
remote_addr := meta_string_variable_or_default ({WGI_META_NAMES}.remote_addr, empty_string, False)
|
||||
remote_addr := meta_string_variable_or_default ({WGI_META_NAMES}.remote_addr, l_empty_string, False)
|
||||
|
||||
--| REMOTE_HOST
|
||||
remote_host := meta_string_variable_or_default ({WGI_META_NAMES}.remote_host, empty_string, False)
|
||||
remote_host := meta_string_variable_or_default ({WGI_META_NAMES}.remote_host, l_empty_string, False)
|
||||
|
||||
--| REQUEST_URI
|
||||
s := meta_string_variable ({WGI_META_NAMES}.request_uri)
|
||||
@@ -358,6 +367,12 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO
|
||||
|
||||
feature {NONE} -- Implementation: utilities
|
||||
|
||||
has_white_space (s: READABLE_STRING_8): BOOLEAN
|
||||
-- `s' has white space?
|
||||
do
|
||||
Result := s.has (' ') or else s.has ('%T')
|
||||
end
|
||||
|
||||
single_slash_starting_string (s: READABLE_STRING_8): STRING_8
|
||||
-- Return the string `s' (or twin) with one and only one starting slash
|
||||
local
|
||||
@@ -411,7 +426,7 @@ invariant
|
||||
empty_string_unchanged: empty_string.is_empty
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -17,9 +17,10 @@ create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_output: like output)
|
||||
make (a_output: like output; a_error: like error)
|
||||
do
|
||||
output := a_output
|
||||
error := a_error
|
||||
end
|
||||
|
||||
feature {WGI_CONNECTOR, WGI_SERVICE} -- Commit
|
||||
@@ -48,68 +49,51 @@ feature -- Status report
|
||||
Result := status_is_set and header_committed
|
||||
end
|
||||
|
||||
feature {NONE} -- Core output operation
|
||||
|
||||
write (s: READABLE_STRING_8)
|
||||
-- Send the content of `s'
|
||||
-- this can be used for header and body
|
||||
do
|
||||
output.put_string (s)
|
||||
end
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
status_is_set: BOOLEAN
|
||||
-- Is status set?
|
||||
do
|
||||
Result := status_code /= 0
|
||||
Result := status_code > 0
|
||||
end
|
||||
|
||||
set_status_code (a_code: INTEGER)
|
||||
set_status_code (a_code: INTEGER; a_reason_phrase: detachable READABLE_STRING_8)
|
||||
-- Set response status code
|
||||
-- Should be done before sending any data back to the client
|
||||
do
|
||||
status_code := a_code
|
||||
output.put_status_line (a_code)
|
||||
status_reason_phrase := a_reason_phrase
|
||||
output.put_status_line (a_code, a_reason_phrase)
|
||||
status_committed := True
|
||||
end
|
||||
|
||||
status_code: INTEGER
|
||||
-- Response status
|
||||
|
||||
status_reason_phrase: detachable READABLE_STRING_8
|
||||
-- Custom status reason phrase for the Response (optional)
|
||||
|
||||
feature -- Header output operation
|
||||
|
||||
put_header_text (a_text: READABLE_STRING_8)
|
||||
do
|
||||
write (a_text)
|
||||
write (crlf)
|
||||
output.put_string (a_text)
|
||||
output.put_crlf
|
||||
header_committed := True
|
||||
end
|
||||
|
||||
put_header_lines (a_lines: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]])
|
||||
local
|
||||
h: STRING_8
|
||||
do
|
||||
create h.make (256)
|
||||
across
|
||||
a_lines as c
|
||||
loop
|
||||
h.append (c.item.name)
|
||||
h.append_character (':')
|
||||
h.append_character (' ')
|
||||
h.append (c.item.value)
|
||||
h.append_character ('%R')
|
||||
h.append_character ('%N')
|
||||
end
|
||||
put_header_text (h)
|
||||
end
|
||||
|
||||
feature -- Output operation
|
||||
|
||||
put_character (c: CHARACTER_8)
|
||||
-- Send the character `c'
|
||||
do
|
||||
output.put_character (c)
|
||||
end
|
||||
|
||||
put_string (s: READABLE_STRING_8)
|
||||
-- Send the string `s'
|
||||
do
|
||||
write (s)
|
||||
output.put_string (s)
|
||||
end
|
||||
|
||||
put_substring (s: READABLE_STRING_8; start_index, end_index: INTEGER)
|
||||
@@ -124,16 +108,27 @@ feature -- Output operation
|
||||
output.flush
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation: Access
|
||||
feature -- Error reporting
|
||||
|
||||
crlf: STRING = "%R%N"
|
||||
-- End of header
|
||||
put_error (a_message: READABLE_STRING_8)
|
||||
-- Report error described by `a_message'
|
||||
-- This might be used by the underlying connector
|
||||
do
|
||||
if attached error as err then
|
||||
err.put_error (a_message)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation: Access
|
||||
|
||||
output: WGI_OUTPUT_STREAM
|
||||
-- Server output channel
|
||||
|
||||
error: detachable WGI_ERROR_STREAM
|
||||
-- Server output channel
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -36,7 +36,7 @@ invariant
|
||||
callback_attached: callback /= Void
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
note
|
||||
description: "Summary description for {WGI_CHUNKED_INPUT_STREAM}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
WGI_CHUNKED_INPUT_STREAM
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
make (an_input: like input)
|
||||
do
|
||||
create tmp_hex_chunk_size.make_empty
|
||||
input := an_input
|
||||
end
|
||||
|
||||
feature -- Input
|
||||
|
||||
data: STRING_8
|
||||
local
|
||||
d: like internal_data
|
||||
do
|
||||
d := internal_data
|
||||
if d = Void then
|
||||
d := fetched_data
|
||||
internal_data := d
|
||||
end
|
||||
Result := d
|
||||
end
|
||||
|
||||
feature {NONE} -- Parser
|
||||
|
||||
internal_data: detachable STRING_8
|
||||
|
||||
tmp_hex_chunk_size: STRING_8
|
||||
last_chunk_size: INTEGER
|
||||
last_chunk: detachable STRING_8
|
||||
|
||||
fetched_data: STRING_8
|
||||
-- Read all the data in a chunked stream.
|
||||
-- Make the result available in `last_chunked'.
|
||||
-- Chunked-Body = *chunk
|
||||
-- last-chunk
|
||||
-- trailer
|
||||
-- CRLF
|
||||
-- chunk = chunk-size [ chunk-extension ] CRLF
|
||||
-- chunk-data CRLF
|
||||
-- chunk-size = 1*HEX
|
||||
-- last-chunk = 1*("0") [ chunk-extension ] CRLF
|
||||
-- chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
|
||||
-- chunk-ext-name = token
|
||||
-- chunk-ext-val = token | quoted-string
|
||||
-- chunk-data = chunk-size(OCTET)
|
||||
-- trailer = *(entity-header CRLF)
|
||||
local
|
||||
eoc: BOOLEAN
|
||||
s: STRING_8
|
||||
do
|
||||
from
|
||||
create s.make (1024)
|
||||
until
|
||||
eoc
|
||||
loop
|
||||
read_chunk
|
||||
if attached last_chunk as l_last_chunk then
|
||||
s.append (l_last_chunk)
|
||||
else
|
||||
eoc := True
|
||||
end
|
||||
if last_chunk_size = 0 then
|
||||
eoc := True
|
||||
end
|
||||
end
|
||||
|
||||
read_trailer
|
||||
|
||||
Result := s
|
||||
end
|
||||
|
||||
reset_chunk
|
||||
do
|
||||
last_chunk := Void
|
||||
last_chunk_size := 0
|
||||
end
|
||||
|
||||
read_chunk
|
||||
do
|
||||
reset_chunk
|
||||
read_chunk_size
|
||||
if last_chunk_size > 0 then
|
||||
read_chunk_data
|
||||
end
|
||||
end
|
||||
|
||||
read_chunk_data
|
||||
require
|
||||
last_chunk_size > 0
|
||||
do
|
||||
input.read_string (last_chunk_size)
|
||||
last_chunk := input.last_string
|
||||
|
||||
-- read CRLF
|
||||
input.read_character
|
||||
if input.last_character = '%R' then
|
||||
input.read_character
|
||||
end
|
||||
ensure
|
||||
last_chunk_attached: attached last_chunk as el_last_chunk
|
||||
last_chunk_size_ok: el_last_chunk.count = last_chunk_size
|
||||
end
|
||||
|
||||
read_chunk_size
|
||||
require
|
||||
tmp_hex_chunk_size_is_empty: tmp_hex_chunk_size.is_empty
|
||||
local
|
||||
eol : BOOLEAN
|
||||
c: CHARACTER
|
||||
hex : HEXADECIMAL_STRING_TO_INTEGER_CONVERTER
|
||||
do
|
||||
from
|
||||
input.read_character
|
||||
until
|
||||
eol
|
||||
loop
|
||||
c := input.last_character
|
||||
inspect c
|
||||
when '%R' then
|
||||
-- We are in the end of the line, we need to read the next character to start the next line.
|
||||
eol := True
|
||||
input.read_character
|
||||
when ';' then
|
||||
-- We are in an extension chunk data
|
||||
read_extension_chunk
|
||||
else
|
||||
tmp_hex_chunk_size.append_character (c)
|
||||
input.read_character
|
||||
end
|
||||
end
|
||||
if tmp_hex_chunk_size.same_string ("0") then
|
||||
last_chunk_size := 0
|
||||
else
|
||||
create hex.make
|
||||
hex.parse_string_with_type (tmp_hex_chunk_size, hex.type_integer)
|
||||
if hex.parse_successful then
|
||||
last_chunk_size := hex.parsed_integer
|
||||
else
|
||||
last_chunk_size := 0 -- ERROR ...
|
||||
end
|
||||
end
|
||||
tmp_hex_chunk_size.wipe_out
|
||||
end
|
||||
|
||||
read_extension_chunk
|
||||
do
|
||||
debug
|
||||
print (" Reading extension chunk ")
|
||||
end
|
||||
from
|
||||
input.read_character
|
||||
until
|
||||
input.last_character = '%R'
|
||||
loop
|
||||
debug
|
||||
print (input.last_character)
|
||||
end
|
||||
input.read_character
|
||||
end
|
||||
end
|
||||
|
||||
read_trailer
|
||||
do
|
||||
if not input.end_of_input then
|
||||
debug
|
||||
print (" Reading trailer ")
|
||||
end
|
||||
from
|
||||
input.read_character
|
||||
until
|
||||
input.last_character = '%R'
|
||||
loop
|
||||
debug
|
||||
print (input.last_character)
|
||||
end
|
||||
input.read_character
|
||||
end
|
||||
-- read the LF
|
||||
input.read_character
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
input: WGI_INPUT_STREAM
|
||||
-- Input Stream
|
||||
|
||||
;note
|
||||
copyright: "2011-2012, 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
|
||||
@@ -1,128 +0,0 @@
|
||||
note
|
||||
description : "[
|
||||
Objects that represents the input stream
|
||||
]"
|
||||
specification: "EWSGI/connector 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
|
||||
WGI_INPUT_STREAM
|
||||
|
||||
feature -- Input
|
||||
|
||||
read_character
|
||||
-- Read the next character in input stream.
|
||||
-- Make the result available in `last_character'.
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
deferred
|
||||
ensure
|
||||
same_last_string_reference: last_string = old last_string
|
||||
end
|
||||
|
||||
read_string (nb: INTEGER)
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
nb_large_enough: nb > 0
|
||||
deferred
|
||||
ensure
|
||||
last_string_count_small_enough: not end_of_input implies last_string.count <= nb
|
||||
character_read: not end_of_input implies last_string.count > 0
|
||||
same_last_string_reference: last_string = old last_string
|
||||
end
|
||||
|
||||
read_to_string (a_string: STRING; pos, nb: INTEGER): INTEGER
|
||||
-- Fill `a_string', starting at position `pos', with
|
||||
-- at most `nb' characters read from input stream.
|
||||
-- Return the number of characters actually read.
|
||||
-- (Note that even if at least `nb' characters are available
|
||||
-- in the input stream, there is no guarantee that they
|
||||
-- will all be read.)
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
a_string_not_void: a_string /= Void
|
||||
valid_position: a_string.valid_index (pos)
|
||||
nb_large_enough: nb > 0
|
||||
nb_small_enough: nb <= a_string.count - pos + 1
|
||||
local
|
||||
i, end_pos: INTEGER
|
||||
do
|
||||
end_pos := pos + nb - 1
|
||||
from
|
||||
i := pos
|
||||
until
|
||||
i > end_pos
|
||||
loop
|
||||
read_character
|
||||
if not end_of_input then
|
||||
a_string.put (last_character, i)
|
||||
i := i + 1
|
||||
else
|
||||
Result := i - pos - nb
|
||||
-- Jump out of the loop.
|
||||
i := end_pos + 1
|
||||
end
|
||||
end
|
||||
Result := Result + i - pos
|
||||
ensure
|
||||
nb_char_read_large_enough: Result >= 0
|
||||
nb_char_read_small_enough: Result <= nb
|
||||
character_read: not end_of_input implies Result > 0
|
||||
same_last_string_reference: last_string = old last_string
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_string: STRING_8
|
||||
-- Last string read
|
||||
-- (Note: this query always return the same object.
|
||||
-- Therefore a clone should be used if the result
|
||||
-- is to be kept beyond the next call to this feature.
|
||||
-- However `last_string' is not shared between file objects.)
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
deferred
|
||||
ensure
|
||||
last_string_not_void: Result /= Void
|
||||
end
|
||||
|
||||
last_character: CHARACTER_8
|
||||
-- Last item read
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
not_end_of_input: not end_of_input
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_open_read: BOOLEAN
|
||||
-- Can items be read from input stream?
|
||||
deferred
|
||||
end
|
||||
|
||||
end_of_input: BOOLEAN
|
||||
-- Has the end of input stream been reached?
|
||||
require
|
||||
is_open_read: is_open_read
|
||||
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
|
||||
@@ -1,93 +0,0 @@
|
||||
note
|
||||
description : "[
|
||||
Objects that represents the output stream
|
||||
]"
|
||||
specification: "EWSGI/connector 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
|
||||
WGI_OUTPUT_STREAM
|
||||
|
||||
feature -- Output
|
||||
|
||||
put_string (a_string: READABLE_STRING_8)
|
||||
-- Write `a_string' to output stream.
|
||||
require
|
||||
is_open_write: is_open_write
|
||||
a_string_not_void: a_string /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
put_substring (a_string: READABLE_STRING_8; s, e: INTEGER)
|
||||
-- Write substring of `a_string' between indexes
|
||||
-- `s' and `e' to output stream.
|
||||
--| Could be redefined for optimization
|
||||
require
|
||||
is_open_write: is_open_write
|
||||
a_string_not_void: a_string /= Void
|
||||
s_large_enough: s >= 1
|
||||
e_small_enough: e <= a_string.count
|
||||
valid_interval: s <= e + 1
|
||||
do
|
||||
if s <= e then
|
||||
put_string (a_string.substring (s, e))
|
||||
end
|
||||
end
|
||||
|
||||
put_character_8 (c: CHARACTER_8)
|
||||
-- Write `c' to output stream.
|
||||
--| Could be redefined for optimization
|
||||
require
|
||||
is_open_write: is_open_write
|
||||
do
|
||||
put_string (c.out)
|
||||
end
|
||||
|
||||
feature -- Specific output
|
||||
|
||||
put_header_line (s: READABLE_STRING_8)
|
||||
-- Send `s' to http client as header line
|
||||
do
|
||||
put_string (s)
|
||||
put_string ("%R%N")
|
||||
end
|
||||
|
||||
feature -- Status writing
|
||||
|
||||
put_status_line (a_code: INTEGER)
|
||||
-- Put status code line for `a_code'
|
||||
--| Note this is a default implementation, and could be redefined
|
||||
--| for instance in relation to NPH CGI script
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_open_write: BOOLEAN
|
||||
-- Can items be written to output stream?
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
flush
|
||||
-- Flush buffered data to disk.
|
||||
require
|
||||
is_open_write: is_open_write
|
||||
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
|
||||
@@ -55,6 +55,14 @@ feature -- FCGI output
|
||||
io.put_string (a_str)
|
||||
end
|
||||
|
||||
feature -- Error
|
||||
|
||||
put_error (a_str: READABLE_STRING_8)
|
||||
-- Put `a_str' on the FastCGI stdout.
|
||||
do
|
||||
io.error.put_string (a_str)
|
||||
end
|
||||
|
||||
feature -- FCGI Input
|
||||
|
||||
read_from_stdin (n: INTEGER)
|
||||
|
||||
@@ -96,6 +96,15 @@ feature -- Output
|
||||
"FCGI_fwrite($v, 1, $n, FCGI_stdout);"
|
||||
end
|
||||
|
||||
feature -- Error
|
||||
|
||||
put_error (v: POINTER; n: INTEGER)
|
||||
external
|
||||
"C inline use %"fcgi_stdio.h%""
|
||||
alias
|
||||
"FCGI_fwrite($v, 1, $n, FCGI_stderr);"
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
stdout: POINTER
|
||||
@@ -114,6 +123,14 @@ feature -- Access
|
||||
"FCGI_stdin"
|
||||
end
|
||||
|
||||
stderr: POINTER
|
||||
-- FCGI_stderr() return pointer on error FCGI_FILE
|
||||
external
|
||||
"C inline use %"fcgi_stdio.h%""
|
||||
alias
|
||||
"FCGI_stderr"
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -77,6 +77,18 @@ feature -- FCGI output
|
||||
{FCGI_C_API}.put_string (l_c_str.item, l_c_str.count)
|
||||
end
|
||||
|
||||
feature -- Error
|
||||
|
||||
put_error (a_message: READABLE_STRING_8)
|
||||
-- Put error message `a_message' on the FastCGI stderr
|
||||
local
|
||||
l_c_str: C_STRING
|
||||
do
|
||||
l_c_str := c_buffer
|
||||
l_c_str.set_string (a_message)
|
||||
fcgi.put_error (l_c_str.item, l_c_str.count)
|
||||
end
|
||||
|
||||
feature -- FCGI Input
|
||||
|
||||
copy_from_stdin (n: INTEGER; tf: FILE)
|
||||
|
||||
@@ -101,6 +101,15 @@ feature -- Output
|
||||
i := fwrite (v, 1, n, stdout)
|
||||
end
|
||||
|
||||
feature -- Error
|
||||
|
||||
put_error (v: POINTER; n: INTEGER)
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
i := fwrite (v, 1, n, stderr)
|
||||
end
|
||||
|
||||
feature {NONE} -- Output
|
||||
|
||||
fwrite (v: POINTER; a_size: INTEGER; n: INTEGER; fp: POINTER): INTEGER
|
||||
@@ -129,6 +138,15 @@ feature -- Access
|
||||
"FCGI_stdin"
|
||||
end
|
||||
|
||||
stderr: POINTER
|
||||
-- FCGI_stderr() return pointer on error FCGI_FILE
|
||||
external
|
||||
"C inline use %"fcgi_stdio.h%""
|
||||
alias
|
||||
"FCGI_stderr"
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -136,6 +136,18 @@ feature -- FCGI output
|
||||
fcgi.put_string (l_c_str.item, l_c_str.count)
|
||||
end
|
||||
|
||||
feature -- Error
|
||||
|
||||
put_error (a_message: READABLE_STRING_8)
|
||||
-- Put error message `a_message' on the FastCGI stderr
|
||||
local
|
||||
l_c_str: C_STRING
|
||||
do
|
||||
l_c_str := c_buffer
|
||||
l_c_str.set_string (a_message)
|
||||
fcgi.put_error (l_c_str.item, l_c_str.count)
|
||||
end
|
||||
|
||||
feature -- FCGI input
|
||||
|
||||
copy_from_stdin (n: INTEGER; f: FILE)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
${NOTE_KEYWORD}
|
||||
copyright: "2011-${YEAR}, Eiffel Software and others"
|
||||
copyright: "2011-${YEAR}, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
30
library/server/wsf/connector/all-safe.ecf
Normal file
30
library/server/wsf/connector/all-safe.ecf
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="wsf_all" uuid="223E2E7D-AA90-4ADC-93CB-D304E794E3E6" library_target="wsf_all">
|
||||
<target name="wsf_all">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="ewsgi" location="../../ewsgi/ewsgi-safe.ecf"/>
|
||||
<library name="wsf" location="../wsf-safe.ecf"/>
|
||||
<library name="connector_cgi" location="../../ewsgi/connectors/cgi/cgi-safe.ecf"/>
|
||||
<library name="connector_libfcgi" location="../../ewsgi/connectors/libfcgi/libfcgi-safe.ecf"/>
|
||||
<library name="connector_nino" location="../../ewsgi/connectors/nino/nino-safe.ecf"/>
|
||||
<library name="nino" location="..\..\..\..\contrib\library\server\nino\nino-safe.ecf" readonly="false">
|
||||
<renaming old_name="HTTP_CONSTANTS" new_name="NINO_HTTP_CONSTANTS"/>
|
||||
</library>
|
||||
|
||||
<library name="error" location="..\..\..\error\error-safe.ecf"/>
|
||||
<library name="http" location="..\..\..\protocol\http\http-safe.ecf"/>
|
||||
<library name="encoder" location="..\..\..\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<cluster name="wsf_nino" location="./nino" recursive="true"/>
|
||||
<cluster name="wsf_cgi" location="./cgi" recursive="true"/>
|
||||
<cluster name="wsf_libfcgi" location="./libfcgi" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
22
library/server/wsf/connector/cgi-safe.ecf
Normal file
22
library/server/wsf/connector/cgi-safe.ecf
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="wsf_cgi" uuid="1B416A7F-D49B-43FC-8308-F14AA9531AF8" library_target="wsf_cgi">
|
||||
<target name="wsf_cgi">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="ewsgi" location="../../ewsgi/ewsgi-safe.ecf"/>
|
||||
<library name="wsf" location="../wsf-safe.ecf"/>
|
||||
<library name="connector_cgi" location="../../ewsgi/connectors/cgi/cgi-safe.ecf"/>
|
||||
<library name="error" location="..\..\..\error\error-safe.ecf"/>
|
||||
<library name="http" location="..\..\..\protocol\http\http-safe.ecf"/>
|
||||
<library name="encoder" location="..\..\..\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<cluster name="wsf_cgi" location="./cgi" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user