jjzjj

go - Web 地址路由在 http.ListenAndServe 上运行良好,但在 cgi.Serve() 上运行失败

coder 2024-07-07 原文

我正在使用 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)
    }
}

最佳答案

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

关于go - Web 地址路由在 http.ListenAndServe 上运行良好,但在 cgi.Serve() 上运行失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46329506/

有关go - Web 地址路由在 http.ListenAndServe 上运行良好,但在 cgi.Serve() 上运行失败的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  3. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  4. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  5. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  6. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  7. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  8. ruby-on-rails - 无法让 rspec、spork 和调试器正常运行 - 2

    GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'

  9. ruby-on-rails - before_filter 运行多个方法 - 2

    是否有可能:before_filter:authenticate_user!||:authenticate_admin! 最佳答案 before_filter:do_authenticationdefdo_authenticationauthenticate_user!||authenticate_admin!end 关于ruby-on-rails-before_filter运行多个方法,我们在StackOverflow上找到一个类似的问题: https://

  10. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

随机推荐