Simple systemd socket activation from HTTP request
0
votes
1
answer
1259
views
I want to use systemd socket activation to start a service whenever an HTTP request is received on the listening socket. The incoming message is not important and can be discarded by systemd or the service it starts. I have been able to do this, but not without the HTTP sender crashing with errors of
Connection reset by peer
. I would like to satisfy the sending HTTP client, closing sockets or HTTP exchanges properly.
First, I have a question of whether to use Accept=yes
or no
in the .socket
file. For example:
echo.socket
:
[Unit]
Description=Example echo socket
[Socket]
ListenStream=127.0.0.1:33300
Accept=yes
[Install]
WantedBy=sockets.target
In man systemd.socket
, it is suggested that
> For performance reasons, it is recommended to write new daemons only in a way that is suitable for Accept=no
.
However, I guess the name Accept=
implies whether or not the incoming connection on the socket has been accepted (I guess calling accept()
at the kernel level), because with Accept=no
the burden is on the started service to accept and handle connections on the socket. See, for example, [this question](https://unix.stackexchange.com/questions/573767/systemd-socket-based-activation-service-fails-due-to-start-request-repeated-too) and its answer. I would really like it if I could follow the man page's recommendation and use Accept=no
, but the answer in the aformentioned question implies I would need to invoke some kind of TCP server, which is an additional learning curve and layer of complexity I might like to avoid if possible. (Any answers along these lines would certainly be acceptable though.)
So, assume then I use Accept=yes
, and I also have echo@.service
:
[Unit]
Description=echo service
[Service]
ExecStart=sh -c 'echo -e "HTTP/1.1 200 OK\nContent-Type: text/plain; charset=utf-8\nConnection: close\n\nOK"'
StandardInput=socket
StandardOutput=socket
Sending HTTP requests works to activate the service, but the client doesn't like it:
$ curl 'http://127.0.0.1:33300 '
OK
curl: (56) Recv failure: Connection reset by peer
$ journalctl --user -e
Jun 13 14:02:59 myhost systemd: Started echo service (127.0.0.1:39908).
(Try also, for example, python -c "import requests; r = requests.get('http://127.0.0.1:33300 '); print(r.status_code)"
.)
A simple socat
without any HTTP seems to exit without issue though.
$ socat - TCP:127.0.0.1:33300
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Connection: close
OK
I don't know what the issue is here, if systemd closes the connection too abruptly for the HTTP exchange, if the HTTP exchange is missing some extra closing message, or something else. And, as mentioned above, I'm still curious about Accept=no
solutions too.
Asked by tsj
(207 rep)
Jun 13, 2024, 06:16 PM
Last activity: Jun 14, 2024, 03:31 PM
Last activity: Jun 14, 2024, 03:31 PM