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) 2002-2016, 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_client, 37 [ http_get/3, % +URL, -Reply, +Options 38 http_delete/3, % +URL, -Reply, +Options 39 http_post/4, % +URL, +In, -Reply, +Options 40 http_put/4, % +URL, +In, -Reply, +Options 41 http_patch/4, % +URL, +In, -Reply, +Options 42 http_read_data/3, % +Header, -Data, :Options 43 http_disconnect/1 % +What 44 ]). 45:- autoload(http_header,[http_post_data/3]). 46:- autoload(http_stream,[http_chunked_open/3,stream_range_open/3]). 47:- autoload(library(error),[must_be/2]). 48:- autoload(library(lists),[delete/3,select/3]). 49:- autoload(library(memfile), 50 [ new_memory_file/1, open_memory_file/4, free_memory_file/1, 51 memory_file_to_atom/3, memory_file_to_string/3, 52 memory_file_to_codes/3, open_memory_file/3 53 ]). 54:- autoload(library(option), 55 [option/3,option/2,meta_options/3,select_option/3]). 56:- autoload(library(uri),[uri_query_components/2]). 57:- autoload(library(http/http_open), 58 [http_open/3,http_close_keep_alive/1]). 59 60:- meta_predicate 61 http_read_data( , , ). 62 63:- multifile 64 http_convert_data/4, % http_read_data plugin-hook 65 http:post_data_hook/3. 66 67:- predicate_options(http_get/3, 3, 68 [ pass_to(http_open/3, 3), 69 pass_to(http_read_data/3, 3) 70 ]). 71:- predicate_options(http_delete/3, 3, [pass_to(http_get/3, 3)]). 72:- predicate_options(http_post/4, 4, [pass_to(http_get/3, 3)]). 73:- predicate_options(http_put/4, 4, [pass_to(http_post/4, 4)]). 74:- predicate_options(http_read_data/3, 3, 75 [ to(any), 76 content_type(any), 77 form_data(oneof([form,mime])), 78 input_encoding(encoding), 79 on_filename(callable) 80 ]).
114 /******************************* 115 * GET * 116 *******************************/
Content-Type
header and plugins.
This predicate is the common implementation of the HTTP client
operations. The predicates http_delete/3, http_post/4 and
http_put/4 call this predicate with an appropriate
method(+Method)
option and ---for http_post/4 and http_put/4---
a post(+Data)
option.
Options are passed to http_open/3 and http_read_data/3. Other options:
headers(Fields)
from http_open/3. Provided for
backward compatibility. Note that http_version(Major-Minor)
is missing in the new version.136http_get(URL, Data, Options) :- 137 headers_option(Options, Options1, Headers), 138 option(reply_header(Headers), Options, _), 139 http_open(URL, In, Options1), 140 delete(Headers, transfer_encoding(_), Headers1), 141 call_cleanup( 142 http_read_data(In, Headers1, Data, Options), 143 close(In)). 144 145headers_option(Options, Options1, Headers) :- 146 option(headers(Headers), Options), 147 !, 148 Options1 = Options. 149headers_option(Options, [headers(Headers)|Options], Headers).
DELETE
method on the server. Arguments are the same
as for http_get/3. Typically one should pass the option
status_code(-Code)
to assess and evaluate the returned status
code. Without, codes other than 200 are interpreted as an error.
162http_delete(URL, Data, Options) :-
163 http_get(URL, Data, [method(delete)|Options]).
POST
request. Data is posted using
http_post_data/3. The HTTP server reply is returned in Reply,
using the same rules as for http_get/3.
174http_post(URL, Data, Reply, Options) :-
175 http_get(URL, Reply,
176 [ post(Data)
177 | Options
178 ]).
PUT
request. Arguments are the same as for
http_post/4.
187http_put(URL, In, Out, Options) :-
188 http_post(URL, In, Out, [method(put)|Options]).
PATCH
request. Arguments are the same as for
http_post/4.
197http_patch(URL, In, Out, Options) :-
198 http_post(URL, In, Out, [method(patch)|Options]).
to(Format)
option or based on the Content-type
in the Request. The following options are supported:
stream(+WriteStream)
)
Append the content of the message to Streammultipart/form-data
content.Without plugins, this predicate handles
Name=Value
terms.238http_read_data(Fields, Data, QOptions) :- 239 meta_options(is_meta, QOptions, Options), 240 memberchk(input(In), Fields), 241 ( http_read_data(In, Fields, Data, Options) 242 -> true 243 ; throw(error(failed(http_read_data), _)) 244 ). 245 246is_meta(on_filename). 247 248http_read_data(In, Fields, Data, Options) :- % Transfer-encoding: chunked 249 select(transfer_encoding(chunked), Fields, RestFields), 250 !, 251 setup_call_cleanup( 252 http_chunked_open(In, DataStream, []), 253 http_read_data(DataStream, RestFields, Data, Options), 254 close(DataStream)). 255http_read_data(In, Fields, Data, Options) :- 256 option(to(X), Options), 257 !, 258 ( X = stream(Stream) 259 -> ( memberchk(content_length(Bytes), Fields) 260 -> copy_stream_data(In, Stream, Bytes) 261 ; copy_stream_data(In, Stream) 262 ) 263 ; must_be(oneof([atom,string,codes]), X), 264 setup_call_cleanup( 265 new_memory_file(MemFile), 266 ( setup_call_cleanup( 267 open_memory_file(MemFile, write, Stream, 268 [encoding(octet)]), 269 ( memberchk(content_length(Bytes), Fields) 270 -> copy_stream_data(In, Stream, Bytes) 271 ; copy_stream_data(In, Stream) 272 ), 273 close(Stream)), 274 encoding(Fields, Encoding), 275 memory_file_to(X, MemFile, Encoding, Data0) 276 ), 277 free_memory_file(MemFile)), 278 Data = Data0 279 ). 280http_read_data(In, Fields, Data, _) :- 281 option(content_type(ContentType), Fields), 282 is_content_type(ContentType, 'application/x-www-form-urlencoded'), 283 !, 284 http_read_data(In, Fields, Codes, [to(string)]), 285 uri_query_components(Codes, Data). 286http_read_data(In, Fields, Data, Options) :- % call hook 287 ( select_option(content_type(Type), Options, Options1) 288 -> delete(Fields, content_type(_), Fields1), 289 http_convert_data(In, [content_type(Type)|Fields1], Data, Options1) 290 ; http_convert_data(In, Fields, Data, Options) 291 ), 292 !. 293http_read_data(In, Fields, Data, Options) :- 294 http_read_data(In, Fields, Data, [to(atom)|Options]). 295 296memory_file_to(atom, MemFile, Encoding, Data) :- 297 memory_file_to_atom(MemFile, Data, Encoding). 298memory_file_to(string, MemFile, Encoding, Data) :- 299 memory_file_to_string(MemFile, Data, Encoding). 300memory_file_to(codes, MemFile, Encoding, Data) :- 301 memory_file_to_codes(MemFile, Data, Encoding). 302 303 304encoding(Fields, utf8) :- 305 memberchk(content_type(Type), Fields), 306 ( sub_atom(Type, _, _, _, 'UTF-8') 307 -> true 308 ; sub_atom(Type, _, _, _, 'utf-8') 309 ), 310 !. 311encoding(_, octet). 312 313is_content_type(ContentType, Check) :- 314 sub_atom(ContentType, 0, Len, After, Check), 315 ( After == 0 316 -> true 317 ; sub_atom(ContentType, Len, 1, _, ';') 318 ).
328http_convert_data(In, Fields, Data, Options) :-
329 memberchk(content_type(Type), Fields),
330 is_content_type(Type, 'application/x-prolog'),
331 !,
332 ( memberchk(content_length(Bytes), Fields)
333 -> setup_call_cleanup(
334 ( stream_range_open(In, Range, [size(Bytes)]),
335 set_stream(Range, encoding(utf8)),
336 set_stream(Range, file_name('HTTP:DATA'))
337 ),
338 read_term(Range, Data, Options),
339 close(Range))
340 ; set_stream(In, encoding(utf8)),
341 read_term(In, Data, Options)
342 ).
all
, closing all connections.
352http_disconnect(all) :-
353 http_close_keep_alive(_).
post(Data)
option
of http_open/3. The default implementation supports
prolog(Term)
, sending a Prolog term as application/x-prolog
.
361httppost_data_hook(prolog(Term), Out, HdrExtra) :-
362 setup_call_cleanup(
363 ( new_memory_file(MemFile),
364 open_memory_file(MemFile, write, Handle)
365 ),
366 ( format(Handle,
367 'Content-Type: application/x-prolog; charset=UTF-8~n~n',
368 []),
369 write_term(Handle, Term,
370 [ quoted(true),
371 ignore_ops(true),
372 fullstop(true),
373 nl(true)
374 ])
375 ),
376 close(Handle)),
377 setup_call_cleanup(
378 open_memory_file(MemFile, read, RdHandle,
379 [ free_on_close(true)
380 ]),
381 http_post_data(cgi_stream(RdHandle), Out, HdrExtra),
382 close(RdHandle))
HTTP client library
This library provides the four basic HTTP client actions:
GET
,DELETE
,POST
andPUT
. In addition, it provides http_read_data/3, which is used by library(http/http_parameters) to decodePOST
data in server applications.This library is based on http_open/3, which opens a URL as a Prolog stream. The reply is processed by http_read_data/3. The following content-types are supported. Options passed to http_get/3 and friends are passed to http_read_data/3, which in turn passes them to the conversion predicates. Support for additional content types can be added by extending the multifile predicate http_client:http_convert_data/4.
Name=Value
terms.json_object(As)
can be used to return a termjson(Attributes)
(As isterm
) or a dict (As isdict
). */