35
36:- module(http_exception,
37 [ map_exception_to_http_status/4, 38 39 in_or_exclude_backtrace/2 40 ]). 41
58
59:- multifile
60 http:bad_request_error/2, 61 http:map_exception_to_http_status_hook/4. 62
67
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 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
135resource_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))).
161
166
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).
175
176
192
193
198
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 217
219
220:- multifile
221 prolog:general_exception/2. 222
223prolog:general_exception(http_reply(_), http_reply(_)).
224prolog:general_exception(http_reply(_,_), http_reply(_,_))