Merge pull request #22 from oligot/cors
Cross-Origin Resource Sharing initial support
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
</option>
|
</option>
|
||||||
<setting name="concurrency" value="thread"/>
|
<setting name="concurrency" value="thread"/>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf" readonly="true"/>
|
<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="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" readonly="true"/>
|
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" readonly="true"/>
|
||||||
<library name="http" location="../../library/network/protocol/http/http-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="json" location="..\..\contrib\library\text\parser\json\library\json-safe.ecf" readonly="true"/>
|
||||||
|
|||||||
@@ -24,38 +24,60 @@ create
|
|||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make
|
make
|
||||||
|
local
|
||||||
|
l_message: STRING
|
||||||
|
l_factory: INET_ADDRESS_FACTORY
|
||||||
do
|
do
|
||||||
|
create router.make (1)
|
||||||
initialize_filter
|
initialize_filter
|
||||||
initialize_json
|
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
|
make_and_launch
|
||||||
end
|
end
|
||||||
|
|
||||||
create_filter
|
create_filter
|
||||||
-- Create `filter'
|
-- Create `filter'
|
||||||
local
|
local
|
||||||
l_authentication_filter_hdl: AUTHENTICATION_FILTER
|
l_cors_filter: WSF_CORS_FILTER
|
||||||
l_user_filter: USER_HANDLER
|
|
||||||
l_routing_filter: WSF_ROUTING_FILTER
|
|
||||||
do
|
do
|
||||||
create router.make (1)
|
create l_cors_filter
|
||||||
create l_authentication_filter_hdl
|
filter := l_cors_filter
|
||||||
create l_user_filter
|
|
||||||
l_authentication_filter_hdl.set_next (l_user_filter)
|
|
||||||
|
|
||||||
router.handle_with_request_methods ("/user/{userid}", l_authentication_filter_hdl, router.methods_get)
|
|
||||||
create l_routing_filter.make (router)
|
|
||||||
l_routing_filter.set_execute_default_action (agent execute_default)
|
|
||||||
filter := l_routing_filter
|
|
||||||
end
|
end
|
||||||
|
|
||||||
setup_filter
|
setup_filter
|
||||||
-- Setup `filter'
|
-- Setup `filter'
|
||||||
local
|
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
|
l_logging_filter: WSF_LOGGING_FILTER
|
||||||
do
|
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
|
create l_logging_filter
|
||||||
filter.set_next (l_logging_filter)
|
l_routing_filter.set_next (l_logging_filter)
|
||||||
end
|
end
|
||||||
|
|
||||||
initialize_json
|
initialize_json
|
||||||
@@ -82,6 +104,9 @@ feature -- Basic operations
|
|||||||
|
|
||||||
feature {NONE} -- Implementation
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
port: INTEGER = 9090
|
||||||
|
-- Port number
|
||||||
|
|
||||||
router: WSF_ROUTER;
|
router: WSF_ROUTER;
|
||||||
-- Router
|
-- Router
|
||||||
|
|
||||||
|
|||||||
@@ -504,6 +504,32 @@ feature -- Content-type helpers
|
|||||||
put_content_type_multipart_encrypted do put_content_type ({HTTP_MIME_TYPES}.multipart_encrypted) 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
|
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_values ({HTTP_HEADER_NAMES}.header_access_control_allow_methods, a_methods, Void)
|
||||||
|
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
|
feature -- Method related
|
||||||
|
|
||||||
put_allow (a_methods: ITERABLE [READABLE_STRING_8])
|
put_allow (a_methods: ITERABLE [READABLE_STRING_8])
|
||||||
|
|||||||
@@ -194,6 +194,23 @@ feature -- Response header name
|
|||||||
-- Indicates the authentication scheme that should be used to access the requested entity.
|
-- Indicates the authentication scheme that should be used to access the requested entity.
|
||||||
--| Example: WWW-Authenticate: Basic
|
--| 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
|
feature -- Request or Response header name
|
||||||
|
|
||||||
header_cache_control: STRING = "Cache-Control"
|
header_cache_control: STRING = "Cache-Control"
|
||||||
@@ -248,7 +265,7 @@ feature -- MIME related
|
|||||||
header_content_transfer_encoding: STRING = "Content-Transfer-Encoding"
|
header_content_transfer_encoding: STRING = "Content-Transfer-Encoding"
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ feature -- Access
|
|||||||
|
|
||||||
http_transfer_encoding: STRING = "HTTP_TRANSFER_ENCODING"
|
http_transfer_encoding: STRING = "HTTP_TRANSFER_ENCODING"
|
||||||
|
|
||||||
|
http_access_control_request_headers: STRING = "HTTP_ACCESS_CONTROL_REQUEST_HEADERS"
|
||||||
|
|
||||||
gateway_interface: STRING = "GATEWAY_INTERFACE"
|
gateway_interface: STRING = "GATEWAY_INTERFACE"
|
||||||
|
|
||||||
auth_type: STRING = "AUTH_TYPE"
|
auth_type: STRING = "AUTH_TYPE"
|
||||||
|
|||||||
@@ -598,6 +598,12 @@ feature -- HTTP_*
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
http_access_control_request_headers: detachable READABLE_STRING_8
|
||||||
|
-- Indicates which headers will be used in the actual request
|
||||||
|
-- as part of the preflight request
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Extra CGI environment variables
|
feature -- Extra CGI environment variables
|
||||||
|
|
||||||
request_uri: READABLE_STRING_8
|
request_uri: READABLE_STRING_8
|
||||||
|
|||||||
@@ -241,6 +241,13 @@ feature -- Access: HTTP_* CGI meta parameters - 1.1
|
|||||||
Result := meta_string_variable ({WGI_META_NAMES}.http_transfer_encoding)
|
Result := meta_string_variable ({WGI_META_NAMES}.http_transfer_encoding)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
http_access_control_request_headers: detachable READABLE_STRING_8
|
||||||
|
-- Indicates which headers will be used in the actual request
|
||||||
|
-- as part of the preflight request
|
||||||
|
do
|
||||||
|
Result := meta_string_variable ({WGI_META_NAMES}.http_access_control_request_headers)
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Access: Extension to CGI meta parameters - 1.1
|
feature -- Access: Extension to CGI meta parameters - 1.1
|
||||||
|
|
||||||
request_uri: READABLE_STRING_8
|
request_uri: READABLE_STRING_8
|
||||||
|
|||||||
37
library/server/wsf/router/filter/wsf_cors_filter.e
Normal file
37
library/server/wsf/router/filter/wsf_cors_filter.e
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
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.
|
||||||
|
local
|
||||||
|
l_header: HTTP_HEADER
|
||||||
|
do
|
||||||
|
create l_header.make
|
||||||
|
l_header.put_access_control_allow_all_origin
|
||||||
|
res.put_header_text (l_header.string)
|
||||||
|
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
|
||||||
68
library/server/wsf/src/response/wsf_cors_options_response.e
Normal file
68
library/server/wsf/src/response/wsf_cors_options_response.e
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
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}.Ok)
|
||||||
|
header.put_content_type ({HTTP_MIME_TYPES}.text_plain)
|
||||||
|
header.put_current_date
|
||||||
|
header.put_content_length (0)
|
||||||
|
if attached request.http_access_control_request_headers as l_headers then
|
||||||
|
header.put_access_control_allow_headers (l_headers)
|
||||||
|
end
|
||||||
|
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
|
||||||
@@ -1041,6 +1041,13 @@ feature -- HTTP_*
|
|||||||
Result := wgi_request.http_transfer_encoding
|
Result := wgi_request.http_transfer_encoding
|
||||||
end
|
end
|
||||||
|
|
||||||
|
http_access_control_request_headers: detachable READABLE_STRING_8
|
||||||
|
-- Indicates which headers will be used in the actual request
|
||||||
|
-- as part of the preflight request
|
||||||
|
do
|
||||||
|
Result := wgi_request.http_access_control_request_headers
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Extra CGI environment variables
|
feature -- Extra CGI environment variables
|
||||||
|
|
||||||
request_uri: READABLE_STRING_8
|
request_uri: READABLE_STRING_8
|
||||||
|
|||||||
Reference in New Issue
Block a user