Nginx + FastCGI + Go Setup.
UPDATE : Previous code example no longer work since Golang version 1.5. Updated the code example below to work with the latest version
In most examples of Go that I came across that deal with net/http
package, accessing the Go program is usually done via http://localhost:8080/
This is useful if you want to use Go web server on a port.
However, there are times you need a front web server to handle incoming requests and proxy the requests to multiple Go processes.
In this tutorial, we will learn how to connect a Go process via FastCGI and Nginx web server. This tutorial assumes that you already know how to setup Nginx and FastCGI.
In the Nginx server block, you need to configure FastCGI to listen to certain port. For example :
location ~ /go.* {
include fastcgi.conf;
fastcgi_pass 127.0.0.1:9001;
}
NOTE : Make sure to include this FastCGI block in HTTPS part of the nginx.conf file if your web server redirects all traffic to HTTPS
We will try to achieve the following :
Print out a "Hello World!" string via the localhost:8080 way
Change the Go program to output via FastCGI.
Ok, let's get started with the "traditional" way
File : nginx_fastcgi.go
package main
import (
"net/http"
)
func HelloHandler(w http.ResponseWriter, r *http.Request) {
html := "Hello"
html = html + " World"
w.Write([]byte(html))
}
func main() {
http.HandleFunc("/", HelloHandler)
http.ListenAndServe(":8080", nil)
}
Pointing the browser to http://example.com:8080/nginx_fastgci will give us "Hello World!" output.
Now, change the above codes to :
package main
import (
"github.com/gorilla/mux"
"log"
"net"
"net/http"
"net/http/fcgi"
)
type customHandler struct {
cmux http.Handler
}
// must have at least ServeHTTP(), otherwise you will get this error
// *customHandler does not implement http.Handler (missing ServeHTTP method)
func (c *customHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
html := "Hello"
html = html + " World"
w.Write([]byte(html))
}
func main() {
mux := mux.NewRouter()
// bind cmux to mx(route)
fcgiHandler := &customHandler{cmux: mux}
mux.Path("/").Handler(fcgiHandler)
listener, _ := net.Listen("tcp", "127.0.0.1:9001") // bind to port 9001 because of - fastcgi_pass 127.0.0.1:9001; in nginx.conf file
err := fcgi.Serve(listener, fcgiHandler)
if err != nil {
log.Fatal(err)
}
}
NOTE : The above code is adapted from previous tutorial on how to create custom handler with Gorilla framework
Test out by running > go run nginx_fastcgi.go
and point your browser to http://example.com/go
you should see the output as the same, but this time without the :8080
port.
Why go
at the end of the URL ? Err.... because it is configured in the Nginx server block.
location ~ /go.* {
include fastcgi.conf;
fastcgi_pass 127.0.0.1:9001;
}
To wrap this up, what we did here is to tell nginx_fastcgi.go to listen to new requests pass down via FastCGI and serve the simple Hello World HTML.
Happy coding!
References:
https://www.socketloop.com/tutorials/golang-example-of-custom-handler-for-gorilla-s-path-usage
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+17.3k Golang : delete and modify XML file content
+14.8k Golang : How do I get the local IP (non-loopback) address ?
+31.9k Golang : Convert []string to []byte examples
+9.8k Golang : Test a slice of integers for odd and even numbers
+16.9k Golang : How to tell if a file is compressed either gzip or zip ?
+19.6k Golang : How to run your code only once with sync.Once object
+22.1k Golang : How to read JPG(JPEG), GIF and PNG files ?
+13.3k Golang : Strings comparison
+10.9k Golang : Calculate Relative Strength Index(RSI) example
+9.2k Mac OSX : Get a process/daemon status information
+10.9k Golang : How to determine a prime number?
+12.7k Python : Convert IPv6 address to decimal and back to IPv6