Go Web App:如何从Golang将PHP脚本路由到PHP-FPM

I have one main web site and numerous small web sites. I'm currently using Nginx & PHP for all of this. My plan is to do away with both and build a single web app in Go that will serve everything, which will hopefully reduce load and memory (especially since some of the pages are very computationally heavy.)

My issue is that it would be a serious waste of time for me to try to port things like rarely used PHPBB forums to Go. So I'd like to have the main web site all served from the Go web app, but some of the other sites can remain as PHP.

My question is: can I use the Go web app to route requests for PHP scripts to PHP-FPM?

I would like it so that I can do away with Nginx, the web app will handle all of the incoming traffic and serve the main site directly from its own code, but for less important sites that are still in PHP these can be served by the Go app routing these requests to PHP-FPM (along with all the full request info including cookies, POST vars, etc.)

Any ideas?

To redirect to another url you can use httputil.HostReverseProxy

    origin := "http://php.website.com"
    originUrl, err := url.Parse(origin)
    if err != nil {
        log.Fatal(err)
    }

    proxy := httputil.NewSingleHostReverseProxy(originUrl)
    prev := proxy.Director

    proxy.Director = func(req *http.Request) {
        prev(req)
        req.Host = originUrl.Host
    }

    http.HandleFunc("/php", proxy.ServeHTTP)

PHP-FPM is listening on an unix socket. So you can simply connect to its unix socket using the net.Dial method:

conn, err:= net.Dial("unix","", "/path/to/php-fpm.sock")

then write what you need on the resulting connection. You may use the net.Pipe method, which will require use the net package for connection handling (or hijacking those of a more classic http server).

That said, I would however advice against handling this with go: nginx is highly efficient, fast, has a low memory usage, and will do this job far better than you. What you should do (IMHO) is to port each application you want to go, then use nginx as a reverse proxy. If you're after performance, you can use unix socket for communication between nginx and apps, as it will be faster than listening on a TCP port.

I realize this is an ancient post, but here's my answer since I've had to research this for myself after running into essentially the same issue.

TL;DR I suggest proxying to Nginx via HTTP and letting it talk to PHP-FPM - not because Nginx is better or faster or shinier or whatever, but because this code path is orders of magnitude more well tested and maintained and the disadvantages are minimal.

Two obvious approaches:

A) Use Nginx and proxy request through go to PHP. This can be done with httputil as described in @fabrizioM's answer, and is essentially proxying the request via HTTP to Nginx which then converts it to FastCGI and calls PHP-FPM.

B) Use an implementation of the FastCGI protocol to call to PHP-FPM directly from Go. I haven't tried this, but there are a number of Go libraries out there which purport to do this, including:

n.b. I realize some of these probably didn't exist with the question was asked.

The first one above has 21 stars as of this writing.

IMO, while Nginx is a great webserver, there is little to gain from it over serving static files in Go. However, there is one big thing you gain by using Nginx here and it is the stability and maintenance of that FastCGI code. Clearly calling via FastCGI in Go is not an extremely popular approach, and I don't know how much I trust the implementation. On the other hand, there are bazillions of PHP devs out there who swear by Nginx+PHP-FPM and it is well tested and maintained.

There are some other nice perks when using HTTP for proxying, e.g. it's more likely to work correctly when you, during local development, forward requests from your Go process over the Internet to wherever your PHP server is. This makes it easy to hack away on your Go app without having to run a local copy of all of the PHP stuff and yet still be able to see everything functional.

So while both approaches are viable, my suggestion is to include Nginx solely because it is a much better supported code path that your requests flow through, has some practical local dev advantages and the performance loss is negligible. I think those are much stronger arguments than the "Nginx is great at serving static files" or "has low memory usage", etc. arguments.