golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.71k stars 17.5k forks source link

net/http/cgi: support Python etc non-executable scripts on Windows #18420

Open zhw2101024 opened 7 years ago

zhw2101024 commented 7 years ago

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

1.7.4

What operating system and processor architecture are you using (go env)?

set GOARCH=amd64 set GOBIN= set GOEXE=.exe set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOOS=windows set GOPATH= set GORACE= set GOROOT=D:\Go set GOTOOLDIR=D:\Go\pkg\tool\windows_amd64 set CC=gcc set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 set CXX=g++ set CGO_ENABLED=1

What did you do?

If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on play.golang.org is best.

cgidemo.zip Change to unziped directory, and execute go run cgi.go, then visit http://localhost:8000/cgi-bin/test.py

What did you expect to see?

Hello on my browser

What did you see instead?

The page hangs up

robothor commented 7 years ago

This works for me if I make sure test.py is executable:

#!/usr/bin/env python

print("Content-Type: text/html\n")
print("Hello")

Also, there were some strange whitespace characters in the file that were causing problems.

Note that I am running on darwin and am not really sure how to fix this on Windows.

minux commented 7 years ago

You need to somehow make the program test.py runnable on Windows.

On Unix, you can add a shebang header and make the script executable. I don't know how to achieve that on windows.

I don't think this is a Go bug. Please ask questions on other mediums, see https://golang.org/wiki/Questions

bradfitz commented 7 years ago

@minux, but "runnable" on a file is a concept that doesn't exist on Windows.

We should do whatever other popular CGI servers do. (Whatever that is.) Shebang support, perhaps?

minux commented 7 years ago

On windows, it's likely based on file suffix alone. @alexbrainmain.

One simple solution is perhaps using "cmd /c start script.py arguments...", but I don't know the implications.

mattn commented 7 years ago

For Windows, you should handle extension whether it will be runnable.

https://github.com/mattn/go-cgiserver/blob/master/cgiserver.go

BTW: s/alexbrainmain/alexbrainman/

zhw2101024 commented 7 years ago

There's a WINAPI called ShellExecute, equals to cmd /c script.py, but have no idea if it's applicable to use this here. Maybe will link to windows dll file. cmd should work, as all supported windows versions have cmd and cmd's behavior seems won't change.

zhw2101024 commented 7 years ago

@bradfitz Thanks for reopening this issue. Please allow me to clarify this issue with more details. currently golang's cgi only supports .com, .exe, .bat and .cmd files. If one want to use golang's cgi on windows, there's only two choices: one of compiling languages, or bat script. compiling languages have many advantages, but not so handy as script languages such as perl, one of most popular cgi backend languages. On the other hand, bat lack too many modern features, so it's difficult to implement a complete service with just bat. So if cgi support script languages, it will be far more useful than before.

minux commented 7 years ago

You just need to use a special shebang line for Python scripts on Windows (and also save the script with suffix .bat):

@"c:\python27\python.exe" -x %~f0 & exit /b

I think this is also possible for Perl (it's probably easier for Perl, because perl's syntax is not as strict as Python's, and I have to resort to use -x to write a Python/bat polyglot.)

While Windows batch files are quite limiting compared to Unix shell scripts, this is still possible.

zhw2101024 commented 7 years ago

Thank you, This works for me at least. @minux But comparing with Python's cgi module or Apache's cgi module, this still have problems. Imaging you have tones of python script use as cgi backend, and use apache's cgi module. One day you want to use golang's cgi, then you need to modify all existing scripts. A new batch file may do this work for you, but python scripts with bat suffix may terribly misleading your IDE or code editor, or other maintainers.

minux commented 7 years ago

You need to name the python script with .bat suffix to persuade the system to execute it.

It's fundamentally a Python script embedded within a Batch script.

zhw2101024 commented 7 years ago

code editor will not be useful for these script files, as many functions will not work, such as highlighting, autocompletion, etc.

rskumar commented 7 years ago

MS Windows has different approach than *nix systems for FileType and Application association. There can be multiple associations, and association can have multiple options (first in list being default). And verbs are like Open, Edit, Print etc... So probably you have to call windows ShellExecute (Ex) for default or open verb action. Read here - https://msdn.microsoft.com/en-us/library/windows/desktop/cc144148(v=vs.85).aspx

Or, we can query windows registry just once for every extensions to find registered launcher for the script, and cache it. But if intelligent approach to auto-execute does not seems to be working, why don't we choose explicit approach? Like, if shebang specified with windows program path, and if available, use it or print sensible error on console for developer. And, also let developer specify a database of executable and their association to file types in program, which can be plugged to cgi handler, and then it will override shebang if that is also available and valid.

Apache HTTPD perhaps looks into cgi file shebang for per/python.

alexbrainman commented 7 years ago

I agree we should use what windows shell already knows - see assoc and ftype windows commands. We could then use ShellExecute, or do it ourselves with AssocQueryString and CreateProcess.

Alex

mattn commented 7 years ago

I guess AssocQueryString make unexpected behavior when the file is .docx or something which is not expected as CGI.

alexbrainman commented 7 years ago

unexpected behavior when the file is .docx

What does CGI do on unix when file is .docx? Or .html or whatever?

Alex

mattn commented 7 years ago

What does CGI do on unix when file is .docx? Or .html or whatever?

Windows doesn't have executable-permission as same as UNIX's one. So we have to handle the file-suffix which can runnable with white-list. If it use AssocQueryString without white-list, the server may start Microsoft Word for the .docx.

bradfitz commented 7 years ago

Could we just check the PE file's Console-vs-GUI type and not execute *.exe files if they're GUI exes?

alexbrainman commented 7 years ago

Could we just check the PE file's Console-vs-GUI type and not execute *.exe files if they're GUI exes?

Yes we could do that.

Alex

withrocks commented 7 years ago

I would suggest (at least as a workaround) to create a bat script test.bat that acts as a proxy/entry for the script test.py:

@echo off
python.exe test.py

These proxy scripts can then be generated automatically for all scripts that should be made available via the CGI.

I believe this is a rather common alternative to shebang on Windows.

mattn commented 7 years ago

I believe this is a rather common alternative to shebang on Windows.

I think so. Over hack can be a trouble afterwards.