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:
Olivier Ligot
2013-01-09 17:34:50 +01:00
parent 65d7545320
commit ff57d0ecd4
10 changed files with 324 additions and 82 deletions

View 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

View 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

View 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

View File

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