1/* Part of the SWI-Prolog HTTP package 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2012-2014, University of Amsterdam, 7 VU University Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(http_cors, 37 [ cors_enable/0, 38 cors_enable/2 % +Request, +Options 39 ]). 40:- use_module(library(settings)). 41 42:- setting(http:cors, list(atom), [], 43 'Enable CORS for the listed domains. Use [*] for all domains').
Access-Control-Allow-Origin
using
domains from the setting http:cors. This this setting is []
(default), nothing is written. This predicate is typically used
for replying to API HTTP-request (e.g., replies to an AJAX
request that typically serve JSON or XML).97cors_enable :- 98 cors_enable_domain, 99 !. 100cors_enable. % CORS not enabled 101 102cors_enable_domain :- 103 setting(http:cors, List), 104 List \== [], 105 !, 106 format('Access-Control-Allow-Origin: ', []), 107 write_domains(List), 108 nl. 109 110write_domains([]). 111write_domains([H|T]) :- 112 write(H), 113 ( T == [] 114 -> true 115 ; write(' '), 116 write_domains(T) 117 ).
OPTIONS
request. Request is the
HTTP request. Options provides:
GET
, only
allowing for read requests.
Both methods and headers may use Prolog friendly syntax, e.g.,
get
for a method and content_type
for a header.
136cors_enable(Request, Options) :- 137 cors_enable_domain, 138 !, 139 option(methods(Methods), Options, [get]), 140 cors_methods(Methods), 141 ( option(headers(ReqHeaders), Options) 142 -> cors_request_headers(ReqHeaders) 143 ; option(access_control_request_headers(ReqHeader), Request) 144 -> format('Access-Control-Allow-Headers: ~w~n', [ReqHeader]) 145 ; true 146 ). 147cors_enable(_, _). 148 149cors_methods([]) :- !. 150cors_methods(Methods) :- 151 format('Access-Control-Allow-Methods: '), 152 write_methods(Methods), 153 nl. 154 155write_methods([H|T]) :- 156 upcase_atom(H, U), 157 write(U), 158 ( T == [] 159 -> true 160 ; write(', '), 161 write_methods(T) 162 ). 163 164cors_request_headers([]) :- !. 165cors_request_headers(ReqHeaders) :- 166 phrase(field_names(ReqHeaders), String), 167 format('Access-Control-Allow-Headers: ~s', String). 168 169 170field_names([H|T]) --> 171 http_header:field_name(H), 172 ( {T==[]} 173 -> "" 174 ; ", ", 175 field_names(T) 176 )
Enable CORS: Cross-Origin Resource Sharing
This small module allows for enabling Cross-Origin Resource Sharing (CORS) for a specific request. Typically, CORS is enabled for API services that you want to have useable from browser client code that is loaded from another domain. An example are the LOD and SPARQL services in ClioPatria.
Because CORS is a security risc (see references), it is disabled by default. It is enabled through the setting http:cors. The value of this setting is a list of domains that are allowed to access the service. Because * is used as a wildcard match, the value [*] allows access from anywhere.
Services for which CORS is relevant must call cors_enable/0 as part of the HTTP response, as shown below. Note that cors_enable/0 is a no-op if the setting http:cors is set to the empty list ([]).
If a site uses a Preflight
OPTIONS
request to find the server's capabilities and access politics, cors_enable/2 can be used to formulate an appropriate reply. For example: