35
36:- module(http_exception,
37 [ map_exception_to_http_status/4, 38 39 in_or_exclude_backtrace/2 40 ]).
41
54
55:- multifile
56 http:bad_request_error/2. 57
63
64map_exception_to_http_status(http(not_modified),
65 not_modified,
66 [connection('Keep-Alive')],
67 []) :- !.
68map_exception_to_http_status(http_reply(Reply),
69 Reply,
70 [connection(Close)],
71 []) :-
72 !,
73 keep_alive(Reply, Close).
74map_exception_to_http_status(http_reply(Reply, HdrExtra0),
75 Reply,
76 HdrExtra,
77 Context) :-
78 !,
79 map_exception_to_http_status(http_reply(Reply, HdrExtra0, []),
80 Reply,
81 HdrExtra,
82 Context).
83
84map_exception_to_http_status(http_reply(Reply, HdrExtra0, Context),
85 Reply,
86 HdrExtra,
87 Context):-
88 !,
89 ( memberchk(connection(_), HdrExtra0)
90 -> HdrExtra = HdrExtra0
91 ; HdrExtra = [connection(Close)|HdrExtra0],
92 keep_alive(Reply, Close)
93 ).
94map_exception_to_http_status(error(existence_error(http_location, Location), _),
95 not_found(Location),
96 [connection(close)],
97 []) :- !.
98map_exception_to_http_status(error(permission_error(http_method, Method, Location), _),
99 method_not_allowed(Method, Location),
100 [connection(close)],
101 []) :- !.
102map_exception_to_http_status(error(permission_error(_, http_location, Location), _),
103 forbidden(Location),
104 [connection(close)],
105 []) :- !.
106map_exception_to_http_status(error(threads_in_pool(_Pool), _),
107 busy,
108 [connection(close)],
109 []) :- !.
110map_exception_to_http_status(E,
111 resource_error(E),
112 [connection(close)],
113 []) :-
114 resource_error(E),
115 !.
116map_exception_to_http_status(E,
117 bad_request(E2),
118 [connection(close)],
119 []) :-
120 bad_request_exception(E),
121 !,
122 discard_stack_trace(E, E2).
123map_exception_to_http_status(E,
124 server_error(E),
125 [connection(close)],
126 []).
127
128resource_error(error(resource_error(_), _)).
129
130bad_request_exception(error(Error, Context)) :-
131 nonvar(Error),
132 bad_request_error(Error, ContextGeneral),
133 ( var(ContextGeneral)
134 -> true
135 ; Context = context(_Stack, ContextInstance)
136 -> subsumes_term(ContextGeneral, ContextInstance)
137 ),
138 !.
139
140bad_request_error(Error, Context) :-
141 http:bad_request_error(Error, Context).
142bad_request_error(Error, Context) :-
143 default_bad_request_error(Error, Context).
144
145default_bad_request_error(domain_error(http_request, _), _).
146default_bad_request_error(existence_error(http_parameter, _), _).
147default_bad_request_error(type_error(_, _), http_parameter(_)).
148default_bad_request_error(syntax_error(http_request_line(_)), _).
149default_bad_request_error(syntax_error(http_request(_)), _).
150default_bad_request_error(syntax_error(_), in_http_request).
151
152discard_stack_trace(error(Formal, context(_,Msg)),
153 error(Formal, context(_,Msg))).
154
159
160in_or_exclude_backtrace(Error, Error) :-
161 current_setting(http:client_backtrace),
162 setting(http:client_backtrace, true),
163 !.
164in_or_exclude_backtrace(Error0, Error) :-
165 discard_stack_trace(Error0, Error),
166 !.
167in_or_exclude_backtrace(Exception, Exception).
168
169
185
186
191
192keep_alive(Reply, Connection) :-
193 ( keep_alive(Reply)
194 -> Connection = 'Keep-Alive'
195 ; Connection = close
196 ).
197
198keep_alive(not_modified).
199keep_alive(bytes(_Type, _Bytes)).
200keep_alive(file(_Type, _File)).
201keep_alive(tmp_file(_Type, _File)).
202keep_alive(stream(_In, _Len)).
203keep_alive(cgi_stream(_In, _Len)).
204keep_alive(switching_protocols(_Goal, _)).
205
206
207 210
212
213:- multifile
214 prolog:general_exception/2.
215
216prolog:general_exception(http_reply(_), http_reply(_)).
217prolog:general_exception(http_reply(_,_), http_reply(_,_)).