【发布时间】:2017-09-12 09:07:34
【问题描述】:
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 确实获得了 URL 的 /first 位——Apache 没有将其剥离——因为我可以读取 r.URL.Path[1:] 并确认这是发送到 Go 应用程序的整个路径。
我在网上找到的所有使用类似框架的 FastCGI 示例都只显示 一个 处理程序。这是 FastCGI 包本身的限制吗? FastCGI 协议的限制(但为什么正确发送整个路径?)?在 Apache 配置中做了什么强加了这个限制(记住,我不能触及 Apache 配置)?还是我做错了什么?
(为了完整起见,我应该补充一点,是的,我已经尝试了上面的几种变体,重命名 Go 应用程序,使用子文件夹,使用 几个 处理程序,而不仅仅是一个,等等.等等)
我的真实世界场景实际上是一个小型应用程序,它应该作为一个使用 net/http 的独立 Web 服务器运行或在独立模型的情况下作为 FastCGI 应用程序运行要么不支持,要么甚至被禁止(某些共享环境的提供者就是这种情况)。由于这两种情况的实际处理完全相同,唯一的区别是调用fcgi.Serve() 而不是http.ListenAndServe()。但是如果能在 FastCGI 下使用 net/http 包的路由能力和不同的处理程序,那就太好了。
提前感谢您提供任何见解。即使答案是“是的,这正是在 Go 下 FastCGI 实现是如何工作的——只有一个处理程序!”这仍然很有用——这意味着我只需要处理我自己的代码并以不同的方式做事(基本上,根据通过 Form 接口传递的参数创建我自己的路由器/调度程序——没什么大不了的,这是可行的!)
【问题讨论】:
-
fcgi 只是提供 HTTP 服务器部分;处理程序及其注册由多路复用器提供,在这种情况下是标准的
net/httpServeMux。它的行为不应该有任何不同,而且我不确定这两个处理程序是如何被调用的——它们都写入标头,所以由于标头已经发送,应该会感到恐慌。 -
您确定对
handler2的调用是针对/first而不是针对favicon.ico?handler2,由于它的映射,将处理除/first之外的所有请求,所以我不会惊讶地看到它在同一页面视图上获得浏览器生成的辅助请求。