Go 在围棋中+;FastCGI,使用多个处理程序有意义吗?
这里是地鼠新手。请善待:-) 我有一个设置,我在一个共享服务器上有一个帐户,该服务器运行Apache+FastCGI,我对此没有控制权。不过,它与Go的接口很平滑。我更习惯于在Go 在围棋中+;FastCGI,使用多个处理程序有意义吗?,go,fastcgi,Go,Fastcgi,这里是地鼠新手。请善待:-) 我有一个设置,我在一个共享服务器上有一个帐户,该服务器运行Apache+FastCGI,我对此没有控制权。不过,它与Go的接口很平滑。我更习惯于在net/http中使用Go,但弄清楚如何在net/http/fcgi中使用它似乎很简单。以下是我的最小测试应用程序: package main import ( "fmt" "net/http" "net/http/fcgi" ) func handler(w http.ResponseWrit
net/http
中使用Go,但弄清楚如何在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
。为了简单起见,我省略了大部分实际处理过程——但这对于提取表单参数、环境变量(在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
到输出这来自handler2
,事实上,这正是发生的情况
但是为什么http://my.shared.web.server/go-fcgi-test.fcgi/first
实际调用handler2
,即handler1
被完全忽略?请注意,handler2
确实获得了URL的/first
位—Apache没有将其剥离—因为我可以读取r.URL.Path[1://code>,并确认这是发送到Go应用程序的整个路径
我在Web上找到的所有使用类似FastCGI框架的示例都只显示了一个处理程序。这是FastCGI包本身的限制吗?FastCGI协议的一个限制(但是为什么正确发送整个路径?)?在Apache配置中执行的某些操作施加了此限制(请记住,我无法接触Apache配置)?还是我做错了什么
(为了完整起见,我应该补充一点,是的,我已经尝试了上面的几种变体,重命名Go应用程序,使用子文件夹,使用多个处理程序,而不仅仅是一个,等等)
我的现实世界场景实际上是一个小应用程序,它可以作为使用net/http
的独立web服务器运行,也可以作为FastCGI应用程序运行,以防独立模型不受支持甚至被禁止(这是一些共享环境提供商的情况)。由于这两种情况的实际处理方式完全相同,唯一的区别是调用fcgi.service()
,而不是http.listenandservice()
。但是,如果能够在FastCGI下使用net/http
包的路由功能和不同的处理程序,那就太好了
提前感谢您提供的任何见解。即使答案是“是的,这正是FastCGI实现在Go-one处理程序下工作的方式!”这仍然是有用的-这意味着我只需要围绕自己的代码工作,并以不同的方式做事(基本上,根据表单接口传递的参数创建自己的路由器/调度器-没什么大不了的,这是可行的!)我意识到这是一篇老文章,但我自己刚开始玩围棋和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
最接近的匹配项,即/
在阅读了@Kodiak提供的答案后,我重新阅读了,发现了这一段:
请注意,由于以斜杠结尾的模式将根子树命名,因此模式“/”将匹配其他已注册模式未匹配的所有路径,而不仅仅是路径为=“/”的URL
如果已注册子树,并且收到一个请求,该请求命名子树根而不带尾随斜杠,则ServeMax会将该请求重定向到子树根(添加尾随斜杠)。可以使用不带尾随斜杠的路径的单独注册来覆盖此行为。例如,注册“/images/”会导致ServeMux将对“/images”的请求重定向到“/images/”,除非“/images”已单独注册
(斜体)
我的假设是,ServeMux
几乎表现为nginx
和/或Apache的rewrite
模块的基于规则的模式匹配特性,即。E规则是根据它们注册的顺序进行处理的,因此我希望首先匹配/first
(双关语),并且只有在没有找到匹配项的情况下,/
下一步才会匹配
但这并不是文件所说的。相反,登记顺序没有实际区别ServeMux
,在我给定的场景中,因为我忘了添加一个尾随斜杠,所以总是“退回”到“/”
的处理程序,这不是因为匹配算法的一些错误或扭曲,而是因为这是Go开发人员编写的预期行为!换句话说,如果您有一个处理程序来处理“/”
,那么它将充当每个非斜杠终止子树的全部处理程序
我只是没能正确地阅读文档!(或者早在2017年,这一段还不够清楚)fcgi只是提供HTTP服务器部分;处理程序及其注册由mux提供,在本例中,mux是标准的net/http
ServeMux
。它的行为应该不会有任何不同,我也不确定这两种情况怎么可能同时发生