35
36:- module(http_exception,
37 [ map_exception_to_http_status/4, 38 39 in_or_exclude_backtrace/2 40 ]). 41:- use_module(library(settings), [current_setting/1, setting/2]). 42
59
60:- multifile
61 http:bad_request_error/2, 62 http:map_exception_to_http_status_hook/4. 63
68
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))).
162
167
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).
176
177
193
194
199
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 218
220
221:- multifile
222 prolog:general_exception/2. 223
224prolog:general_exception(http_reply(_), http_reply(_)).
225prolog:general_exception(http_reply(_,_), http_reply(_,_))