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接口传递的参数创建我自己的路由器/调度程序 - 没什么大不了的,它是可行的! )
答案 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年,该段落还不够清晰)