I recently needed to read the HTTP POST data using a BASH cgi script.

When using BASH this way most of the HTTP variables are set as environment variables, and can be accessed simply. The exception is the HTTP POST data, this goes to the stdin stream.

There were some examples of reading stdin like:

1
POST_DATA=$(</dev/stdin)

and

1
POST_DATA=`cat /dev/stdin`

However I found that these intermittently failed. I believe this is because at the point of execution you can not guarantee that all the data has been sent.

The solution to this is to use the CONTENT_LENGTH environment variable to read the correct number of bytes:

1
2
3
4
5
6
#!/bin/bash
if [ "$REQUEST_METHOD" = "POST" ]; then
    if [ "$CONTENT_LENGTH" -gt 0 ]; then
        read -n $CONTENT_LENGTH POST_DATA <&0
    fi
fi