问题描述
在过去的几个小时里,我一直在绞尽脑汁,试图使用 socat 构建一个穷人的 http 服务器。不要问为什么或建议替代方案。我需要在纯 bash 中执行此操作。所以我像这样运行 socat:
socat -v TCP-LISTEN:1234,reuseaddr,fork SYstem:./httpd.sh
httpd.sh 应该读取 http 请求,解析它然后发送响应。
例如GET /index.html 将输出 Index! 而 GET /random 将输出一个随机数。
我遇到的问题是读取整个 http 请求。考虑以下用于读取 http 请求的每一行的代码:
while read -r LINE
do
echo "$LINE"
done
通常它应该将请求输出回浏览器。问题是在我打开 127.0.0.1:1234 后它只是挂起等待某些东西。如果我 CTRL + C socat,连接将关闭并且响应显示在浏览器中。我认为 while 循环会一直持续下去,从而阻止了响应的传输。
如果我使用下面的代码:
while read -r LINE
do
echo "$LINE"
[ -z "$LINE" ] && break
done
while 循环中断,浏览器不再挂起。似乎是一个很好的解决方案。但是...在 POST 请求的情况下,不会记录 POST 数据,因为中断发生在标题(空行)之后...
POST /index.html HTTP/1.0
User-Agent: Firefox
Content-Type: application/x-www-form-urlencoded
parameter1=test
如何通过 shell 脚本读取整个 http 请求,处理它并发送响应而不挂起?
编辑:
我认为这可能是答案。如果我运行这个命令:
socat TCP4-LISTEN:1234,fork,crlf SYstem:"echo hello world"
一切正常,每次都输出hello world。
socat 如何知道 HTTP 请求何时结束?
解决方法
如何通过 shell 脚本读取整个 http 请求,处理它并发送响应而不挂起?
在您撰写本文时,您已经有了 GET 的解决方案;在 POST 请求的情况下,您只需要再读一行(多个数据值 &
分隔在一行上)。发送响应后,您必须退出 httpd.sh
或至少关闭其输出。
socat 如何知道 HTTP 请求何时结束?
socat
知道 响应 在来自 echo
的数据管道在该进程终止时关闭时结束。
您无法逐行读取请求。 HTTP 请求可能包含换行符。您需要阅读整个请求并对其进行解析。
对于 GET 请求或 Head 请求,您只需要标题,因此您只能读取一行。
对于帖子,您需要读取内容长度标头中规定的字节数,或者直到您收到 EOF。
可以说,您的脚本变得更加复杂了。