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 ]). 41:- use_module(library(settings), [current_setting/1, setting/2]).
60:- multifile 61 http:bad_request_error/2, % Formal, Context 62 http:map_exception_to_http_status_hook/4. % Exception, Reply, HdrExtra, Ctx
http(not_modified)
provides backward compatibility to http_reply(not_modified)
.69map_exception_to_http_status(Exception, Reply, HdrExtra, Context) :- 70 http:map_exception_to_http_status_hook(Exception, Reply, HdrExtra, Context), 71 !. 72map_exception_to_http_status(http(not_modified), 73 not_modified, 74 [connection('Keep-Alive')], 75 []) :- !. 76map_exception_to_http_status(http_reply(Reply), 77 Reply, 78 [connection(Close)], 79 []) :- 80 !, 81 keep_alive(Reply, Close). 82map_exception_to_http_status(http_reply(Reply, HdrExtra0), 83 Reply, 84 HdrExtra, 85 Context) :- 86 !, 87 map_exception_to_http_status(http_reply(Reply, HdrExtra0, []), 88 Reply, 89 HdrExtra, 90 Context). 91 92map_exception_to_http_status(http_reply(Reply, HdrExtra0, Context), 93 Reply, 94 HdrExtra, 95 Context):- 96 !, 97 ( memberchk(connection(_), HdrExtra0) 98 -> HdrExtra = HdrExtra0 99 ; HdrExtra = [connection(Close)|HdrExtra0], 100 keep_alive(Reply, Close) 101 ). 102map_exception_to_http_status(error(existence_error(http_location, Location), _), 103 not_found(Location), 104 [connection(close)], 105 []) :- !. 106map_exception_to_http_status(error(permission_error(http_method, Method, Location), _), 107 method_not_allowed(Method, Location), 108 [connection(close)], 109 []) :- !. 110map_exception_to_http_status(error(permission_error(_, http_location, Location), _), 111 forbidden(Location), 112 [connection(close)], 113 []) :- !. 114map_exception_to_http_status(error(threads_in_pool(_Pool), _), 115 busy, 116 [connection(close)], 117 []) :- !. 118map_exception_to_http_status(E, 119 resource_error(E), 120 [connection(close)], 121 []) :- 122 is_resource_error(E), 123 !. 124map_exception_to_http_status(E, 125 bad_request(E2), 126 [connection(close)], 127 []) :- 128 bad_request_exception(E), 129 !, 130 discard_stack_trace(E, E2). 131map_exception_to_http_status(E, 132 server_error(E), 133 [connection(close)], 134 []). 135 136is_resource_error(error(resource_error(_), _)). 137 138bad_request_exception(error(Error, Context)) :- 139 nonvar(Error), 140 bad_request_error(Error, ContextGeneral), 141 ( var(ContextGeneral) 142 -> true 143 ; Context = context(_Stack, ContextInstance) 144 -> subsumes_term(ContextGeneral, ContextInstance) 145 ), 146 !. 147 148bad_request_error(Error, Context) :- 149 http:bad_request_error(Error, Context). 150bad_request_error(Error, Context) :- 151 default_bad_request_error(Error, Context). 152 153default_bad_request_error(domain_error(http_request, _), _). 154default_bad_request_error(existence_error(http_parameter, _), _). 155default_bad_request_error(type_error(_, _), http_parameter(_)). 156default_bad_request_error(syntax_error(http_request_line(_)), _). 157default_bad_request_error(syntax_error(http_request(_)), _). 158default_bad_request_error(syntax_error(_), in_http_request). 159 160discard_stack_trace(error(Formal, context(_,Msg)), 161 error(Formal, context(_,Msg))).
http:client_backtrace
is true
.168in_or_exclude_backtrace(Error, Error) :- 169 current_setting(http:client_backtrace), 170 setting(http:client_backtrace, true), 171 !. 172in_or_exclude_backtrace(Error0, Error) :- 173 discard_stack_trace(Error0, Error), 174 !. 175in_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
200keep_alive(Reply, Connection) :- 201 ( keep_alive(Reply) 202 -> Connection = 'Keep-Alive' 203 ; Connection = close 204 ). 205 206keep_alive(not_modified). 207keep_alive(bytes(_Type, _Bytes)). 208keep_alive(file(_Type, _File)). 209keep_alive(tmp_file(_Type, _File)). 210keep_alive(stream(_In, _Len)). 211keep_alive(cgi_stream(_In, _Len)). 212keep_alive(switching_protocols(_Goal, _)). 213 214 215 /******************************* 216 * IDE SUPPORT * 217 *******************************/ 218 219% See library('trace/exceptions') 220 221:- multifile 222 prolog:general_exception/2. 223 224prolog:general_exception(http_reply(_), http_reply(_)). 225prolog: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
*/