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
+11k Golang : Get UDP client IP address and differentiate clients by port number
+16.5k Golang : Find out mime type from bytes in buffer
+7.4k Golang : How to iterate a slice without using for loop?
+4.9k Which content-type(MIME type) to use for JSON data
+15.9k Golang : Intercept Ctrl-C interrupt or kill signal and determine the signal type
+9.1k Golang : Build and compile multiple source files
+7.2k Golang : Transform lisp or spinal case to Pascal case example
+11.1k Golang : Create S3 bucket with official aws-sdk-go package
+6.3k Golang : Extract XML attribute data with attr field tag example
+8.7k Golang : Another camera capture GUI application with GTK and OpenCV
+5k Unix/Linux : secure copying between servers with SCP command examples
+23.6k Golang : Check if element exist in map