Applied recent changes on WGI_ and WSF_
Moved classes away from ewsgi, restructured, cleaned
This commit is contained in:
22
library/server/wsf/default/cgi-safe.ecf
Normal file
22
library/server/wsf/default/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="default_cgi" uuid="A9137009-B5BA-4C58-BCD3-7753909918B5" library_target="default_cgi">
|
||||
<target name="default_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="default_cgi" location="./cgi" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
22
library/server/wsf/default/cgi.ecf
Normal file
22
library/server/wsf/default/cgi.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="default_cgi" uuid="A9137009-B5BA-4C58-BCD3-7753909918B5" library_target="default_cgi">
|
||||
<target name="default_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" syntax="provisional">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<library name="ewsgi" location="../../ewsgi/ewsgi.ecf"/>
|
||||
<library name="wsf" location="../wsf.ecf"/>
|
||||
<library name="connector_cgi" location="../../ewsgi/connectors/cgi/cgi.ecf"/>
|
||||
<library name="error" location="..\..\..\error\error.ecf"/>
|
||||
<library name="http" location="..\..\..\protocol\http\http.ecf"/>
|
||||
<library name="encoder" location="..\..\..\text\encoder\encoder.ecf" readonly="false"/>
|
||||
<cluster name="default_cgi" location="./cgi" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
32
library/server/wsf/default/cgi/default_application.e
Normal file
32
library/server/wsf/default/cgi/default_application.e
Normal file
@@ -0,0 +1,32 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_APPLICATION}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
DEFAULT_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_APPLICATION
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_and_launch
|
||||
local
|
||||
cgi: WGI_CGI_CONNECTOR
|
||||
do
|
||||
create cgi.make (Current)
|
||||
cgi.launch
|
||||
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
|
||||
26
library/server/wsf/default/nino-safe.ecf
Normal file
26
library/server/wsf/default/nino-safe.ecf
Normal file
@@ -0,0 +1,26 @@
|
||||
<?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="default_nino" uuid="ACBEDC97-956C-45F5-97E3-65A6D9987625" library_target="default_nino">
|
||||
<target name="default_nino">
|
||||
<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_nino" location="../../ewsgi/connectors/nino/nino-safe.ecf"/>
|
||||
<library name="nino" location="..\..\..\..\ext\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="default_nino" location="./nino" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
26
library/server/wsf/default/nino.ecf
Normal file
26
library/server/wsf/default/nino.ecf
Normal file
@@ -0,0 +1,26 @@
|
||||
<?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="default_nino" uuid="ACBEDC97-956C-45F5-97E3-65A6D9987625" library_target="default_nino">
|
||||
<target name="default_nino">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" syntax="provisional">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<library name="ewsgi" location="../../ewsgi/ewsgi.ecf"/>
|
||||
<library name="wsf" location="../wsf.ecf"/>
|
||||
<library name="connector_nino" location="../../ewsgi/connectors/nino/nino.ecf"/>
|
||||
<library name="nino" location="..\..\..\..\ext\server\nino\nino.ecf" readonly="false">
|
||||
<renaming old_name="HTTP_CONSTANTS" new_name="NINO_HTTP_CONSTANTS"/>
|
||||
</library>
|
||||
|
||||
<library name="error" location="..\..\..\error\error.ecf"/>
|
||||
<library name="http" location="..\..\..\protocol\http\http.ecf"/>
|
||||
<library name="encoder" location="..\..\..\text\encoder\encoder.ecf" readonly="false"/>
|
||||
<cluster name="default_nino" location="./nino" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
44
library/server/wsf/default/nino/default_application.e
Normal file
44
library/server/wsf/default/nino/default_application.e
Normal file
@@ -0,0 +1,44 @@
|
||||
note
|
||||
description: "Summary description for {DEFAULT_APPLICATION}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
DEFAULT_APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_APPLICATION
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_and_launch
|
||||
local
|
||||
app: NINO_APPLICATION
|
||||
do
|
||||
port_number := 8080
|
||||
base_url := ""
|
||||
debug ("nino")
|
||||
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)
|
||||
app.listen (port_number)
|
||||
end
|
||||
|
||||
port_number: INTEGER
|
||||
|
||||
base_url: STRING
|
||||
|
||||
invariant
|
||||
port_number_valid: port_number > 0
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
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
|
||||
@@ -23,424 +23,12 @@ class
|
||||
WSF_HEADER
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
HTTP_STATUS_CODE_MESSAGES --| useful for `put_status'
|
||||
export
|
||||
{NONE} all
|
||||
end
|
||||
EWF_HEADER
|
||||
|
||||
create
|
||||
make,
|
||||
make_with_count
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize current
|
||||
do
|
||||
make_with_count (3)
|
||||
end
|
||||
|
||||
make_with_count (n: INTEGER)
|
||||
-- Make with a capacity of `n' header entries
|
||||
do
|
||||
create {ARRAYED_LIST [READABLE_STRING_8]} headers.make (n)
|
||||
end
|
||||
|
||||
feature -- Recycle
|
||||
|
||||
recycle
|
||||
-- Recycle current object
|
||||
do
|
||||
headers.wipe_out
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
headers: LIST [READABLE_STRING_8]
|
||||
-- Header's lines
|
||||
|
||||
string: STRING
|
||||
-- String representation of the headers
|
||||
local
|
||||
l_headers: like headers
|
||||
do
|
||||
create Result.make (32)
|
||||
l_headers := headers
|
||||
if l_headers.is_empty then
|
||||
put_content_type_text_html -- See if this make sense to define a default content-type
|
||||
else
|
||||
from
|
||||
l_headers.start
|
||||
until
|
||||
l_headers.after
|
||||
loop
|
||||
append_line_to (l_headers.item, Result)
|
||||
l_headers.forth
|
||||
end
|
||||
end
|
||||
append_end_of_line_to (Result)
|
||||
end
|
||||
|
||||
feature -- Header change: general
|
||||
|
||||
add_header (h: READABLE_STRING_8)
|
||||
-- Add header `h'
|
||||
-- if it already exists, there will be multiple header with same name
|
||||
-- which can also be valid
|
||||
require
|
||||
h_not_empty: not h.is_empty
|
||||
do
|
||||
headers.force (h)
|
||||
end
|
||||
|
||||
put_header (h: READABLE_STRING_8)
|
||||
-- Add header `h' or replace existing header of same header name
|
||||
require
|
||||
h_not_empty: not h.is_empty
|
||||
do
|
||||
force_header_by_name (header_name (h), h)
|
||||
end
|
||||
|
||||
add_header_key_value (k,v: READABLE_STRING_8)
|
||||
-- Add header `k:v', or replace existing header of same header name/key
|
||||
do
|
||||
add_header (k + colon_space + v)
|
||||
end
|
||||
|
||||
put_header_key_value (k,v: READABLE_STRING_8)
|
||||
-- Add header `k:v', or replace existing header of same header name/key
|
||||
do
|
||||
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)
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t)
|
||||
end
|
||||
|
||||
add_content_type (t: READABLE_STRING_8)
|
||||
-- same as `put_content_type', but allow multiple definition of "Content-Type"
|
||||
do
|
||||
add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t)
|
||||
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 + "%"")
|
||||
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 + "%"")
|
||||
end
|
||||
|
||||
put_content_length (n: INTEGER)
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_length, n.out)
|
||||
end
|
||||
|
||||
put_content_transfer_encoding (a_mechanism: READABLE_STRING_8)
|
||||
-- Put "Content-Transfer-Encoding" header with for instance "binary"
|
||||
--| encoding := "Content-Transfer-Encoding" ":" mechanism
|
||||
--|
|
||||
--| mechanism := "7bit" ; case-insensitive
|
||||
--| / "quoted-printable"
|
||||
--| / "base64"
|
||||
--| / "8bit"
|
||||
--| / "binary"
|
||||
--| / x-token
|
||||
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_transfer_encoding, a_mechanism)
|
||||
end
|
||||
|
||||
put_transfer_encoding (a_enc: READABLE_STRING_8)
|
||||
-- Put "Transfer-Encoding" header with for instance "chunked"
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_transfer_encoding, a_enc)
|
||||
end
|
||||
|
||||
put_transfer_encoding_chunked
|
||||
-- Put "Transfer-Encoding: chunked" header
|
||||
do
|
||||
put_transfer_encoding ("chunked")
|
||||
end
|
||||
|
||||
put_content_disposition (a_type: READABLE_STRING_8; a_params: detachable READABLE_STRING_8)
|
||||
-- Put "Content-Disposition" header
|
||||
--| See RFC2183
|
||||
--| disposition := "Content-Disposition" ":"
|
||||
--| disposition-type
|
||||
--| *(";" disposition-parm)
|
||||
--| disposition-type := "inline"
|
||||
--| / "attachment"
|
||||
--| / extension-token
|
||||
--| ; values are not case-sensitive
|
||||
--| disposition-parm := filename-parm
|
||||
--| / creation-date-parm
|
||||
--| / modification-date-parm
|
||||
--| / read-date-parm
|
||||
--| / size-parm
|
||||
--| / parameter
|
||||
--| filename-parm := "filename" "=" value
|
||||
--| creation-date-parm := "creation-date" "=" quoted-date-time
|
||||
--| modification-date-parm := "modification-date" "=" quoted-date-time
|
||||
--| read-date-parm := "read-date" "=" quoted-date-time
|
||||
--| size-parm := "size" "=" 1*DIGIT
|
||||
--| quoted-date-time := quoted-string
|
||||
--| ; contents MUST be an RFC 822 `date-time'
|
||||
--| ; numeric timezones (+HHMM or -HHMM) MUST be used
|
||||
do
|
||||
if a_params /= Void then
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type + semi_colon_space + a_params)
|
||||
else
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Content-type helpers
|
||||
|
||||
put_content_type_text_css do put_content_type ({HTTP_MIME_TYPES}.text_css) end
|
||||
put_content_type_text_csv do put_content_type ({HTTP_MIME_TYPES}.text_csv) end
|
||||
put_content_type_text_html do put_content_type ({HTTP_MIME_TYPES}.text_html) end
|
||||
put_content_type_text_javascript do put_content_type ({HTTP_MIME_TYPES}.text_javascript) end
|
||||
put_content_type_text_json do put_content_type ({HTTP_MIME_TYPES}.text_json) end
|
||||
put_content_type_text_plain do put_content_type ({HTTP_MIME_TYPES}.text_plain) end
|
||||
put_content_type_text_xml do put_content_type ({HTTP_MIME_TYPES}.text_xml) end
|
||||
|
||||
put_content_type_application_json do put_content_type ({HTTP_MIME_TYPES}.application_json) end
|
||||
put_content_type_application_javascript do put_content_type ({HTTP_MIME_TYPES}.application_javascript) end
|
||||
put_content_type_application_zip do put_content_type ({HTTP_MIME_TYPES}.application_zip) end
|
||||
|
||||
put_content_type_image_gif do put_content_type ({HTTP_MIME_TYPES}.image_gif) end
|
||||
put_content_type_image_png do put_content_type ({HTTP_MIME_TYPES}.image_png) end
|
||||
put_content_type_image_jpg do put_content_type ({HTTP_MIME_TYPES}.image_jpg) end
|
||||
put_content_type_image_svg_xml do put_content_type ({HTTP_MIME_TYPES}.image_svg_xml) end
|
||||
|
||||
put_content_type_message_http do put_content_type ({HTTP_MIME_TYPES}.message_http) end
|
||||
|
||||
put_content_type_multipart_mixed do put_content_type ({HTTP_MIME_TYPES}.multipart_mixed) end
|
||||
put_content_type_multipart_alternative do put_content_type ({HTTP_MIME_TYPES}.multipart_alternative) end
|
||||
put_content_type_multipart_related do put_content_type ({HTTP_MIME_TYPES}.multipart_related) end
|
||||
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
|
||||
|
||||
feature -- Date
|
||||
|
||||
put_date (s: READABLE_STRING_8)
|
||||
-- Put "Date: " header
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_date, s)
|
||||
end
|
||||
|
||||
put_current_date
|
||||
-- Put current date time with "Date" header
|
||||
do
|
||||
put_utc_date (create {DATE_TIME}.make_now_utc)
|
||||
end
|
||||
|
||||
put_utc_date (dt: DATE_TIME)
|
||||
-- Put UTC date time `dt' with "Date" header
|
||||
do
|
||||
put_date (dt.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT")
|
||||
end
|
||||
|
||||
feature -- Others
|
||||
|
||||
put_expires (n: INTEGER)
|
||||
do
|
||||
put_header_key_value ("Expires", n.out)
|
||||
end
|
||||
|
||||
put_cache_control (s: READABLE_STRING_8)
|
||||
-- `s' could be for instance "no-cache, must-revalidate"
|
||||
do
|
||||
put_header_key_value ("Cache-Control", s)
|
||||
end
|
||||
|
||||
put_pragma (s: READABLE_STRING_8)
|
||||
do
|
||||
put_header_key_value ("Pragma", s)
|
||||
end
|
||||
|
||||
put_pragma_no_cache
|
||||
do
|
||||
put_pragma ("no-cache")
|
||||
end
|
||||
|
||||
feature -- Redirection
|
||||
|
||||
put_location (a_location: READABLE_STRING_8)
|
||||
-- Tell the client the new location `a_location'
|
||||
require
|
||||
a_location_valid: not a_location.is_empty
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_location, a_location)
|
||||
end
|
||||
|
||||
put_refresh (a_location: READABLE_STRING_8; a_timeout_in_seconds: INTEGER)
|
||||
-- Tell the client to refresh page with `a_location' after `a_timeout_in_seconds' in seconds
|
||||
require
|
||||
a_location_valid: not a_location.is_empty
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_refresh, a_timeout_in_seconds.out + "; url=" + a_location)
|
||||
end
|
||||
|
||||
feature -- Cookie
|
||||
|
||||
put_cookie (key, value: READABLE_STRING_8; expiration, path, domain, secure: detachable READABLE_STRING_8)
|
||||
-- Set a cookie on the client's machine
|
||||
-- with key 'key' and value 'value'.
|
||||
require
|
||||
make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty)
|
||||
local
|
||||
s: STRING
|
||||
do
|
||||
s := {HTTP_HEADER_NAMES}.header_set_cookie + colon_space + key + "=" + value
|
||||
if expiration /= Void then
|
||||
s.append ("; expires=" + expiration)
|
||||
end
|
||||
if path /= Void then
|
||||
s.append ("; path=" + path)
|
||||
end
|
||||
if domain /= Void then
|
||||
s.append ("; domain=" + domain)
|
||||
end
|
||||
if secure /= Void then
|
||||
s.append ("; secure=" + secure)
|
||||
end
|
||||
add_header (s)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_header_named (a_name: READABLE_STRING_8): BOOLEAN
|
||||
-- Has header item for `n'?
|
||||
local
|
||||
c: like headers.new_cursor
|
||||
n: INTEGER
|
||||
l_line: READABLE_STRING_8
|
||||
do
|
||||
from
|
||||
n := a_name.count
|
||||
c := headers.new_cursor
|
||||
until
|
||||
c.after or Result
|
||||
loop
|
||||
l_line := c.item
|
||||
if l_line.starts_with (a_name) then
|
||||
if l_line.valid_index (n + 1) then
|
||||
Result := l_line [n + 1] = ':'
|
||||
end
|
||||
end
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
has_content_length: BOOLEAN
|
||||
-- Has header "content_length"
|
||||
do
|
||||
Result := has_header_named ({HTTP_HEADER_NAMES}.header_content_length)
|
||||
end
|
||||
|
||||
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)
|
||||
local
|
||||
l_headers: like headers
|
||||
do
|
||||
if n /= Void then
|
||||
from
|
||||
l_headers := headers
|
||||
l_headers.start
|
||||
until
|
||||
l_headers.after or l_headers.item.starts_with (n)
|
||||
loop
|
||||
l_headers.forth
|
||||
end
|
||||
if not l_headers.after then
|
||||
l_headers.replace (h)
|
||||
else
|
||||
add_header (h)
|
||||
end
|
||||
else
|
||||
add_header (h)
|
||||
end
|
||||
end
|
||||
|
||||
header_name (h: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- If any, header's name with colon
|
||||
--| ex: for "Foo-bar: something", this will return "Foo-bar:"
|
||||
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
|
||||
s.extend (c)
|
||||
when '-', 'a' .. 'z', 'A' .. 'Z' then
|
||||
s.extend (c)
|
||||
else
|
||||
s := Void
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
Result := s
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
append_line_to (s: READABLE_STRING_8; h: like string)
|
||||
do
|
||||
h.append_string (s)
|
||||
append_end_of_line_to (h)
|
||||
end
|
||||
|
||||
append_end_of_line_to (h: like string)
|
||||
do
|
||||
h.append_character ('%R')
|
||||
h.append_character ('%N')
|
||||
end
|
||||
|
||||
feature {NONE} -- Constants
|
||||
|
||||
colon_space: STRING = ": "
|
||||
semi_colon_space: STRING = "; "
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -1393,7 +1393,7 @@ feature {NONE} -- Implementation
|
||||
report_bad_request_error (a_message: detachable STRING)
|
||||
-- Report error
|
||||
local
|
||||
e: EWF_ERROR
|
||||
e: WSF_ERROR
|
||||
do
|
||||
create e.make ({HTTP_STATUS_CODE}.bad_request)
|
||||
if a_message /= Void then
|
||||
|
||||
213
library/server/wsf/tests/test_wsf_request.e
Normal file
213
library/server/wsf/tests/test_wsf_request.e
Normal file
@@ -0,0 +1,213 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing: "type/manual"
|
||||
|
||||
class
|
||||
TEST_EWSGI_REQUEST
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
end
|
||||
|
||||
WSF_APPLICATION
|
||||
undefine
|
||||
default_create
|
||||
end
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
web_app: detachable NINO_APPLICATION
|
||||
|
||||
port_number: INTEGER
|
||||
base_url: detachable STRING
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
local
|
||||
app: NINO_APPLICATION
|
||||
wt: WORKER_THREAD
|
||||
e: EXECUTION_ENVIRONMENT
|
||||
do
|
||||
port_number := 8087
|
||||
base_url := "test/"
|
||||
create app.make_custom (agent wgi_execute, base_url)
|
||||
web_app := app
|
||||
|
||||
create wt.make (agent app.listen (port_number))
|
||||
wt.launch
|
||||
|
||||
create e
|
||||
e.sleep (1_000_000_000 * 5)
|
||||
end
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
q: detachable STRING_32
|
||||
do
|
||||
if attached req.request_uri as l_uri then
|
||||
if l_uri.starts_with (test_url ("get/01")) then
|
||||
res.write_header (200, <<["Content-Type", "text/plain"]>>)
|
||||
res.write_string ("get-01")
|
||||
create q.make_empty
|
||||
|
||||
across
|
||||
req.query_parameters as qcur
|
||||
loop
|
||||
if not q.is_empty then
|
||||
q.append_character ('&')
|
||||
end
|
||||
q.append (qcur.item.name.as_string_32 + "=" + qcur.item.as_string)
|
||||
end
|
||||
if not q.is_empty then
|
||||
res.write_string ("(" + q + ")")
|
||||
end
|
||||
elseif l_uri.starts_with (test_url ("post/01")) then
|
||||
res.write_header (200, <<["Content-Type", "text/plain"]>>)
|
||||
res.write_string ("post-01")
|
||||
create q.make_empty
|
||||
|
||||
across
|
||||
req.query_parameters as qcur
|
||||
loop
|
||||
if not q.is_empty then
|
||||
q.append_character ('&')
|
||||
end
|
||||
q.append (qcur.item.name.as_string_32 + "=" + qcur.item.as_string)
|
||||
end
|
||||
|
||||
if not q.is_empty then
|
||||
res.write_string ("(" + q + ")")
|
||||
end
|
||||
|
||||
create q.make_empty
|
||||
|
||||
|
||||
across
|
||||
req.form_data_parameters as fcur
|
||||
loop
|
||||
if not q.is_empty then
|
||||
q.append_character ('&')
|
||||
end
|
||||
q.append (fcur.item.name.as_string_32 + "=" + fcur.item.as_string)
|
||||
end
|
||||
|
||||
if not q.is_empty then
|
||||
res.write_string (" : " + q )
|
||||
end
|
||||
else
|
||||
res.write_header (200, <<["Content-Type", "text/plain"]>>)
|
||||
res.write_string ("Hello")
|
||||
end
|
||||
else
|
||||
res.write_header (200, <<["Content-Type", "text/plain"]>>)
|
||||
res.write_string ("Bye")
|
||||
end
|
||||
end
|
||||
|
||||
test_url (a_query_url: READABLE_STRING_8): READABLE_STRING_8
|
||||
local
|
||||
b: like base_url
|
||||
do
|
||||
b := base_url
|
||||
if b = Void then
|
||||
b := ""
|
||||
end
|
||||
Result := "/" + b + a_query_url
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
if attached web_app as app then
|
||||
app.shutdown
|
||||
end
|
||||
end
|
||||
|
||||
http_session: detachable HTTP_CLIENT_SESSION
|
||||
|
||||
get_http_session
|
||||
local
|
||||
h: LIBCURL_HTTP_CLIENT
|
||||
b: like base_url
|
||||
do
|
||||
create h.make
|
||||
b := base_url
|
||||
if b = Void then
|
||||
b := ""
|
||||
end
|
||||
if attached {HTTP_CLIENT_SESSION} h.new_session ("localhost:" + port_number.out + "/" + b) as sess then
|
||||
http_session := sess
|
||||
sess.set_timeout (-1)
|
||||
sess.set_connect_timeout (-1)
|
||||
end
|
||||
end
|
||||
|
||||
test_get_request (a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; a_expected_body: READABLE_STRING_8)
|
||||
do
|
||||
get_http_session
|
||||
if attached http_session as sess then
|
||||
if attached sess.get (a_url, ctx) as res and then not res.error_occurred and then attached res.body as l_body then
|
||||
assert ("Good answer got=%""+l_body+"%" expected=%""+a_expected_body+"%"", l_body.same_string (a_expected_body))
|
||||
else
|
||||
assert ("Request %""+a_url+"%" failed", False)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test_post_request (a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; a_expected_body: READABLE_STRING_8)
|
||||
do
|
||||
get_http_session
|
||||
if attached http_session as sess then
|
||||
if attached sess.post (a_url, ctx, Void) as res and then not res.error_occurred and then attached res.body as l_body then
|
||||
assert ("Good answer got=%""+l_body+"%" expected=%""+a_expected_body+"%"", l_body.same_string (a_expected_body))
|
||||
else
|
||||
assert ("Request %""+a_url+"%" failed", False)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_get_request_01
|
||||
-- New test routine
|
||||
do
|
||||
get_http_session
|
||||
if attached http_session as sess then
|
||||
test_get_request ("get/01", Void, "get-01")
|
||||
test_get_request ("get/01/?foo=bar", Void, "get-01(foo=bar)")
|
||||
test_get_request ("get/01/?foo=bar&abc=def", Void, "get-01(foo=bar&abc=def)")
|
||||
test_get_request ("get/01/?lst=a&lst=b", Void, "get-01(lst=[a,b])")
|
||||
else
|
||||
assert ("not_implemented", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_post_request_01
|
||||
-- New test routine
|
||||
local
|
||||
ctx: HTTP_CLIENT_REQUEST_CONTEXT
|
||||
do
|
||||
get_http_session
|
||||
if attached http_session as sess then
|
||||
create ctx.make
|
||||
ctx.add_form_data_parameter ("id", "123")
|
||||
test_post_request ("post/01", ctx, "post-01 : id=123")
|
||||
test_post_request ("post/01/?foo=bar", ctx, "post-01(foo=bar) : id=123")
|
||||
test_post_request ("post/01/?foo=bar&abc=def", ctx, "post-01(foo=bar&abc=def) : id=123")
|
||||
test_post_request ("post/01/?lst=a&lst=b", ctx, "post-01(lst=[a,b]) : id=123")
|
||||
else
|
||||
assert ("not_implemented", False)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
21
library/server/wsf/tests/tests-safe.ecf
Normal file
21
library/server/wsf/tests/tests-safe.ecf
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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="tests" uuid="CA72F5B3-E608-4FA5-8F05-A812441DB961">
|
||||
<target name="tests">
|
||||
<root class="ANY" feature="default_create"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="connector_nino" location="..\..\ewsgi\connectors\nino\nino-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="..\wsf-safe.ecf" readonly="false"/>
|
||||
<library name="http_client" location="..\..\..\client\http_client\http_client-safe.ecf"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
||||
<tests name="src" location=".\" recursive="false"/>
|
||||
</target>
|
||||
</system>
|
||||
21
library/server/wsf/tests/tests.ecf
Normal file
21
library/server/wsf/tests/tests.ecf
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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="tests" uuid="CA72F5B3-E608-4FA5-8F05-A812441DB961">
|
||||
<target name="tests">
|
||||
<root class="ANY" feature="default_create"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" void_safety="none" syntax="provisional">
|
||||
</option>
|
||||
<setting name="concurrency" value="none"/>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<library name="dft_nino" location="..\default\nino.ecf"/>
|
||||
<library name="wsf" location="..\wsf.ecf"/>
|
||||
<library name="http_client" location="..\..\..\client\http_client\http_client.ecf"/>
|
||||
<library name="testing" location="$ISE_LIBRARY/library/testing/testing.ecf"/>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
||||
<tests name="src" location="." recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -14,7 +14,7 @@
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-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="src" location=".\" recursive="true"/>
|
||||
<library name="encoder" location="..\..\text\encoder\encoder-safe.ecf"/>
|
||||
<cluster name="src" location=".\src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -9,8 +9,12 @@
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
|
||||
</option>
|
||||
<library name="ewsgi" location="..\ewsgi\ewsgi.ecf"/>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<cluster name="src" location="." recursive="true"/>
|
||||
<library name="ewsgi" location="..\ewsgi\ewsgi.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<library name="error" location="..\..\error\error.ecf"/>
|
||||
<library name="http" location="..\..\protocol\http\http.ecf"/>
|
||||
<library name="encoder" location="..\..\text\encoder\encoder.ecf"/>
|
||||
<cluster name="src" location=".\src" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
Reference in New Issue
Block a user