HTTP requests via /dev/tcp

Redowan Delowar August 8, 2024
Source
I learned this neat Bash trick today where you can make a raw HTTP request using the /dev/tcp file descriptor without using tools like curl or wget. This came in handy while writing a health check script that needed to make a TCP request to a service. The following script opens a TCP connection and makes a simple GET request to example.com: Running this will print the response from the site to your console. The snippet first opens a TCP connection to example.com on port 80 and assigns file descriptor 3 to manage this connection. The exec ensures that the file descriptor 3 remains open for the duration of the script, allowing multiple read and write operations without needing to reopen the connection each time. Using a file descriptor makes the code cleaner. Without it, we'd need to redirect input and output directly to /dev/tcp/example.com/80 for each read and write operation, making the script more cumbersome and harder to read. Then we send an HTTP GET request to the server by echoing the request to file descriptor 3. The server's response is read and printed using cat <&3, which reads from the file descriptor and prints the output to the console. Finally, the script closes the connection by terminating file descriptor 3 with exec 3>&-. This is a Bash-specific trick and won't work in other shells like Zsh or Fish. It also allows you to open UDP connections in the same manner. The Bash manpage explains the usage like this: I used this to write the following health check script. I didn't want to install curl in a sidecar container that just runs a single health check process, keeping things simpler. The script makes a GET request to the service and checks that the HTTP status from the raw response is 200. If not, it exits with a non-zero status. Note that the script will fail if your service returns a 301 redirect code. Plus, you need to make raw textual HTTP requests, which can become cumbersome if you need to do anything beyond a simple GET call. At that point, you're better off using curl.

Discussion in the ATmosphere

Loading comments...