Cross-Origin Resource Sharing initial support
Initial support for the Cross-Origin Resource Sharing specification.
This allows JavaScript to make requests across domain boundaries.
Also reviewed the filter example to get rid of the context and
the generic classes (we can actually use {WSF_REQUEST}.execution_variable
and {WSF_REQUEST}.set_execution_variable).
Links:
* How to enable server-side: http://enable-cors.org/server.html
* Specification: http://www.w3.org/TR/cors/
* Github: http://developer.github.com/v3/#cross-origin-resource-sharing
This commit is contained in:
@@ -12,22 +12,23 @@
|
||||
<assertions precondition="true" postcondition="true" invariant="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="connector_nino" location="..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false">
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf" readonly="true"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf" readonly="true"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf" readonly="true"/>
|
||||
<library name="connector_nino" location="..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="true">
|
||||
<option debug="true">
|
||||
<debug name="nino" enabled="true"/>
|
||||
</option>
|
||||
</library>
|
||||
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" readonly="false"/>
|
||||
<library name="eel" location="..\..\contrib\ise_library\text\encryption\eel\eel-safe.ecf" readonly="false"/>
|
||||
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="../../library/network/protocol/http/http-safe.ecf" readonly="false"/>
|
||||
<library name="json" location="..\..\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="uri_template" location="../../library/text/parser/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\wsf_extension-safe.ecf" readonly="false"/>
|
||||
<library name="http_authorization" location="..\..\library\server\authentication\http_authorization\http_authorization-safe.ecf" readonly="false"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" readonly="true"/>
|
||||
<library name="eel" location="..\..\contrib\ise_library\text\encryption\eel\eel-safe.ecf" readonly="true"/>
|
||||
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="true"/>
|
||||
<library name="http" location="../../library/network/protocol/http/http-safe.ecf" readonly="true"/>
|
||||
<library name="json" location="..\..\contrib\library\text\parser\json\library\json-safe.ecf" readonly="true"/>
|
||||
<library name="uri_template" location="../../library/text/parser/uri_template/uri_template-safe.ecf" readonly="true"/>
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="true"/>
|
||||
<library name="wsf_extension" location="..\..\library\server\wsf\wsf_extension-safe.ecf" readonly="true"/>
|
||||
<library name="http_authorization" location="..\..\library\server\authentication\http_authorization\http_authorization-safe.ecf" readonly="true"/>
|
||||
<cluster name="src" location="src\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -8,9 +8,9 @@ class
|
||||
AUTHENTICATION_FILTER
|
||||
|
||||
inherit
|
||||
WSF_FILTER_CONTEXT_HANDLER [FILTER_HANDLER_CONTEXT]
|
||||
WSF_FILTER
|
||||
|
||||
WSF_URI_TEMPLATE_CONTEXT_HANDLER [FILTER_HANDLER_CONTEXT]
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
SHARED_DATABASE_API
|
||||
|
||||
@@ -18,7 +18,7 @@ inherit
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute (ctx: FILTER_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the filter
|
||||
local
|
||||
l_auth: HTTP_AUTHORIZATION
|
||||
@@ -31,8 +31,8 @@ feature -- Basic operations
|
||||
attached l_auth.password as l_auth_password and then
|
||||
l_auth_password.same_string (l_user.password)
|
||||
then
|
||||
ctx.set_user (l_user)
|
||||
execute_next (ctx, req, res)
|
||||
req.set_execution_variable ("user", l_user)
|
||||
execute_next (req, res)
|
||||
else
|
||||
handle_unauthorized ("Unauthorized", req, res)
|
||||
end
|
||||
@@ -56,6 +56,6 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Olivier Ligot, Jocelyn Fiat and others"
|
||||
copyright: "2011-2013, Olivier Ligot, Jocelyn Fiat and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -24,39 +24,60 @@ create
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
local
|
||||
l_message: STRING
|
||||
l_factory: INET_ADDRESS_FACTORY
|
||||
do
|
||||
create router.make (1)
|
||||
initialize_filter
|
||||
initialize_json
|
||||
set_service_option ("port", 9090)
|
||||
set_service_option ("port", port)
|
||||
create l_message.make_empty
|
||||
l_message.append_string ("Launching filter server at ")
|
||||
create l_factory
|
||||
l_message.append_string (l_factory.create_localhost.host_name)
|
||||
l_message.append_string (" port ")
|
||||
l_message.append_integer (port)
|
||||
io.put_string (l_message)
|
||||
io.put_new_line
|
||||
make_and_launch
|
||||
end
|
||||
|
||||
create_filter
|
||||
-- Create `filter'
|
||||
local
|
||||
l_router: WSF_ROUTER
|
||||
l_authentication_filter_hdl: AUTHENTICATION_FILTER
|
||||
l_user_filter: USER_HANDLER
|
||||
l_routing_filter: WSF_ROUTING_FILTER
|
||||
l_cors_filter: WSF_CORS_FILTER
|
||||
do
|
||||
create l_router.make (1)
|
||||
create l_authentication_filter_hdl
|
||||
create l_user_filter
|
||||
l_authentication_filter_hdl.set_next (l_user_filter)
|
||||
|
||||
l_router.handle_with_request_methods ("/user/{userid}", l_authentication_filter_hdl, l_router.methods_get)
|
||||
create l_routing_filter.make (l_router)
|
||||
l_routing_filter.set_execute_default_action (agent execute_default)
|
||||
filter := l_routing_filter
|
||||
create l_cors_filter
|
||||
filter := l_cors_filter
|
||||
end
|
||||
|
||||
setup_filter
|
||||
-- Setup `filter'
|
||||
local
|
||||
l_options_filter: WSF_CORS_OPTIONS_FILTER
|
||||
l_authentication_filter: AUTHENTICATION_FILTER
|
||||
l_user_filter: USER_HANDLER
|
||||
l_methods: WSF_REQUEST_METHODS
|
||||
l_routing_filter: WSF_ROUTING_FILTER
|
||||
l_logging_filter: WSF_LOGGING_FILTER
|
||||
do
|
||||
create l_options_filter.make (router)
|
||||
create l_authentication_filter
|
||||
l_options_filter.set_next (l_authentication_filter)
|
||||
create l_user_filter
|
||||
l_authentication_filter.set_next (l_user_filter)
|
||||
|
||||
create l_methods
|
||||
l_methods.enable_options
|
||||
l_methods.enable_get
|
||||
router.handle_with_request_methods ("/user/{userid}", l_options_filter, l_methods)
|
||||
create l_routing_filter.make (router)
|
||||
l_routing_filter.set_execute_default_action (agent execute_default)
|
||||
filter.set_next (l_routing_filter)
|
||||
|
||||
create l_logging_filter
|
||||
filter.set_next (l_logging_filter)
|
||||
l_routing_filter.set_next (l_logging_filter)
|
||||
end
|
||||
|
||||
initialize_json
|
||||
@@ -73,30 +94,24 @@ feature -- Basic operations
|
||||
end
|
||||
|
||||
execute_default (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- I'm using this method to handle the method not allowed response
|
||||
-- in the case that the given uri does not have a corresponding http method
|
||||
-- to handle it.
|
||||
local
|
||||
h : HTTP_HEADER
|
||||
l_description : STRING
|
||||
l_api_doc : STRING
|
||||
l_message: WSF_DEFAULT_ROUTER_RESPONSE
|
||||
do
|
||||
if req.content_length_value > 0 then
|
||||
req.input.read_string (req.content_length_value.as_integer_32)
|
||||
end
|
||||
create h.make
|
||||
h.put_content_type_text_plain
|
||||
l_api_doc := "%NPlease check the API%NURI:/user/{userid} METHOD: GET%N"
|
||||
l_description := req.request_method + req.request_uri + " is not allowed" + "%N" + l_api_doc
|
||||
h.put_content_length (l_description.count)
|
||||
h.put_current_date
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.method_not_allowed)
|
||||
res.put_header_text (h.string)
|
||||
res.put_string (l_description)
|
||||
create l_message.make_with_router (req, router)
|
||||
l_message.set_documentation_included (True)
|
||||
res.send (l_message)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
port: INTEGER = 9090
|
||||
-- Port number
|
||||
|
||||
router: WSF_ROUTER;
|
||||
-- Router
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Olivier Ligot, Jocelyn Fiat and others"
|
||||
copyright: "2011-2013, Olivier Ligot, Jocelyn Fiat and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -8,11 +8,11 @@ class
|
||||
USER_HANDLER
|
||||
|
||||
inherit
|
||||
WSF_FILTER_CONTEXT_HANDLER [FILTER_HANDLER_CONTEXT]
|
||||
WSF_FILTER
|
||||
|
||||
WSF_URI_TEMPLATE_CONTEXT_HANDLER [FILTER_HANDLER_CONTEXT]
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
WSF_RESOURCE_CONTEXT_HANDLER_HELPER [FILTER_HANDLER_CONTEXT]
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
redefine
|
||||
do_get
|
||||
end
|
||||
@@ -23,30 +23,30 @@ inherit
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute (ctx: FILTER_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute_methods (ctx, req, res)
|
||||
execute_next (ctx, req, res)
|
||||
execute_methods (req, res)
|
||||
execute_next (req, res)
|
||||
end
|
||||
|
||||
do_get (ctx: FILTER_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Using GET to retrieve resource information.
|
||||
-- If the GET request is SUCCESS, we response with
|
||||
-- 200 OK, and a representation of the user
|
||||
-- If the GET request is not SUCCESS, we response with
|
||||
-- 404 Resource not found
|
||||
require else
|
||||
authenticated_user_attached: attached ctx.user
|
||||
authenticated_user_attached: attached {USER} req.execution_variable ("user")
|
||||
local
|
||||
id : STRING
|
||||
do
|
||||
if attached req.orig_path_info as orig_path then
|
||||
id := get_user_id_from_path (orig_path)
|
||||
if attached retrieve_user (id) as l_user then
|
||||
if l_user ~ ctx.user then
|
||||
if l_user ~ req.execution_variable ("user") then
|
||||
compute_response_get (req, res, l_user)
|
||||
elseif attached ctx.user as l_auth_user then
|
||||
elseif attached {USER} req.execution_variable ("user") as l_auth_user then
|
||||
-- Trying to access another user that the authenticated one,
|
||||
-- which is forbidden in this example...
|
||||
handle_forbidden ("You try to access the user " + id.out + " while authenticating with the user " + l_auth_user.id.out, req, res)
|
||||
@@ -92,6 +92,6 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Olivier Ligot, Jocelyn Fiat and others"
|
||||
copyright: "2011-2013, Olivier Ligot, Jocelyn Fiat and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -213,6 +213,25 @@ feature -- Header change: general
|
||||
put_header (k + colon_space + v)
|
||||
end
|
||||
|
||||
put_header_key_methods (k: READABLE_STRING_8; a_methods: ITERABLE [READABLE_STRING_8])
|
||||
-- Add header `k: a_methods', or replace existing header of same header methods/key
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
create s.make_empty
|
||||
across
|
||||
a_methods as c
|
||||
loop
|
||||
if not s.is_empty then
|
||||
s.append_string (", ")
|
||||
end
|
||||
s.append (c.item)
|
||||
end
|
||||
if not s.is_empty then
|
||||
put_header_key_value (k, s)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Content related header
|
||||
|
||||
put_content_type (t: READABLE_STRING_8)
|
||||
@@ -397,26 +416,38 @@ feature -- Content-type helpers
|
||||
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 -- Cross-Origin Resource Sharing
|
||||
|
||||
put_access_control_allow_origin (s: READABLE_STRING_8)
|
||||
-- Put "Access-Control-Allow-Origin" header.
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_access_control_allow_origin, s)
|
||||
end
|
||||
|
||||
put_access_control_allow_all_origin
|
||||
-- Put "Access-Control-Allow-Origin: *" header.
|
||||
do
|
||||
put_access_control_allow_origin ("*")
|
||||
end
|
||||
|
||||
put_access_control_allow_methods (a_methods: ITERABLE [READABLE_STRING_8])
|
||||
-- If `a_methods' is not empty, put `Access-Control-Allow-Methods' header with list `a_methods' of methods
|
||||
do
|
||||
put_header_key_methods ({HTTP_HEADER_NAMES}.header_access_control_allow_methods, a_methods)
|
||||
end
|
||||
|
||||
put_access_control_allow_headers (s: READABLE_STRING_8)
|
||||
-- Put "Access-Control-Allow-Headers" header.
|
||||
do
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_access_control_allow_headers, s)
|
||||
end
|
||||
|
||||
feature -- Method related
|
||||
|
||||
put_allow (a_methods: ITERABLE [READABLE_STRING_8])
|
||||
-- If `a_methods' is not empty, put `Allow' header with list `a_methods' of methods
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
create s.make_empty
|
||||
across
|
||||
a_methods as c
|
||||
loop
|
||||
if not s.is_empty then
|
||||
s.append_character (',')
|
||||
end
|
||||
s.append_character (' ')
|
||||
s.append (c.item)
|
||||
end
|
||||
if not s.is_empty then
|
||||
put_header_key_value ({HTTP_HEADER_NAMES}.header_allow, s)
|
||||
end
|
||||
put_header_key_methods ({HTTP_HEADER_NAMES}.header_allow, a_methods)
|
||||
end
|
||||
|
||||
feature -- Date
|
||||
@@ -738,7 +769,7 @@ feature {NONE} -- Constants
|
||||
semi_colon_space: STRING = "; "
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Eiffel Software and others"
|
||||
copyright: "2011-2013, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -194,6 +194,23 @@ feature -- Response header name
|
||||
-- Indicates the authentication scheme that should be used to access the requested entity.
|
||||
--| Example: WWW-Authenticate: Basic
|
||||
|
||||
feature -- Cross-Origin Resource Sharing
|
||||
|
||||
header_access_control_allow_origin: STRING = "Access-Control-Allow-Origin"
|
||||
-- Indicates whether a resource can be shared based by returning
|
||||
-- the value of the Origin request header in the response.
|
||||
-- | Example: Access-Control-Allow-Origin: http://example.org
|
||||
|
||||
header_access_control_allow_methods: STRING = "Access-Control-Allow-Methods"
|
||||
-- Indicates, as part of the response to a preflight request,
|
||||
-- which methods can be used during the actual request.
|
||||
-- | Example: Access-Control-Allow-Methods: PUT, DELETE
|
||||
|
||||
header_access_control_allow_headers: STRING = "Access-Control-Allow-Headers"
|
||||
-- Indicates, as part of the response to a preflight request,
|
||||
-- which header field names can be used during the actual request.
|
||||
-- | Example: Access-Control-Allow-Headers: Authorization
|
||||
|
||||
feature -- Request or Response header name
|
||||
|
||||
header_cache_control: STRING = "Cache-Control"
|
||||
@@ -248,7 +265,7 @@ feature -- MIME related
|
||||
header_content_transfer_encoding: STRING = "Content-Transfer-Encoding"
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Eiffel Software and others"
|
||||
copyright: "2011-2013, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
33
library/server/wsf/router/filter/wsf_cors_filter.e
Normal file
33
library/server/wsf/router/filter/wsf_cors_filter.e
Normal file
@@ -0,0 +1,33 @@
|
||||
note
|
||||
description: "Cross-Origin Resource Sharing filter."
|
||||
author: "Olivier Ligot"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=Cross-Origin Resource Sharing", "src=http://www.w3.org/TR/cors/", "tag=W3C"
|
||||
|
||||
class
|
||||
WSF_CORS_FILTER
|
||||
|
||||
inherit
|
||||
WSF_FILTER
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the filter.
|
||||
do
|
||||
res.header.put_access_control_allow_all_origin
|
||||
execute_next (req, res)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, 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
|
||||
59
library/server/wsf/router/filter/wsf_cors_options_filter.e
Normal file
59
library/server/wsf/router/filter/wsf_cors_options_filter.e
Normal file
@@ -0,0 +1,59 @@
|
||||
note
|
||||
description: "Filter that handles an OPTIONS request, with Cross-Origin Resource Sharing support."
|
||||
author: "Olvier Ligot"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=Cross-Origin Resource Sharing", "src=http://www.w3.org/TR/cors/", "tag=W3C"
|
||||
|
||||
class
|
||||
WSF_CORS_OPTIONS_FILTER
|
||||
|
||||
inherit
|
||||
WSF_FILTER
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_router: like router)
|
||||
-- Initialize Current with `a_router'.
|
||||
do
|
||||
router := a_router
|
||||
ensure
|
||||
router_set: router = a_router
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
router: WSF_ROUTER
|
||||
-- Associated router
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the filter.
|
||||
local
|
||||
msg: WSF_CORS_OPTIONS_RESPONSE
|
||||
do
|
||||
if req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) then
|
||||
create msg.make (req, router)
|
||||
res.send (msg)
|
||||
else
|
||||
execute_next (req, res)
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, 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
|
||||
64
library/server/wsf/src/response/wsf_cors_options_response.e
Normal file
64
library/server/wsf/src/response/wsf_cors_options_response.e
Normal file
@@ -0,0 +1,64 @@
|
||||
note
|
||||
description: "Response to an OPTIONS request, with Cross-Origin Resource Sharing support."
|
||||
author: "Olivier Ligt"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=Cross-Origin Resource Sharing", "src=http://www.w3.org/TR/cors/", "tag=W3C"
|
||||
|
||||
class
|
||||
WSF_CORS_OPTIONS_RESPONSE
|
||||
|
||||
inherit
|
||||
WSF_RESPONSE_MESSAGE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (req: WSF_REQUEST; a_router: like router)
|
||||
do
|
||||
request := req
|
||||
router := a_router
|
||||
create header.make
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
request: WSF_REQUEST
|
||||
-- Associated request
|
||||
|
||||
router: WSF_ROUTER
|
||||
-- Associated router
|
||||
|
||||
header: HTTP_HEADER
|
||||
-- Response' header
|
||||
|
||||
feature {WSF_RESPONSE} -- Output
|
||||
|
||||
send_to (res: WSF_RESPONSE)
|
||||
local
|
||||
l_methods: WSF_REQUEST_METHODS
|
||||
do
|
||||
res.set_status_code ({HTTP_STATUS_CODE}.No_content)
|
||||
header.put_current_date
|
||||
header.put_access_control_allow_headers ({HTTP_HEADER_NAMES}.header_authorization)
|
||||
l_methods := router.allowed_methods_for_request (request)
|
||||
if not l_methods.is_empty then
|
||||
header.put_allow (l_methods)
|
||||
header.put_access_control_allow_methods (l_methods)
|
||||
end
|
||||
res.put_header_text (header.string)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, 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
|
||||
@@ -31,6 +31,7 @@ feature {NONE} -- Initialization
|
||||
do
|
||||
transfered_content_length := 0
|
||||
wgi_response := r
|
||||
create header.make
|
||||
end
|
||||
|
||||
feature {WSF_RESPONSE_EXPORTER} -- Properties
|
||||
@@ -114,6 +115,13 @@ feature -- Status setting
|
||||
|
||||
feature -- Header output operation
|
||||
|
||||
header: HTTP_HEADER
|
||||
-- Header
|
||||
-- This is useful when we want to fill the `header'
|
||||
-- in two pass (i.e. in two different classes).
|
||||
-- We first call features of `header', and finally
|
||||
-- we call `put_header_text'
|
||||
|
||||
put_header_text (a_text: READABLE_STRING_8)
|
||||
-- Sent `a_text' and just before send the status code
|
||||
require
|
||||
@@ -121,9 +129,23 @@ feature -- Header output operation
|
||||
header_not_committed: not header_committed
|
||||
a_text_ends_with_single_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_end_with_double_crlf: a_text.count > 4 implies not a_text.substring (a_text.count - 4, a_text.count).same_string ("%R%N%R%N")
|
||||
local
|
||||
l_text: READABLE_STRING_8
|
||||
l_header: HTTP_HEADER
|
||||
do
|
||||
wgi_response.set_status_code (status_code, status_reason_phrase)
|
||||
wgi_response.put_header_text (a_text)
|
||||
if header.is_empty then
|
||||
l_text := a_text
|
||||
else
|
||||
create l_header.make_from_raw_header_data (a_text)
|
||||
across
|
||||
l_header as c
|
||||
loop
|
||||
header.put_header (c.item.string)
|
||||
end
|
||||
l_text := header.string
|
||||
end
|
||||
wgi_response.put_header_text (l_text)
|
||||
ensure
|
||||
status_set: status_is_set
|
||||
status_committed: status_committed
|
||||
@@ -376,7 +398,7 @@ feature -- Error reporting
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
|
||||
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
Reference in New Issue
Block a user