In this article, I will go through how to spin up a stub/mock server and proxy server using netcat.

Stub Server

If you are working on any client application and if the service you want to consume is not yet ready, then you can spin up a mock/stub server using netcat.

For example, if you want to mock a service /api/companies store response like below in companies.txt.

HTTP/1.0 200 OK
Content-Type: application/json

[{"id": 1, "name": "Company One"}, {"id": 2, "name": "Company Two"}]

Protip: You can separate response headers and response body into two files.

For example, inside success_head.txt (a new line at the end is required, it separates headers from the body)

HTTP/1.1 200 OK
Content-type: application/json

Now you can start netcat like below

cat /tmp/companies.txt | nc -l 5000
# OR if you seperated headers and json
cat success_head.txt companies.json | nc -l 5000

If you send a request like the one below.

curl localhost:5000/api/companies

output -

[{"id": 1, "name": "Company One"}, {"id": 2, "name": "Company Two"}]

After serving the response, nc exits, you can use a loop to keep it permanently running - while true; do cat companies.txt | nc -l 5000; done

To come out of this, Ctrl+c won’t work; you need to use Ctrl+z and kill %1 to kill the job.

The nice thing about this approach is that you can send any path URL and request method and get your response. For example, if you send a curl request as

curl -H 'content-type:application/json' \
   localhost:5000/api/companies -d '{"x", "y"}'

In the nc logs, you will see

POST /api/companies HTTP/1.1
Host: localhost:5000
User-Agent: curl/7.64.1
Accept: */*
content-type:application/json
Content-Length: 10

{"x", "y"}

Of course, you can mock any response code with any content you want. For example, if you want to mock 404 not found, you can have something like the one below.

HTTP/1.0 404 Not found
Content-Type: application/json

{"message": "company does not exist"}

If you send a request like the one below, you should get the 404 response code.

curl -v -X PUT localhost:5000/api/companies/3 -d '{"x": "y"}'

*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 5000 (#0)
> PUT /api/companies/3 HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 10
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 10 out of 10 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 404 Not found
< Content-Type: application/json
<
{"message": "company does not exist"}

Let’s say you want to test your socket timeouts; you can do nc -l 5000 (you can use any port), now you can send a request, and it waits for the response until you send some response in nc -l 5000 prompt.

Proxy Server

You can also spin up a proxy using nc.

First, create tcpproxy.sh file with the below content

#!/bin/sh -e

if [ $# != 3 ]
then
    echo "usage: $0 <src-port> <dst-host> <dst-port>"
    exit 0
fi

while true
do
    echo "Press [CTRL+C] to stop.."
    TMP=`mktemp -d`
    BACK=$TMP/pipe.back
    SENT=$TMP/pipe.sent
    RCVD=$TMP/pipe.rcvd
    trap 'rm -rf "$TMP"' EXIT
    mkfifo -m 0600 "$BACK" "$SENT" "$RCVD"
    sed 's/^/ => /' <"$SENT" &
    sed 's/^/<=  /' <"$RCVD" &
    nc -l "$1" <"$BACK" | tee "$SENT" | nc "$2" "$3" | tee "$RCVD" >"$BACK"
done

Give permissions chmod 755 tcpproxy.sh

Now start the proxy

tcpproxy.sh 8812 localhost 5000

Now in the other terminal, start the stub server like below

cat companies.txt | nc -l 5000

Now at the client, make a call using http_proxy

http_proxy=localhost:8812 curl -v localhost:5000/api/companies

You should see this in tcpproxy.sh prompt when you send a request.

 => GET http://localhost:5000/api/companies HTTP/1.1
 => Host: localhost:5000
 => User-Agent: curl/7.64.1
 => Accept: */*
 => Proxy-Connection: Keep-Alive
 =>

<=  HTTP/1.0 200 OK
<=  Content-Type: application/json
<=
<=  [{"id": 1, "name": "Company One"}, {"id": 2, "name": "Company Two"}]

Note that you can only capture HTTP traffic with the above approach.

Netcat is a fantastic tool, and above are a few ways to use it to debug HTTP requests. I hope this helps.