Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to respond conditionally based on the request when using netcat

I am trying to set up a web server using only windows batch scripting.

I have already come up with the following script:

@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
  )
)

However, the response is always one request behind, I mean, if I type something like this into the browser:

REQUEST: localhost/mystring

I will get the following response:

RESPONSE: not-found

Only in the next request I will receive the correct answer for the request presented above.

This is happening because as soon as netcat receives a request it responds with the current content of the tempfile.txt which has not been updated yet based on the request.

Is there any way to block the response until the tempfile.txt is updated or any other method which accomplish the expected result?

like image 208
utxeee Avatar asked Oct 17 '16 08:10

utxeee


People also ask

What is netcat command used for?

The Netcat ( nc ) command is a command-line utility for reading and writing data between two computer networks. The communication happens using either TCP or UDP. The command differs depending on the system ( netcat , nc , ncat , and others).

How do I start netcat in listen mode?

The command nc –l will put Netcat into server or listening mode, and nc by itself will run Netcat in client mode.

What does the switch do in netcat?

The –v switch is the parameter for using Netcat in verbose mode. Verbosity is simply the amount of feedback that the utility provides back to the screen during operation. Netcat also supports –vv (double v) for additional verbosity that will give you the number of bytes transferred during a file transfer.

How do I listen to a port in nc?

To listen on port 80, use the nc command with the —v (verbose) —l (listen) —p (port) switches. (The —v switch is not required and simply provides more verbose output, as shown below in Figure 9.18.)


2 Answers

Checkout the -e option, you could write a script that does the processing and then execute

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

which would pipe stdin and stdout back and forth from nc to the script like you want.

exec.bat could be something like (somewhat pseudo code):

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

or maybe a loop (also somewhat pseudo code):

: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)
like image 60
cure Avatar answered Oct 25 '22 19:10

cure


The problem is, as far as I can tell, nc can't perform a callback to tailor its output based on client input. Once you have...

stdout generation | nc -l

... blocking and waiting for a connection, its output is already determined. That output is static at that point.

The only workaround which occurs to me is rather inefficient. It basically involves the following logic:

  1. Listen for a connection prepared to make the client perform a reload
  2. Scrape the GET address from the previous request's headers.
  3. Serve relevant content on client's second connection

Example code:

@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
)

As a side note, delayed expansion can mutilate variable values set with exclamation marks if it's enabled at the time of setting. Best to wait to enable delayed expansion until retrieval.

Also, when performing a boolean check on %ERRORLEVEL% it's more graceful to employ conditional execution. But that has nothing to do with my solution. :)

And finally, instead of doing type filename.html | nc -l, consider using <filename.html nc -l (or nc -l <filename.html) to avoid the useless use of type.

like image 34
rojo Avatar answered Oct 25 '22 20:10

rojo