I replicated your problem. When I connect with another nc
instead of a browser, I see the reply is being sent immediately. I think your browser also receives the reply but since nc
doesn't terminate the connection, the browser doesn't know it's all and it's OK to proceed with redirection.
(Note: during my tests I needed the final \r\n
in the reply from nc
to successfully redirect my browser, therefore all my examples use this fix.)
Edit: simple fix
Here I have found the following:
HTTP requests and HTTP responses use a generic message format of RFC 822 for transferring the required data. This generic message format consists of the following four items.
- [...]
- [...]
- An empty line (i.e., a line with nothing preceding the CRLF)
indicating the end of the header fields
- [...]
So your reply should be:
printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/\r\n\r\n' | ...
After receiving this, your browser should continue with redirection, terminating the connection to nc
on its own behalf. In early December 2017 it works with Opera and Vivaldi; it doesn't work with Firefox, Chrome or Safari, for which you may need another fix (see below).
Original, now inferior answer (it may still be useful for non-HTTP communication with nc
)
According to this answer on Server Fault you need to use -c
, -q
or similar option, depending on nc
implementation.
In my Debian I have the -q
capable version installed. Then
printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/\r\n' | nc -q 0 -l -p 2345
works fine (note I also need -p
to specify port). The explanation is:
-q seconds
after EOF
on stdin
, wait the specified number of seconds and then quit. If seconds is negative, wait forever (default).
If your nc
has no proper option then the workaround may be to detect communication from a client and kill the entire command line. An example that works in my Debian, bash
:
printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/\r\n' | nc -l -p 2345 | { read foo; sleep 1; kill 0; }
When running a pipe, bash
places every process in a single process group; kill 0
sends signals to its entire process group. This way nc
is killed about 1 second after any request is received that triggers read
.
(1) How do you know that the
nc
process is “stuck”? Have you done anstrace
or sniffed the network? (2) But first, try adding another\r\n
to the end of theprintf
text string. – G-Man Says 'Reinstate Monica' – 2017-12-04T05:30:25.063