Web地址路由在http.ListenAndServe上工作正常,但在cgi.Serve()上失败

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