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 数学建模求思路及代码
  • ¥50 silvaco GaN HEMT有栅极场板的击穿电压仿真问题
  • ¥15 谁会P4语言啊,我想请教一下
  • ¥15 哪个tomcat中startup一直一闪而过 找不出问题
  • ¥15 这个怎么改成直流激励源给加热电阻提供5a电流呀
  • ¥50 求解vmware的网络模式问题 别拿AI回答
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码