doumindang2416 2017-09-20 18:39
浏览 47
已采纳

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)
    }
}
  • 写回答

1条回答 默认 最新

  • dshgnt2008 2017-09-21 02:24
    关注

    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
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 目详情-五一模拟赛详情页
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line