当使用netcat时,如何基于请求有条件地响应

7
我正在尝试使用Windows批处理脚本设置Web服务器。
我已经编写了以下脚本:
@echo off
@setlocal  enabledelayedexpansion

for /l %%a in (1,0,2) do (
  type tempfile.txt | nc -w 1 -l -p 80  | findstr mystring
  if !ERRORLEVEL! == 0 (
    echo found > tempfile.txt
  ) else (
    echo not-found > tempfile.txt
  )
)

然而,响应始终滞后于请求,也就是说,如果我在浏览器中键入以下内容:
REQUEST: localhost/mystring

我将得到以下响应:
RESPONSE: not-found

只有在下一次请求中,我才能收到上述请求的正确答案。

这是因为一旦 netcat 接收到一个请求,它就会响应 tempfile.txt 的当前内容,而这个文件还没有根据请求进行更新。

是否有任何方法可以阻止响应,直到 tempfile.txt 更新或者其他可以实现期望结果的方法?


1
你正在用字符串“found”或“not-found”覆盖tempfile.txt的内容;你的代码根本不应该工作。 - SomethingDark
@SomethingDark 我相信那是有意的。它们不是日志,而是用来包含HTTP内容的。OP想知道的是如何根据浏览器请求头内容使nc TCP输出成为有条件的。 - rojo
@rojo - 他正在覆盖一个他正在传输到netcat的文件。Netcat 应该会吐出一堆错误信息。 - SomethingDark
@SomethingDark 当“findstr”执行时,Netcat的执行已经完成。Netcat对“tempfile.txt”的下一次循环迭代发生的情况并不关心。 - rojo
第一次迭代后,tempfile.txt 将仅包含字符串 "found" 或 "not found"。我不明白脚本如何成功运行多次。 - SomethingDark
显示剩余2条评论
2个回答

5

请查看-e选项,您可以编写一个脚本来进行处理,然后执行。

nc -L -w1 -p 80 -eexec.bat

这将会像您想要的那样,从nc到脚本中传输stdin和stdout。

exec.bat可能是以下内容(有点伪代码):

findstr mystring
if not errorlevel 1 (echo found) else (echo not-found)

或许使用一个循环(也可以用伪代码表示):
:top
set /p input=
if input wasn't "" echo %input% >> output.dat && goto top
findstr /C:"mystring" output.dat
if not errorlevel 1 (echo found) else (echo not-found)

你能提供任何工作代码作为概念证明吗?如果可以的话,你使用了哪个版本的netcat来运行你的代码?我尝试了使用netcat 1.12 for Win32/64的每种排列组合,但无论是x86还是x64构建,我都无法让“-e”开关运行批处理脚本并将其输出发送到客户端。Firebug始终显示GET请求状态为“已中止”。 - rojo
是的,我正在使用Linux系统,但需要大约4个半小时后才能回复您。 - cure
把它改成6.5。我正在做。 - cure
哎呀,这是一个有文档记录的功能,但我就是无论如何也无法让它正常工作。它可以很好地与可执行文件配合使用,我想知道是否批处理脚本在非交互会话中运行时会出现问题?真的很抱歉,这是一个有文档记录的功能...我还在继续研究它。 - cure

3
问题是,据我所知,nc不能执行回调函数以根据客户端输入定制其输出。一旦你有了...
stdout generation | nc -l

当一个程序在阻塞并等待连接时,它的输出已经确定了。此时输出是静态的。

我想到的唯一解决方法效率相对较低。基本上涉及以下逻辑:

  1. 监听准备让客户端执行重新加载的连接
  2. 从前一个请求的头部中获取GET地址。
  3. 在客户端的第二个连接上提供相关内容

示例代码:

@echo off & setlocal

rem // macro for netcat command line and args
set "nc=\cygwin64\bin\nc.exe -w 1 -l 80"

rem // macro for sending refresh header
set "refresh=^(echo HTTP/1.1 200 OK^&echo Refresh:0;^)^| %nc%"

for /L %%# in (1,0,2) do (
    rem // run refresh macro and capture client's requested URL
    for /f "tokens=2" %%I in ('%refresh% ^| findstr "^GET"') do set "URL=%%I"

    rem // serve content to the client
    setlocal enabledelayedexpansion
    echo URL: !URL! | %nc%
    endlocal
)

作为一方面的注释,如果启用了延迟扩展并在设置变量值时启用,可能会破坏使用感叹号标记设置的变量值。最好等到检索时再启用延迟扩展。
此外,在对%ERRORLEVEL%执行布尔检查时,更加优美的方式是使用条件执行。但这与我的解决方案无关。 :)
最后,考虑使用<filename.html nc -l(或nc -l <filename.html)而不是type filename.html | nc -l,以避免无用的type的使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接