1/* Part of SWI-Prolog 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2009-2017, 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_exception, 37 [ map_exception_to_http_status/4, % +Exception, -Reply, 38 % -HdrExtra, -Context 39 in_or_exclude_backtrace/2 % +Error, -CleanedError 40 ]).
59:- multifile 60 http:bad_request_error/2, % Formal, Context 61 http:map_exception_to_http_status_hook/4. % Exception, Reply, HdrExtra, Ctx
http(not_modified)
provides backward compatibility to http_reply(not_modified)
.68map_exception_to_http_status(Exception, Reply, HdrExtra, Context) :- 69 http:map_exception_to_http_status_hook(Exception, Reply, HdrExtra, Context), 70 !. 71map_exception_to_http_status(http(not_modified), 72 not_modified, 73 [connection('Keep-Alive')], 74 []) :- !. 75map_exception_to_http_status(http_reply(Reply), 76 Reply, 77 [connection(Close)], 78 []) :- 79 !, 80 keep_alive(Reply, Close). 81map_exception_to_http_status(http_reply(Reply, HdrExtra0), 82 Reply, 83 HdrExtra, 84 Context) :- 85 !, 86 map_exception_to_http_status(http_reply(Reply, HdrExtra0, []), 87 Reply, 88 HdrExtra, 89 Context). 90 91map_exception_to_http_status(http_reply(Reply, HdrExtra0, Context), 92 Reply, 93 HdrExtra, 94 Context):- 95 !, 96 ( memberchk(connection(_), HdrExtra0) 97 -> HdrExtra = HdrExtra0 98 ; HdrExtra = [connection(Close)|HdrExtra0], 99 keep_alive(Reply, Close) 100 ). 101map_exception_to_http_status(error(existence_error(http_location, Location), _), 102 not_found(Location), 103 [connection(close)], 104 []) :- !. 105map_exception_to_http_status(error(permission_error(http_method, Method, Location), _), 106 method_not_allowed(Method, Location), 107 [connection(close)], 108 []) :- !. 109map_exception_to_http_status(error(permission_error(_, http_location, Location), _), 110 forbidden(Location), 111 [connection(close)], 112 []) :- !. 113map_exception_to_http_status(error(threads_in_pool(_Pool), _), 114 busy, 115 [connection(close)], 116 []) :- !. 117map_exception_to_http_status(E, 118 resource_error(E), 119 [connection(close)], 120 []) :- 121 is_resource_error(E), 122 !. 123map_exception_to_http_status(E, 124 bad_request(E2), 125 [connection(close)], 126 []) :- 127 bad_request_exception(E), 128 !, 129 discard_stack_trace(E, E2). 130map_exception_to_http_status(E, 131 server_error(E), 132 [connection(close)], 133 []). 134 135is_resource_error(error(resource_error(_), _)). 136 137bad_request_exception(error(Error, Context)) :- 138 nonvar(Error), 139 bad_request_error(Error, ContextGeneral), 140 ( var(ContextGeneral) 141 -> true 142 ; Context = context(_Stack, ContextInstance) 143 -> subsumes_term(ContextGeneral, ContextInstance) 144 ), 145 !. 146 147bad_request_error(Error, Context) :- 148 http:bad_request_error(Error, Context). 149bad_request_error(Error, Context) :- 150 default_bad_request_error(Error, Context). 151 152default_bad_request_error(domain_error(http_request, _), _). 153default_bad_request_error(existence_error(http_parameter, _), _). 154default_bad_request_error(type_error(_, _), http_parameter(_)). 155default_bad_request_error(syntax_error(http_request_line(_)), _). 156default_bad_request_error(syntax_error(http_request(_)), _). 157default_bad_request_error(syntax_error(_), in_http_request). 158 159discard_stack_trace(error(Formal, context(_,Msg)), 160 error(Formal, context(_,Msg))).
http:client_backtrace
is true
.167in_or_exclude_backtrace(Error, Error) :- 168 current_setting(http:client_backtrace), 169 setting(http:client_backtrace, true), 170 !. 171in_or_exclude_backtrace(Error0, Error) :- 172 discard_stack_trace(Error0, Error), 173 !. 174in_or_exclude_backtrace(Exception, Exception).
error(Formal, context(Stack,
Context))
is caught and subsumes_term(ContextTemplate, Context)
is true, translate the exception into an HTTP 400 exception. If
the exception contains a stack-trace, this is stripped from the
response.
The idea behind this hook is that applications can raise 400 responses by
199keep_alive(Reply, Connection) :- 200 ( keep_alive(Reply) 201 -> Connection = 'Keep-Alive' 202 ; Connection = close 203 ). 204 205keep_alive(not_modified). 206keep_alive(bytes(_Type, _Bytes)). 207keep_alive(file(_Type, _File)). 208keep_alive(tmp_file(_Type, _File)). 209keep_alive(stream(_In, _Len)). 210keep_alive(cgi_stream(_In, _Len)). 211keep_alive(switching_protocols(_Goal, _)). 212 213 214 /******************************* 215 * IDE SUPPORT * 216 *******************************/ 217 218% See library('trace/exceptions') 219 220:- multifile 221 prolog:general_exception/2. 222 223prolog:general_exception(http_reply(_), http_reply(_)). 224prolog:general_exception(http_reply(_,_), http_reply(_,_))
Map Prolog exceptions to HTTP errors
This module maps exceptions from various parts of the HTTP libraries as well as exceptions from user handler predicates into meaningful HTTP error codes such as 4XX and 5XX codes. For example, existence errors on http locations are mapped to 404 while out-of-stack is mapped to 503.
This library provides two hooks:
http_header.pl
,http_wrapper.pl
*/