Reply

I’m using: SWI-Prolog version: 9.3.24 for x86_64-linux

I am writing a web server in Prolog and I want it to return an image file, but only if the user is authorized; otherwise I want to return an error response “Bad request”.

I have seen that some tutorials suggest to do “throw(http_reply(400))”, but I to don’t want to return an error page, because the application does not expect a page, but a binary file. I want it to return something like this:

HTTP/1.1 400 Bad request\r\n

What is the right way to do this?

This is a simplified version of my code:


:-http_handler(root('get_file'),  get_file, []).

get_file(Request):-
   ( 
       authorized(Request),
       get_file_name(Request,FileName)
   ->
       http_reply_file(FileName, [], Request)
  ;
       format("HTTP/1.1 400 Bad request\r\n\r\n",[])
  ).

This code does not work. I get

…error("goal unexpectedly failed: user:get_file(…

Please help. Thank you.

you have to send the http header first of all.
the header contains the information for the response, and the body length
for the message you would like to send.

I think that is mostly the problem with the application. It is quite common that a request for a location may return a (text) error document rather than the expected type.

And no, you cannot affect the first line of the reply this way. That is always generated. The files http_exception.pl and http_header.pl provide hooks that first map exceptions to a Prolog term expressing the reply and then into a concrete document. That can be used to formulate arbitrary replies for error and non-200 status pages. I’d stay away from this though and fix the client.

1 Like

Could you please explain in more details how to formulate arbitrary replies for error and non-200 status pages?

I see in http_header.pl:

http:map_exception_to_http_status_hook/4. % Exception, Reply, HdrExtra, Ctx

Is this the predicate that I have to define? I could not find a good documentation on how to use this.

Hello,

for testing, you can simply create a CGI like Application, that send
a http header.

:- use_module(library(http/http_client)).
:- use_module(library(http/http_open)).

send_http_header(URL, HeaderName, HeaderValue) :-
     setup_call_cleanup(
         http_open(URL, Stream, [request_header(HeaderName = HeaderValue)]),
         read_string(Stream, _, Response),
         close(Stream)
     ),
     format('Response: ~s~n', [Response]).

?- send_http_header('https://localhost.org/headers',
    'X-Custom-Header',
    'your value').
% http_open/3                    opens a HTTP connection
% request_header(Name = Value)   set a HTTP header
% setup_call_cleanup/3           close the stream
% read_string/3                  read server response as string

Happy proller
Jens

@paule32, thank you for looking into this, but it seems that either you don’t understand my question, or I don’t understand your answer.

My previous post was related to Jan’s comment: " The files http_exception.pl and http_header.pl provide hooks that first map exceptions to a Prolog term expressing the reply and then into a concrete document. That can be used to formulate arbitrary replies for error and non-200 status pages."

If possible, I would like Jan (or somebody else) to elaborate on this, and provide an example how would I use these hooks to generate a non-200 status reply.

You can check out the library(http/http_json), which uses these hooks to provide JSON error messages in case the headers indicate to prefer that.

Not you can emit any content with a non-200 code by sending the Status header first. For example:

format('Status: 404~n'),
format('Content-type: text/plain~n~n'),
format('No such document!~n').