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:
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