I'm working on a website using Go. The server constraints require that I use CGI. When I test the following code locally using http.ListenAndServe() (commented out below), the various handlers are called correctly depending on the address requested. However, if I use cgi.Serve() instead, the default router is executed for all addresses (i.e., the handler for "/" is always executed). I'd appreciate any clues as to how to fix the issue.
EDIT: Here is the simplest test case I can think of to show the problem:
//=============SIMPLIFIED CODE================//
package main
import (
"fmt"
"net/http"
"net/http/cgi"
)
func defaultHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Default")
}
func otherHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Other")
}
func main() {
http.HandleFunc("/other", otherHandler)
http.HandleFunc("/", defaultHandler)
/*
//Works fine
err := http.ListenAndServe(":8090", nil)
if err != nil {
panic(err)
}
*/
//Always fires defaultHandler no matter the address requested
err := cgi.Serve(nil)
if err != nil {
panic(err)
}
}
//=============CODE FROM ORIGINAL POST===================//
package main
import (
"fmt"
"net/http"
"net/http/cgi"
"net/url"
"os"
"github.com/go-cas/cas"
)
func logoutHandler(w http.ResponseWriter, r *http.Request) {
cas.RedirectToLogout(w, r)
}
func calendarHandler(w http.ResponseWriter, r *http.Request) {
if !cas.IsAuthenticated(r) {
cas.RedirectToLogin(w, r)
}
fmt.Fprintf(w, "Calendar for %s", cas.Username(r))
}
func defaultHandler(w http.ResponseWriter, r *http.Request) {
if !cas.IsAuthenticated(r) {
cas.RedirectToLogin(w, r)
}
fmt.Fprintf(w, "Hi there %s!", cas.Username(r))
}
func main() {
u, _ := url.Parse("https://www.examplecasserver.com")
client := cas.NewClient(&cas.Options{
URL: u,
})
http.Handle("/logout", client.HandleFunc(logoutHandler))
http.Handle("/calendar", client.HandleFunc(calendarHandler))
http.Handle("/", client.HandleFunc(defaultHandler))
/*
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
*/
err := cgi.Serve(nil)
if err != nil {
panic(err)
}
}
The CGI program expects some variables to be set in order to build the request.
Probably there is some issue with the configuration of your web server in which the variables are either not set correctly or not named correctly.
To verify this:
1) Add this before calling cgi.Serve
and you'll see how the right handler is called (otherHandler
)
os.Setenv("REQUEST_METHOD", "get")
os.Setenv("SERVER_PROTOCOL", "HTTP/1.1")
os.Setenv("SCRIPT_NAME", "/other")
2) Add this at the beginning of the main
to check how the variables are being set by the web server:
fmt.Println(os.Environ())
In that output, look for the CGI meta variables defined in the spec:
http://www.ietf.org/rfc/rfc3875
Look for the section "Request Meta-Variables" in that page, you are probably looking for the SCRIPT_NAME
or PATH_INFO
variables.
EDIT
From the variable values you pasted below, it seems the issue is that the REQUEST_URI contains an additional path component:
REQUEST_URI=/main.cgi/other
So the easiest fix would be for you to map the routes accordingly:
http.HandleFunc("/main.cgi/other", otherHandler)
http.HandleFunc("/", defaultHandler) // or maybe /main.cgi