HTTP POST with JSON body, swi V7(latest)

388 views
Skip to first unread message

jonm...@gmail.com

unread,
Apr 28, 2016, 9:11:01 AM4/28/16
to SWI-Prolog
Hi,

Trying to do an outgoing HTTPS post with JSON body, equivalent to eg.


curl -X POST -H "Content-Type: application/json" -d '{
    "recipient":{
        "id":USER_ID
    }, 
    "message":{
        "text":"hello, world!"
    }
}

My problem is that I can't work out the predicates needed to take my data (which could be either a json term or dictionary..don't care/could implement as  either), convert it to json for output, then post it.

I know json is well supported, in that jsonsupport has a bunch of reply_ predicates, but they all assume (?) that you are replying to an incoming http connection that has already been made, But I want to do an outgoing http connect outside of any incoming connect.. They are just writing to the output stream.  ie. they can't write to a named output stream/variable? 

My first guess was to use http_post, but that uses http_post_data, which doesn't seem to support (docs say..) json as an output type)?), so how would it send the correct Content-Type header?

Then I thought maybe I could do an http_open, and reply_json after doing the outgoing open, but that too uses http_post_data, and there is no way to get reply_json to output to the stream opened by http_open, it goes to standard output ?

Thanks,
Jon.

Jan Wielemaker

unread,
Apr 28, 2016, 9:57:36 AM4/28/16
to jonm...@gmail.com, SWI-Prolog
Hi Jon,

http_post/4 is hookable and hooked by the json libraries. The pengines
code contains:

remote_post_rec(Server, Action, Data, Reply, Options) :-
server_url(Server, Action, [], URL),
probe(Action, URL),
http_open(URL, Stream,
[ post(json(Data))
| Options
]),
call_cleanup(
read_prolog_reply(Stream, Reply),
close(Stream)).

Where Data is a dict (but a term will work as well AFAIK).

Cheers --- Jan


On 28/04/16 15:11, jonm...@gmail.com wrote:
> Hi,
>
> Trying to do an outgoing HTTPS post with JSON body, equivalent to eg.
>
>
> |curl -X POST -H "Content-Type: application/json"-d '{ "recipient":{
> "id":USER_ID }, "message":{ "text":"hello, world!" } }|
>
>
> My problem is that I can't work out the predicates needed to take my
> data (which could be either a json term or dictionary..don't care/could
> implement as either), convert it to json for output, then post it.
>
> I know json is well supported, in that jsonsupport
> <http://www.swi-prolog.org/pldoc/man?section=jsonsupport >has a bunch of
> reply_ predicates, but they all assume (?) that you are replying to an
> incoming http connection that has already been made, But I want to do an
> outgoing http connect outside of any incoming connect.. They are just
> writing to the output stream. ie. they can't write to a named output
> stream/variable?
>
> My first guess was to use http_post
> <http://www.swi-prolog.org/pldoc/doc_for?object=http_post/4>, but that
> uses http_post_data
> <http://www.swi-prolog.org/pldoc/man?predicate=http_post_data/3>, which
> doesn't seem to support (docs say..) json as an output type)?), so how
> would it send the correct Content-Type header?
>
> Then I thought maybe I could do an http_open
> <http://www.swi-prolog.org/pldoc/man?predicate=http_open/3>, and
> reply_json
> <http://www.swi-prolog.org/pldoc/doc_for?object=http_json%3Areply_json/1> after
> doing the outgoing open, but that too uses http_post_data, and there is
> no way to get reply_json to output to the stream opened by http_open, it
> goes to standard output ?
>
> Thanks,
> Jon.
>
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to swi-prolog+...@googlegroups.com
> <mailto:swi-prolog+...@googlegroups.com>.
> Visit this group at https://groups.google.com/group/swi-prolog.
> For more options, visit https://groups.google.com/d/optout.

jonm...@gmail.com

unread,
Apr 29, 2016, 1:30:59 PM4/29/16
to SWI-Prolog
Brilliant - thanks Jan, it really was that simple.  Didn't even need http_post, http_open did the job as you suggested, with the post option:

JSON_Term = json([recipient=json([id=Sender_Id]), message=json([text=Message_Text])]),
http_open(
FB_Post_URL,
Stream,
[ post(json(JSON_Term)), 
status_code(Code)
]
),

close(Stream),
http_log("post http code is ~w~n", Code).

And just by using module http/http_ssl_plugin, having 'https' as the url prefix worked out of the box.

Thanks for your help!

Regards,
Jon.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages