Replying with JSON to an HTTP request

564 views Asked by At

I'm trying to send JSON after using this request: http://localhost:8080/json_test?id=1 This is my code so far:

:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_parameters)).

:- http_handler('/json_test', json_test, []).

nomeEdificio(1, "Torre dos Clérigos").
nomeEdificio(2, "Fonte dos Leões").

anoConstrucao(1, 1754).
anoConstrucao(2, 1882).

anoInauguracao(1, 1763).
anoInauguracao(2, 1884).

server(Port) :-                     
    http_server(http_dispatch, [port(Port)]).

json_test(Request) :-
http_parameters(Request,
                [ id(Id, [])]
                ),
    compute_request(Id,PrologOut),
    prolog_to_json(PrologOut,JSonOut),
    reply_json(JSonOut).

compute_request(Id,PrologOut):-
    nomeEdificio(Id,N), anoConstrucao(Id,Ac), anoInauguracao(Id,Ai), % Some consulting operations
    PrologOut = json([ name=N,
        dates=json([yearConstruction=Ac, yearInauguration=Ai])
    ]).

But I get this error:

"Internal server error

goal unexpectedly failed: user:json_test([protocol(http),peer(ip(127,0,0,1)),pool(client('httpd@8080',user:http_dispatch,<stream>(00000000056CE8C0),<stream>(00000000056CCD90))),input(<stream>(00000000056CE8C0)),method(get),request_uri('/json_test?id=1'),path('/json_test'),search([id='1']),http_version(1-1),host(localhost),port(8080),user_agent('Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'),accept([media(text/html,[],1.0,[]),media(application/'xhtml+xml',[],1.0,[]),media(application/xml,[],0.9,[]),media(_G3007/_G3008,[],0.8,[])]),accept_language('en-US,en;q=0.5'),accept_encoding('gzip, deflate'),connection('keep-alive'),upgrade_insecure_requests('1')])"

I can't figure out what's wrong, there's not much documentation about how to use these Prolog predicates. Any help is welcome, thanks.

1

There are 1 answers

2
mat On BEST ANSWER

Incomplete example

When I load the code you posted, I get:

    catch/3: Undefined procedure: http_handler/3

So, I added:

:- use_module(library(http/thread_httpd)).

Dispatching

Next, when I load the modified example and start the server with ?- server(4040)., and then visit http://localhost:4040/json_test, I get:

Internal server error

Undefined procedure: http_dispatch/1

So, I added:

:- use_module(library(http/http_dispatch)).

Parameters

Then, when I reload and revisit, I get:

Internal server error

Undefined procedure: http_parameters/2

So, I added:

:- use_module(library(http/http_parameters)).

With id

Of course, we must supply an id, so I visit for example:

http://localhost:4040/json_test?id=x

Then, I get:

Internal server error

Undefined procedure: nomeEdificio/2

To debug such problems, you need to simplify everything as far as you can, and post simplified, self-contained examples with clear instructions how to run your test case.

In the above, you have omitted:

  • essential directives which you obviously had included in your program
  • essential information on how to run your server
  • the definition of essential predicates that are used in your program.

You cannot expect others to fill such extreme omissions.

Replying JSON

As to your actual question, your main problem is completely overshadowed by what you posted. To reply JSON, here is an example.

First, obtaining JSON:

:- use_module(library(http/json_convert)).

:- json_object
      point(x:integer, y:integer).

Example query:

?- prolog_to_json(point(10,30), JSON).
JSON = json([x=10, y=30]).

This needs the directive above, otherwise it doesn't work! This is taken directly from the SWI-Prolog documentation, which is a good resource to find out more about these topics.

Then, to reply with such a term:

?- prolog_to_json(point(10,30), JSON),
   reply_json(JSON).
Content-type: application/json; charset=UTF-8

{"x":10, "y":30}
...

So, start small: Once you have this running without HTTP server, you can plug in the same code into an actual dispatch.