在Go + FastCGI中,使用多个处理程序是否有意义?

时间:2017-09-12 09:07:35

标签: go fastcgi

Gopher新手在这里。请善待: - )

我有一个设置,我在共享服务器上有一个帐户,运行Apache + FastCGI,我无法控制。但它可以顺畅地与Go接口。我比较习惯将Go与net/http一起使用,但弄清楚如何将其与net/http/fcgi一起使用似乎很简单。这是我的最小测试应用程序:

package main

import (
    "fmt"
    "net/http"
    "net/http/fcgi"
)

func handler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Header().Set("Content-type", "text/plain; charset=utf-8")
    fmt.Fprintln(w, "This was generated by Go running as a FastCGI app")
}

func main() {
    /*
     *  
     *  Everything that is done here should be setup code etc. which is retained between calls
     *  
     */
    http.HandleFunc("/", handler)
    // This is what actually concurrently handles requests
    if err := fcgi.Serve(nil, nil); err != nil {
            panic(err)
    }
}

现在这种方法运行得非常漂亮和完美:在将其编译为go-fcgi-test.fcgi并将其置于相应目录下之后,Go代码将从http://my.shared.web.server/go-fcgi-test.fcgi这样的URL运行。为了简单起见,我已经将大部分实际处理完成了 - 但这完全适用于提取表单参数,ENV变量(在Go 1.9下)等等,所以我知道基本设置必须正常

让我们尝试一个稍微复杂的例子:

package main

import (
    "fmt"
    "net/http"
    "net/http/fcgi"
)

func handler1(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Header().Set("Content-type", "text/plain; charset=utf-8")
    fmt.Fprintln(w, "This comes from handler1")
}

func handler2(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Header().Set("Content-type", "text/plain; charset=utf-8")
    fmt.Fprintln(w, "This comes from handler2")
}

func main() {
    http.HandleFunc("/first", handler1)
    http.HandleFunc("/", handler2)
    if err := fcgi.Serve(nil, nil); err != nil {
            panic(err)
    }
}

现在,在这种情况下,我希望http://my.shared.web.server/go-fcgi-test.fcgi能够输出This comes from handler2,而且确实会发生这种情况。

但为什么http://my.shared.web.server/go-fcgi-test.fcgi/first实际上也会调用handler2,即handler1完全被忽略?请注意,handler2 获取网址的/first位 - Apache 将其删除 - 因为我可以阅读r.URL.Path[1:]并确认这是发送到Go应用程序的整个路径。

我在Web上使用类似的FastCGI骨架找到的所有示例仅显示一个处理程序。这是FastCGI包本身的限制吗? FastCGI协议的限制(但为什么整个路径正确发送?)?在Apache配置中完成了一些限制(请记住,我无法触及Apache配置)?或者我做了一件非常糟糕的事情?

(为了完整起见,我应该补充一点,是的,我已经尝试了上述的几种变体,重命名Go应用程序,使用子文件夹,使用几个处理程序而不仅仅是一个,等等等等)

我的真实场景实际上是一个小型应用程序,应该作为独立的Web服务器运行,使用net/http 作为FastCGI应用程序,如果单独模型要么不受支持,要么甚至被禁止(某些共享环境提供者就是这种情况)。由于两种情况下的实际处理完全相同,唯一的区别是调用fcgi.Serve()而不是http.ListenAndServe()。但是,能够在FastCGI下使用不同处理程序的net/http包的路由功能也很好。

提前感谢任何见解。即使答案是肯定的,那就是完全 FastCGI实现如何在Go - 仅一个处理程序下工作!'这仍然是有用的 - 这意味着我只需要处理我自己的代码并以不同的方式做事(基本上,根据通过Form接口传递的参数创建我自己的路由器/调度程序 - 没什么大不了的,它是可行的! )

2 个答案:

答案 0 :(得分:1)

我意识到这是一篇过时的文章,但是我才刚刚开始与Go和fcgi一起玩,并且遇到了同样的问题。

简短的回答是,使用多个处理程序确实很有意义。您的示例中的缺陷是您没有考虑go-fcgi-test.fcgi是URL的一部分。

当Go的ServeMux处理URL时,它将使用请求的完整URL,而不仅仅是fcgi进程正在处理的部分。对于http://my.shared.web.server/go-fcgi-test.fcgi/first,程序将寻找与/go-fcgi-test.fcgi/first最接近的匹配项,即/

答案 1 :(得分:0)

在阅读@Kodiak提供的答案后,我重新阅读了documentation for ServeMux并看到了这一段:

  

请注意,由于以斜杠结尾的模式会命名一个有根的子树,因此模式“ /”会匹配其他注册模式不匹配的所有路径,而不仅仅是具有Path ==“ /”的URL。

     

如果已经注册了一个子树,并且收到了一个命名该子树根且没有其后斜杠的请求,则ServeMux将该请求重定向到该子树根(添加后斜杠)。可以用单独的路径注册来覆盖此行为,而不必使用斜杠。例如,注册“ / images /”会使ServeMux将对“ / images”的请求重定向到“ / images /”,除非已单独注册“ / images”。

(斜体字)

我的假设 ServeMux表现得很像nginx和/或Apache的rewrite模块(即i)的基于规则的模式匹配功能。 e。规则是根据注册顺序进行处理的,因此我期望/first将首先被匹配(双关语意),并且只有在未找到匹配项的情况下,/才会被匹配下一个

但这不是文档所说的。相反,注册顺序并没有真正的区别。 ServeMux在我给定的情况下,因为我忘了加一个斜杠,所以会{em>总是退回到"/"的处理程序中,而不是因为某些错误或匹配算法,但是因为这是Go开发人员编码的预期行为!换句话说,如果您有"/"的处理程序,则该处理程序将充当所有未以斜杠结尾的子树的全部。

我只是无法正确阅读文档! (或者早在2017年,该段落还不够清晰)