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
|
||||
|
||||
Reference in New Issue
Block a user