gofast
gofast是纯粹写在Golang的FastCGI“客户端”库。
内容
真的做什么?
在FastCGI规范中,FastCGI系统具有2个组件: (a)Web服务器; (b)应用程序服务器。 Web服务器应通过套接字将请求信息交给应用程序服务器。应用程序服务器始终倾听插座并响应套接字请求。
gofast可帮助您在此图片的Web服务器部分上编写代码。它可以帮助您将请求传递给应用程序服务器并从中接收响应。
您可能会认为gofast是“客户库”,以消费任何FastCGI应用程序服务器。
为什么?
许多受欢迎的语言(例如Python,PHP,Nodejs)具有FastCGI应用程序服务器的实现。使用gofast ,您可以简单地使用这些语言混合使用。
另外,这很有趣:-)
如何使用?
您基本上将使用Handler作为http.handler。您可以使用默认的ServeMux或其他兼容的路由器(例如Gorilla,Pat)进一步MUX。然后,您可以在此Golang HTTP服务器中使用FastCGI。
简单示例
请注意,这只是Web服务器组件。您需要在其他地方启动应用程序组件。
gofast\”
)
func main() {
// Get fastcgi application server tcp address
// from env FASTCGI_ADDR. Then configure
// connection factory for the address.
address := os.Getenv(\”FASTCGI_ADDR\”)
connFactory := gofast .SimpleConnFactory(\”tcp\”, address)
// route all requests to a single php file
http.Handle(\”/\”, gofast .NewHandler(
gofast .NewFileEndpoint(\”/var/www/html/index.php\”)( gofast .BasicSession),
gofast .SimpleClientFactory(connFactory),
))
// serve at 8080 port
log.Fatal(http.ListenAndServe(\”:8080\”, nil))
}
\”>
// this is a very simple fastcgi web server package main import ( \"log\" \"net/http\" \"os\" \"github.com/yookoala/ gofast \" ) func main () { // Get fastcgi application server tcp address // from env FASTCGI_ADDR. Then configure // connection factory for the address. address := os . Getenv ( \"FASTCGI_ADDR\" ) connFactory := gofast . SimpleConnFactory ( \"tcp\" , address ) // route all requests to a single php file http . Handle ( \"/\" , gofast . NewHandler ( gofast . NewFileEndpoint ( \"/var/www/html/index.php\" )( gofast . BasicSession ), gofast . SimpleClientFactory ( connFactory ), )) // serve at 8080 port log . Fatal ( http . ListenAndServe ( \":8080\" , nil )) }
高级示例
正常的PHP应用
要服务普通的PHP应用程序,您需要:
- 从文件系统服务静态资产;和
- 仅使用相关的PHP文件服务路径。
代码
gofast\”
)
func main() {
// Get fastcgi application server tcp address
// from env FASTCGI_ADDR. Then configure
// connection factory for the address.
address := os.Getenv(\”FASTCGI_ADDR\”)
connFactory := gofast .SimpleConnFactory(\”tcp\”, address)
// handles static assets in the assets folder
http.Handle(\”/assets/\”,
http.StripPrefix(\”/assets/\”,
http.FileServer(http.FileSystem(http.Dir(\”/var/www/html/assets\”)))))
// route all requests to relevant PHP file
http.Handle(\”/\”, gofast .NewHandler(
gofast .NewPHPFS(\”/var/www/html\”)( gofast .BasicSession),
gofast .SimpleClientFactory(connFactory),
))
// serve at 8080 port
log.Fatal(http.ListenAndServe(\”:8080\”, nil))
}
\”>
package main import ( \"fmt\" \"net/http\" \"os\" \"github.com/yookoala/ gofast \" ) func main () { // Get fastcgi application server tcp address // from env FASTCGI_ADDR. Then configure // connection factory for the address. address := os . Getenv ( \"FASTCGI_ADDR\" ) connFactory := gofast . SimpleConnFactory ( \"tcp\" , address ) // handles static assets in the assets folder http . Handle ( \"/assets/\" , http . StripPrefix ( \"/assets/\" , http . FileServer ( http . FileSystem ( http . Dir ( \"/var/www/html/assets\" ))))) // route all requests to relevant PHP file http . Handle ( \"/\" , gofast . NewHandler ( gofast . NewPHPFS ( \"/var/www/html\" )( gofast . BasicSession ), gofast . SimpleClientFactory ( connFactory ), )) // serve at 8080 port log . Fatal ( http . ListenAndServe ( \":8080\" , nil )) }
使用中间件自定义请求会话
每个Web服务器请求将导致gofast 。并且每个gofast .Request将首先通过SessionHandler运行,然后将gofast .client的Do()方法交给DO()方法。
默认的gofast .Basicsession实施无济于事。图书馆的功能像gofast .Newphpfs, gofast .newfileendpoint是gofast .Middleware实现,它们是较低级别的中间件链。
因此,您可以通过实现gofast .Middleware自定义自己的会话。
代码
gofast\”
)
func main() {
// Get fastcgi application server tcp address
// from env FASTCGI_ADDR. Then configure
// connection factory for the address.
address := os.Getenv(\”FASTCGI_ADDR\”)
connFactory := gofast .SimpleConnFactory(\”tcp\”, address)
// a custom authentication handler
customAuth := func(inner gofast .SessionHandler) gofast .SessionHandler {
return func(client gofast .Client, req * gofast .Request) (* gofast .ResponsePipe, error) {
user, err := someCustomAuth(
req.Raw.Header.Get(\”Authorization\”))
if err != nil {
// if login not success
return nil, err
}
// set REMOTE_USER accordingly
req.Params[\”REMOTE_USER\”] = user
// run inner session handler
return inner(client, req)
}
}
// session handler
sess := gofast .Chain(
customAuth, // maps REMOTE_USER
gofast .BasicParamsMap, // maps common CGI parameters
gofast .MapHeader, // maps header fields into HTTP_* parameters
gofast .MapRemoteHost, // maps REMOTE_HOST
)( gofast .BasicSession)
// route all requests to a single php file
http.Handle(\”/\”, gofast .NewHandler(
gofast .NewFileEndpoint(\”/var/www/html/index.php\”)(sess),
gofast .SimpleClientFactory(connFactory),
))
// serve at 8080 port
log.Fatal(http.ListenAndServe(\”:8080\”, nil))
}
\”>
package main import ( \"fmt\" \"net/http\" \"os\" \"github.com/yookoala/ gofast \" ) func main () { // Get fastcgi application server tcp address // from env FASTCGI_ADDR. Then configure // connection factory for the address. address := os . Getenv ( \"FASTCGI_ADDR\" ) connFactory := gofast . SimpleConnFactory ( \"tcp\" , address ) // a custom authentication handler customAuth := func ( inner gofast . SessionHandler ) gofast . SessionHandler { return func ( client gofast . Client , req * gofast . Request ) ( * gofast . ResponsePipe , error ) { user , err := someCustomAuth ( req . Raw . Header . Get ( \"Authorization\" )) if err != nil { // if login not success return nil , err } // set REMOTE_USER accordingly req . Params [ \"REMOTE_USER\" ] = user // run inner session handler return inner ( client , req ) } } // session handler sess := gofast . Chain ( customAuth , // maps REMOTE_USER gofast . BasicParamsMap , // maps common CGI parameters gofast . MapHeader , // maps header fields into HTTP_* parameters gofast . MapRemoteHost , // maps REMOTE_HOST )( gofast . BasicSession ) // route all requests to a single php file http . Handle ( \"/\" , gofast . NewHandler ( gofast . NewFileEndpoint ( \"/var/www/html/index.php\" )( sess ), gofast . SimpleClientFactory ( connFactory ), )) // serve at 8080 port log . Fatal ( http . ListenAndServe ( \":8080\" , nil )) }
FastCGI授权者
FASTCGI指定了授权使用“授权器应用程序”的HTTP请求的授权者角色。与通常的FASTCGI应用程序(IE响应者)不同,它仅进行授权检查。
规格摘要
在实际服务HTTP请求之前,Web服务器可以将正常的FASTCGI请求格式化为仅使用FastCGI参数( FCGI_PARAMS流)的授权器应用程序。此应用程序负责确定请求是否正确验证并授权该请求。
如果有效,
-
授权器应用程序应使用HTTP状态
200(确定)响应。 -
它可以通过将
Variable-SOME-HEADER头标头字段添加到其对Web服务器的响应中,从而将其他变量(例如SOME-HEADER)添加到子序列请求中。 -
Web服务器将从旧的请求创建一个新的HTTP请求,并附加附加标题变量(例如
Some-Header),然后将修改后的请求发送到子任务应用程序。
如果无效,
-
授权器应用程序应以HTTP状态为不
200http状态响应,并且要显示登录失败的内容。 -
Web服务器将跳过响应者,直接显示授权者的回应。
代码
gofast\”
)
func myApp() http.Handler {
// … any normal http.Handler, using gofast or not
return h
}
func main() {
address := os.Getenv(\”FASTCGI_ADDR\”)
connFactory := gofast .SimpleConnFactory(\”tcp\”, address)
clientFactory := gofast .SimpleClientFactory(connFactory)
// authorization with php
authSess := gofast .Chain(
gofast .NewAuthPrepare(),
gofast .NewFileEndpoint(\”/var/www/html/authorization.php\”),
)( gofast .BasicSession)
authorizer := gofast .NewAuthorizer(
authSess,
gofast .SimpleConnFactory(network, address)
)
// wrap the actual app
http.Handle(\”/\”, authorizer.Wrap(myApp()))
// serve at 8080 port
log.Fatal(http.ListenAndServe(\”:8080\”, nil))
}
\”>
package main import ( \"net/http\" \"time\" \"github.com/yookoala/ gofast \" ) func myApp () http. Handler { // ... any normal http.Handler, using gofast or not return h } func main () { address := os . Getenv ( \"FASTCGI_ADDR\" ) connFactory := gofast . SimpleConnFactory ( \"tcp\" , address ) clientFactory := gofast . SimpleClientFactory ( connFactory ) // authorization with php authSess := gofast . Chain ( gofast . NewAuthPrepare (), gofast . NewFileEndpoint ( \"/var/www/html/authorization.php\" ), )( gofast . BasicSession ) authorizer := gofast . NewAuthorizer ( authSess , gofast . SimpleConnFactory ( network , address ) ) // wrap the actual app http . Handle ( \"/\" , authorizer . Wrap ( myApp ())) // serve at 8080 port log . Fatal ( http . ListenAndServe ( \":8080\" , nil )) }
FastCGI过滤器
FastCGI在发送之前指定了过滤Web服务器资产的过滤角色。与通常的FastCGI应用程序(IE响应者)不同,请求的数据位于Web服务器端。因此,当要求时,Web服务器将将这些数据传递给应用程序。
代码
gofast\”
)
func main() {
address := os.Getenv(\”FASTCGI_ADDR\”)
connFactory := gofast .SimpleConnFactory(\”tcp\”, address)
clientFactory := gofast .SimpleClientFactory(connFactory)
// Note: The local file system \”/var/www/html/\” only need to be
// local to web server. No need for the FastCGI application to access
// it directly.
connFactory := gofast .SimpleConnFactory(network, address)
http.Handle(\”/\”, gofast .NewHandler(
gofast .NewFilterLocalFS(\”/var/www/html/\”)( gofast .BasicSession),
clientFactory,
))
// serve at 8080 port
log.Fatal(http.ListenAndServe(\”:8080\”, nil))
}
\”>
package main import ( \"net/http\" \"time\" \"github.com/yookoala/ gofast \" ) func main () { address := os . Getenv ( \"FASTCGI_ADDR\" ) connFactory := gofast . SimpleConnFactory ( \"tcp\" , address ) clientFactory := gofast . SimpleClientFactory ( connFactory ) // Note: The local file system \"/var/www/html/\" only need to be // local to web server. No need for the FastCGI application to access // it directly. connFactory := gofast . SimpleConnFactory ( network , address ) http . Handle ( \"/\" , gofast . NewHandler ( gofast . NewFilterLocalFS ( \"/var/www/html/\" )( gofast . BasicSession ), clientFactory , )) // serve at 8080 port log . Fatal ( http . ListenAndServe ( \":8080\" , nil )) }
汇总客户
为了拥有更好,更受控的扩展属性,您可以使用客户室扩展客户端。
代码
gofast\”
)
func main() {
// Get fastcgi application server tcp address
// from env FASTCGI_ADDR. Then configure
// connection factory for the address.
address := os.Getenv(\”FASTCGI_ADDR\”)
connFactory := gofast .SimpleConnFactory(\”tcp\”, address)
// handles static assets in the assets folder
http.Handle(\”/assets/\”,
http.StripPrefix(\”/assets/\”,
http.FileSystem(http.Dir(\”/var/www/html/assets\”))))
// handle all scripts in document root
// extra pooling layer
pool := gofast .NewClientPool(
gofast .SimpleClientFactory(connFactory),
10, // buffer size for pre-created client-connection
30*time.Second, // life span of a client before expire
)
http.Handle(\”/\”, gofast .NewHandler(
gofast .NewPHPFS(\”/var/www/html\”)( gofast .BasicSession),
pool.CreateClient,
))
// serve at 8080 port
log.Fatal(http.ListenAndServe(\”:8080\”, nil))
}
\”>
package main import ( \"fmt\" \"net/http\" \"os\" \"github.com/yookoala/ gofast \" ) func main () { // Get fastcgi application server tcp address // from env FASTCGI_ADDR. Then configure // connection factory for the address. address := os . Getenv ( \"FASTCGI_ADDR\" ) connFactory := gofast . SimpleConnFactory ( \"tcp\" , address ) // handles static assets in the assets folder http . Handle ( \"/assets/\" , http . StripPrefix ( \"/assets/\" , http . FileSystem ( http . Dir ( \"/var/www/html/assets\" )))) // handle all scripts in document root // extra pooling layer pool := gofast . NewClientPool ( gofast . SimpleClientFactory ( connFactory ), 10 , // buffer size for pre-created client-connection 30 * time . Second , // life span of a client before expire ) http . Handle ( \"/\" , gofast . NewHandler ( gofast . NewPHPFS ( \"/var/www/html\" )( gofast . BasicSession ), pool . CreateClient , )) // serve at 8080 port log . Fatal ( http . ListenAndServe ( \":8080\" , nil )) }
完整的例子
请参阅示例用法:
- php
- python3
- nodejs
作者
该图书馆由考拉·杨(Koala Yeung)撰写。
贡献
欢迎您为这个图书馆做出贡献。
要报告错误,请使用问题跟踪器。
要修复现有错误或实施新功能,请:
- 检查问题跟踪器并提取现有讨论请求。
- 如果没有,请打开一个新问题进行讨论。
- 写测试。
- 打开引用该问题的拉请请求。
- 玩得开心 :-)
执照
该库是根据BSD式许可发布的。请在此存储库中找到许可证文件
