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