【问题标题】:Web address routing works fine with http.ListenAndServe, but fails with cgi.Serve()Web 地址路由在 http.ListenAndServe 中运行良好,但在 cgi.Serve() 中失败
【发布时间】:2017-09-22 04:43:23
【问题描述】:

我正在使用 Go 开发一个网站。服务器限制要求我使用 CGI。当我使用 http.ListenAndServe() (在下面注释掉)在本地测试以下代码时,会根据请求的地址正确调用各种处理程序。但是,如果我改用 cgi.Serve(),则会为所有地址执行默认路由器(即,始终执行“/”的处理程序)。如有任何有关如何解决此问题的线索,我将不胜感激。

编辑:这是我能想到的最简单的测试用例来显示问题:

//=============简化代码================//

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)
    }
}

//=============来自原始帖子的代码===================//

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)
    }
}

【问题讨论】:

  • 你试过去掉cas客户端中间件的使用吗?也许首先尝试使用最简单的处理程序,而不需要 client.HandleFunc 或任何 cas.xxx 调用。您可能会发现 cas 正在重定向到 /。
  • 是的。我将编辑帖子以添加我能想到的最简单的测试用例。

标签: go routing


【解决方案1】:

CGI 程序需要设置一些变量来构建请求。

您的网络服务器的配置可能存在一些问题,其中变量设置不正确或命名不正确。

要验证这一点:

1) 在调用 cgi.Serve 之前添加它,您将看到如何调用正确的处理程序 (otherHandler)

os.Setenv("REQUEST_METHOD", "get")
os.Setenv("SERVER_PROTOCOL", "HTTP/1.1")
os.Setenv("SCRIPT_NAME", "/other")

2) 在main 的开头添加此代码,以检查 Web 服务器如何设置变量:

fmt.Println(os.Environ())

在该输出中,查找规范中定义的 CGI 元变量:

http://www.ietf.org/rfc/rfc3875

在该页面中查找“请求元变量”部分,您可能正在寻找 SCRIPT_NAMEPATH_INFO 变量。

编辑

从您在下面粘贴的变量值来看,问题似乎在于 REQUEST_URI 包含一个额外的路径组件:

REQUEST_URI=/main.cgi/other

因此,最简单的解决方法是让您相应地映射路线:

http.HandleFunc("/main.cgi/other", otherHandler)
http.HandleFunc("/", defaultHandler)  // or maybe /main.cgi

【讨论】:

  • 感谢您的帮助。我不太确定我在这里做什么,但这是一次尝试的打印输出:REQUEST_SCHEME=http CONTEXT_PREFIX= CONTEXT_DOCUMENT_ROOT=/home/user1/public_html SERVER_ADMIN=webmaster@user1.mycpanel.sample.com SCRIPT_FILENAME=/home/ user1/public_html/main.cgi REMOTE_PORT=45516 GATEWAY_INTERFACE=CGI/1.1 SERVER_PROTOCOL=HTTP/1.1 REQUEST_METHOD=get QUERY_STRING= REQUEST_URI=/main.cgi/other SCRIPT_NAME=/other PATH_INFO=/other PATH_TRANSLATED=/home/user1/public_html/其他
  • 看看 Go 如何基于这些变量构建请求:golang.org/src/net/http/cgi/child.go?#L94
  • @Brent:根据您粘贴的内容查看我在答案中的编辑
猜你喜欢
  • 2013-02-12
  • 2013-04-09
  • 2011-07-27
  • 2012-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-25
  • 2011-10-27
相关资源
最近更新 更多