Re: [PATCH] Support DELETE verb in http_open/3

Wouter Beek <[email protected]>
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <CAE1un7NvqM85iR7ft8Q0PttZoCd_zNbV5NzSV6TX_NwV6ZwW7w@mail.gmail.com>
Hi Michael,

That's great! My impression is that the HTTP package is in principle able
to support all HTTP methods, but that many higher-level predicates contain
unnecessary restrictions on the HTTP method allowed (mostly POST and GET).

Here's a workaround module that I'm using now, providing (1) variants of
http_parameters/[2,3] that work for non-POST methods and JSON data, and (2)
a variant of http_read_json/2 that works for non-POST methods. (Maybe it
comes in handy.)

~~~{.pl}
:- module(
  json_ext,
  [
    http_parameters2/2, % +Request:list
                        % ?Params:list
    http_parameters2/3, % +Request:list
                        % ?Params:list
                        % :Options:list
    http_read_json2/2 % +Request:list
                      % -JSON:compound
  ]
).
:- reexport(
  library(http/http_json),
  [
    http_read_json/2,
    http_read_json/3,
    reply_json/1,
    reply_json/2
  ]
).

:- use_module(library(error)).
:- use_module(library(http/http_client)).
:- use_module(library(http/http_parameters)).
:- use_module(library(option)).

:- meta_predicate(http_parameters2(+,?,:)).

%! http_parameters2(+Request, ?Params)
% @see Like http_parameters/2, but works for JSON as well and
%      is not restricted to the POST method.

http_parameters2(Request, Params) :-
  http_parameters2(Request, Params, []).

%! http_parameters2(+Request, ?Params, :Options)
% @see Like http_parameters/2, but works for JSON as well and
%      is not restricted to the POST method.

http_parameters2(Request, Params, Options) :-
    must_be(list, Params),
    meta_options(http_parameters:is_meta, Options, QOptions),
    option(attribute_declarations(DeclGoal), QOptions, -),
    http_parms2(Request, Params, DeclGoal, Form),
    (   memberchk(form_data(RForm), QOptions)
    ->  RForm = Form
    ;   true
    ).

http_parms2(Request, Params, DeclGoal, Data2) :-
  memberchk(content_type(Type), Request),
  http_json:is_json_type(Type), !,
  http_read_data(Request, Data1, []),
  Data1 = json(Data2),
  http_parameters:fill_parameters(Params, Data2, DeclGoal).

%! http_read_json2(+Request:list(nvpair), -JSON:compound) is det.
% @see Like http_read_json/2, but is not restricted to the HTTP POST method.

http_read_json2(Request, JSON):-
  memberchk(content_type(Type), Request),
  (
    http_json:is_json_type(Type)
  ->
    http_read_data(Request, JSON, [])
  ;
    domain_error(mimetype, Type)
  ).
~~~

---
Cheers!,
Wouter.

E-mail: [email protected]
WWW: www.wouterbeek.com
Tel.: 0647674624


On Sun, Jul 21, 2013 at 5:10 AM, Michael Hendricks <[email protected]>wrote:

> As requested by Wouter Beek, this patch adds support for HTTP 1.1 verb
> DELETE.  Its implementation is very similar to GET and HEAD.
>
> I actually needed this for a project I'm working.  Without this patch,
> I got this:
>
>     ?- http_open('http://127.0.0.1:3000/foo', Stream, [method(delete)]),
>     |    close(Stream).
>     ERROR: Domain error: `method' expected, found `delete'
>
> With this patch, I get:
>
>     Stream = <stream>(0x7fb71212e070).
>
> and the correct request is made to the server.
> ---
>  http_open.pl | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git http_open.pl http_open.pl
> index 4014ecd..1d0a96c 100644
> --- http_open.pl
> +++ http_open.pl
> @@ -54,7 +54,7 @@ two additional modules that acts as plugins:
>
>      * library(http/http_header)
>      Loading this library causes http_open/3 to support the =POST= method
> -    in addition to =GET= and =HEAD=.
> +    in addition to =GET=, =HEAD= and =DELETE=.
>
>      * library(http/http_ssl_plugin)
>      Loading this library causes http_open/3 HTTPS connections.  Relevant
> @@ -106,7 +106,7 @@ resource. See also parse_time/2.
>                      [ authorization(compound),
>                        final_url(-atom),
>                        header(+atom, -atom),
> -                      method(oneof([get,head,post])),
> +                      method(oneof([delete,get,head,post])),
>                        size(-integer),
>                        status_code(-integer),
>                        timeout(number),
> @@ -155,7 +155,8 @@ user_agent('SWI-Prolog').
>  %        AtomValue is unified to the empty atom ('').
>  %
>  %        * method(+Method)
> -%        One of =get= (default) or =head=.   The  =head= message can be
> +%        One of =get= (default), =head= or =delete=.
> +%        The  =head= message can be
>  %        used in combination with  the   header(Name,  Value) option to
>  %        access information on the resource   without actually fetching
>  %        the resource itself.  The  returned   stream  must  be  closed
> @@ -348,6 +349,7 @@ method(Options, MNAME) :-
>         ;   domain_error(method, M)
>         ).
>
> +map_method(delete, 'DELETE').
>  map_method(get,  'GET').
>  map_method(head, 'HEAD').
>  map_method(post, 'POST') :-
> @@ -472,6 +474,7 @@ redirect_options(Options0, Options) :-
>         ;   Options = Options1
>         ).
>
> +redirect_method(delete).
>  redirect_method(get).
>  redirect_method(head).
>
> --
> 1.8.2.3
>
>
>
-------------- next part --------------
HTML attachment scrubbed and removed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.