This repository stores documentation of CGI and FastCGI interfaces and programming tools which may be useful for building applications using the FastCGI interface in Go programming language, a.k.a. Golang.
These tools include a library written in Go language. This library provides objects, methods and functions to work with FastCGI interface in Go programming language.
The library implements methods for a FastCGI client, mostly.
Implementation of a FastCGI server can be found in a built-in standard
library of Go language – net/http/fcgi
package,
https://pkg.go.dev/net/http/fcgi.
The library provides a simple experimental web server to use with legacy scripts supporting the CGI and FastCGI interfaces. This server should not be used anywhere except some experiments with PHP scripts because it has several issues which are described further in the Résumé section.
N.B. Due to some bugs in Go language, the structure of this repository is
heavily modified to meet the requirements of the Google's Golang proxy server
which often throws funny messages. The most funny of them are messages stating
that a package was downloaded but not found. If you are used to a strict
repository layout which separates source code into an src
folder and other
stuff – into other folders, this structure is forbidden by Google's Golang.
So, knowing all the above, the structure of this repository is as follows:
- 'doc' folder contains the documentation.
- Other folders contain various parts of the library for Go language.
Usage examples can be found in the 'example' folder.
The most simple usage example requires only a few lines of code and is as simple as the following code:
package main
import (
"fmt"
"os"
"github.com/vault-thirteen/Fast-CGI/pkg/models/php"
)
func main() {
var err error
err = runSimplePhpScript(`D:\Scripts\script.php`)
if err != nil {
panic(err)
}
}
func runSimplePhpScript(scriptFilePath string) (err error) {
var stdOut, stdErr []byte
stdOut, stdErr, err = pm.RunOnceSimplePhpScript("tcp", "127.0.0.1:9000", scriptFilePath)
if err != nil {
return err
}
if len(stdErr) > 0 {
_, err = fmt.Fprintln(os.Stderr, string(stdErr))
if err != nil {
return err
}
}
if len(stdOut) > 0 {
_, err = fmt.Fprintln(os.Stdout, string(stdOut))
if err != nil {
return err
}
}
return nil
}
For more complex tasks, the Client
object and its methods can be used.
Reason 1
FastCGI interface provides a cross-platform and cross-language interface for communication between totally different programming languages. For example, with the help of FastCGI it is possible to call a function of a PHP language from the code written in Go language, where Go is a compiled language and PHP is an interpreted language with no runtime "engine".
Reason 2
FastCGI interface is still actual for simple tasks and applications where client code is not a bottleneck, e.g. for applications using a lot of complicated SQL queries, such as bulletin boards and online forums.
Reason 3
There are a lot of programming languages which still support the FastCGI interface. And many of these languages are mature and are sufficient for their purposes.
Reason 4
This library makes it possible to bring a new life into old projects written in other programming languages that support the FastCGI interface. It is not necessary to re-write PHP projects in Go from scratch. This is why it is said in this repository, that this project is a compatibility layer.
-
The FastCGI interface itself is not so bad even with all its drawbacks.
- It uses 16-bit fields for data transmission making it practically useless for HTTP bodies being longer than 65535 bytes, but it does its job when you need to connect totally different systems together. The main problem lies much deeper than FastCGI.
-
The main problem is the CGI interface which is even older than FastCGI interface and has several serious issues.
-
First of all, CGI was made for UNIX operating systems. It was using so-called UNIX sockets to make it work faster than a turtle. Other operating systems, such as Microsoft Windows, do not have UNIX sockets and use TCP network protocol for inter-process communication. This approach itself decreases the already slow protocol and makes it even slower.
-
CGI on UNIX uses forward slash symbols in all paths – in URL and in paths inside an operating system. This creates difficulties for non-UNIX operating systems.
-
The
Extra Path
feature of the CGI interface is very dumb and dangerous at the same time. Yes, this is D&D, but it is not about dragons this time. First of all, it breaks URL parsing completely, because there is no way to distinguish files and folders by only looking at their names. So, the URLhttp://some.machine/cgi-bin/display.pl/cgi/cgi_doc.txt
in real life may be a Perl scriptdisplay.pl
with a CGI "extra path", or it may be a text filecgi_doc.txt
sitting inside a folder with dot symbol in its name. This "feature" makes CGI unusable in real-world applications because it forces owners of web servers to invent stupid mechanisms for guessing the real meaning of a URL. All this situation introduces at least two consequences: poor performance of a web server and a huge hole in the security of an entire system. ThisExtra Path
feature should be disabled all the time except those corner cases when you really need it to experiment with some legacy code. -
Another problem of the
Extra Path
CGI feature is that it breaks directory levels and spoils the page hierarchy. So, for example, when you try to install the ancient phpBB3 forum and open following URL – http://localhost:8000/phpBB3/install/app.php/support – the PHP script acts as it should, thinking that the document is located at the level ofinstall
folder, but all the modern web browsers see this URL as ansupport
file sitting in theapp.php
folder, which is one level above theinstall
folder. Together with another ancient habit to use relative links, this makes all the relations between pages, files and scripts – a total nonsense. Relative links stop working, CSS styles stop being used, JavaScript dies and so on. The page breaks apart into sand and dust ... -
The above stated bug with page levels can be mitigated using HTTP redirects. The example web server tries to use 307 and 302 status redirects for requests having HTTP body and those without it. But it looks like this redirect can break some sensitive scripts which do not allow redirects for some reason.
-
-
Experiment with phpBB 3 forum installation has shown that the installer has bugs. For example, the same page is linked with and without a trailing slash, which is a violation of common sense and is critical for parsing the CGI extra paths. Another bug is that the installer starts looping the
/installer/status
request infinitely at 15% of the installation progress. R.i.P., phpBB.
If you have any feedback, you are free to direct it to this GitHub repository: