# Reply

**URL:** <https://swi-prolog.discourse.group/t/reply/9061>\
**Category:** Help!\
**Tags:** http\
**Created:** [June 20, 2025, 1:14am UTC](https://swi-prolog.discourse.group/t/reply/9061 "2025-06-20T01:14:31Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![tinkersaur](https://avatars.discourse-cdn.com/v4/letter/t/ad7895/32.png) [@tinkersaur](https://swi-prolog.discourse.group/u/tinkersaur)\
**Post date:** [June 20, 2025, 1:14am UTC](https://swi-prolog.discourse.group/t/reply/9061/1 "2025-06-20T01:14:31Z")

</div>

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:

```prolog

:-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.

---

<div class="post-metadata">

**Author:** ![paule32](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/paule32/32/5112_2.png) [@paule32](https://swi-prolog.discourse.group/u/paule32)\
**Post date:** [June 20, 2025, 6:39am UTC](https://swi-prolog.discourse.group/t/reply/9061/2 "2025-06-20T06:39:04Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [June 20, 2025, 7:09am UTC](https://swi-prolog.discourse.group/t/reply/9061/3 "2025-06-20T07:09:41Z")

</div>

> [@tinkersaur](#):
>
> 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 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.

---

<div class="post-metadata">

**Author:** ![tinkersaur](https://avatars.discourse-cdn.com/v4/letter/t/ad7895/32.png) [@tinkersaur](https://swi-prolog.discourse.group/u/tinkersaur)\
**Post date:** [June 21, 2025, 4:47am UTC](https://swi-prolog.discourse.group/t/reply/9061/4 "2025-06-21T04:47:08Z")

</div>

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:

```prolog
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.

---

<div class="post-metadata">

**Author:** ![paule32](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/paule32/32/5112_2.png) [@paule32](https://swi-prolog.discourse.group/u/paule32)\
**Post date:** [June 21, 2025, 9:18am UTC](https://swi-prolog.discourse.group/t/reply/9061/5 "2025-06-21T09:18:18Z")

</div>

Hello,

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

```prolog
:- 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').

```

```prolog
% 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

---

<div class="post-metadata">

**Author:** ![tinkersaur](https://avatars.discourse-cdn.com/v4/letter/t/ad7895/32.png) [@tinkersaur](https://swi-prolog.discourse.group/u/tinkersaur)\
**Post date:** [June 21, 2025, 2:39pm UTC](https://swi-prolog.discourse.group/t/reply/9061/7 "2025-06-21T14:39:19Z")

</div>

@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.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [June 21, 2025, 3:14pm UTC](https://swi-prolog.discourse.group/t/reply/9061/8 "2025-06-21T15:14:01Z")

</div>

> [@tinkersaur](#):
>
> 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:

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

```
