{"id":13798075,"url":"https://github.com/yookoala/gofast","last_synced_at":"2025-04-05T02:09:41.278Z","repository":{"id":51797387,"uuid":"49763674","full_name":"yookoala/gofast","owner":"yookoala","description":"gofast is a FastCGI \"client\" library written purely in go","archived":false,"fork":false,"pushed_at":"2024-03-30T05:46:35.000Z","size":245,"stargazers_count":231,"open_issues_count":9,"forks_count":50,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-03-29T01:08:07.188Z","etag":null,"topics":["fastcgi","golang","golang-library","golang-middleware","hacktoberfest","nodejs","php-fpm","python3","webserver"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yookoala.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-16T07:16:12.000Z","updated_at":"2025-02-20T05:17:25.000Z","dependencies_parsed_at":"2022-08-17T15:25:53.095Z","dependency_job_id":"7bb27aa5-8267-4ae3-8545-88136c88f21e","html_url":"https://github.com/yookoala/gofast","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yookoala%2Fgofast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yookoala%2Fgofast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yookoala%2Fgofast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yookoala%2Fgofast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yookoala","download_url":"https://codeload.github.com/yookoala/gofast/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247276188,"owners_count":20912288,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastcgi","golang","golang-library","golang-middleware","hacktoberfest","nodejs","php-fpm","python3","webserver"],"created_at":"2024-08-04T00:00:38.665Z","updated_at":"2025-04-05T02:09:41.260Z","avatar_url":"https://github.com/yookoala.png","language":"Go","readme":"# gofast [![GoDoc][godoc-badge]][godoc] [![Go Report Card][goreport-badge]][goreport] [![Travis CI results][travis-badge]][travis] [![GitHub Action Test result][github-action-badge]][github-action]\n\n**gofast** is a [FastCGI][fastcgi] \"client\" library written purely in\n[golang][golang].\n\n## Contents\n\n* [What does it do, really?](#what-does-it-do-really)\n* [Why?](#why)\n* [How to Use?](#how-to-use)\n  * [Simple Example](#simple-example)\n  * [Advanced Examples](#advanced-examples)\n    * [Normal PHP Application](#normal-php-application)\n    * [Customizing Request Session with Middleware](#customizing-request-session-with-middleware)\n    * [FastCGI Authorizer](#fastcgi-authorizer)\n    * [FastCGI Filter](#fastcgi-filter)\n    * [Pooling Clients](#pooling-clients)\n  * [Full Examples](#full-examples)\n* [Author](#author)\n* [Contributing](#contributing)\n* [Licence](#licence)\n\n[fastcgi]: http://www.mit.edu/~yandros/doc/specs/fcgi-spec.html\n[godoc]: https://godoc.org/github.com/yookoala/gofast\n[godoc-badge]: https://godoc.org/github.com/yookoala/gofast?status.svg\n[travis]: https://travis-ci.com/github/yookoala/gofast?branch=main\n[travis-badge]: https://api.travis-ci.com/yookoala/gofast.svg?branch=main\n[github-action]: https://github.com/yookoala/gofast/actions?query=workflow%3ATests+branch%3Amain\n[github-action-badge]: https://github.com/yookoala/gofast/actions/workflows/ci.yml/badge.svg?branch=main\n[goreport]: https://goreportcard.com/report/github.com/yookoala/gofast\n[goreport-badge]: https://goreportcard.com/badge/github.com/yookoala/gofast\n[golang]: https://golang.org\n\n## What does it do, really?\n\nIn FastCGI specification, a FastCGI system has 2 components: **(a) web\nserver**; and **(b) application server**. A web server should hand over\nrequest information to the application server through socket. The\napplication server always listens to the socket and response to\nsocket request accordingly.\n\n[![visitor → web server → application server → web server → visitor][fastcgi-illustration]][fastcgi-illustration]\n\n[fastcgi-illustration]: docs/fastcgi-illustration.svg\n\n**gofast** help you to write the code on the **web server** part of this\npicture. It helps you to pass the request to application server and\nreceive response from it.\n\nYou may think of **gofast** as a \"client library\" to consume\nany FastCGI application server.\n\n## Why?\n\nMany popular languages (e.g. [Python][python/webservers],\n[PHP][php-fpm], [nodejs][node-fastcgi]) has FastCGI application\nserver implementations. With **gofast**, you may mix using the languages\nin a simple way.\n\nAlso, this is fun to do :-)\n\n[php-fpm]: http://php.net/manual/en/install.fpm.php\n[python/webservers]: https://docs.python.org/3.1/howto/webservers.html\n[node-fastcgi]: https://www.npmjs.com/package/node-fastcgi\n\n\n## How to Use?\n\nYou basically would use the `Handler` as [http.Handler]. You can further mux it\nwith [default ServeMux][http.NewServeMux] or other compatible routers (e.g.\n[gorilla][gorilla], [pat][pat]). You then serve your fastcgi within this\ngolang http server.\n\n[http.Handler]: https://golang.org/pkg/net/http/#Handler\n[mux]: https://golang.org/pkg/net/http/#ServeMux\n[http.NewServeMux]: https://golang.org/pkg/net/http/#NewServeMux\n[gorilla]: https://github.com/gorilla/mux\n[pat]: https://github.com/gorilla/pat\n\n### Simple Example\n\nPlease note that this is only the **web server** component. You need to start\nyour **application** component elsewhere.\n\n```go\n// this is a very simple fastcgi web server\npackage main\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/yookoala/gofast\"\n)\n\nfunc main() {\n\t// Get fastcgi application server tcp address\n\t// from env FASTCGI_ADDR. Then configure\n\t// connection factory for the address.\n\taddress := os.Getenv(\"FASTCGI_ADDR\")\n\tconnFactory := gofast.SimpleConnFactory(\"tcp\", address)\n\n\t// route all requests to a single php file\n\thttp.Handle(\"/\", gofast.NewHandler(\n\t\tgofast.NewFileEndpoint(\"/var/www/html/index.php\")(gofast.BasicSession),\n\t\tgofast.SimpleClientFactory(connFactory),\n\t))\n\n\t// serve at 8080 port\n\tlog.Fatal(http.ListenAndServe(\":8080\", nil))\n}\n\n```\n\n### Advanced Examples\n\n#### Normal PHP Application\n\nTo serve normal PHP application, you'd need to:\n\n1. Serve the static assets from file system; and\n1. Serve only the path with relevant PHP file.\n\n\u003cdetails\u003e\n\u003csummary\u003eCode\u003c/summary\u003e\n\u003cdiv\u003e\n\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/yookoala/gofast\"\n)\n\nfunc main() {\n\t// Get fastcgi application server tcp address\n\t// from env FASTCGI_ADDR. Then configure\n\t// connection factory for the address.\n\taddress := os.Getenv(\"FASTCGI_ADDR\")\n\tconnFactory := gofast.SimpleConnFactory(\"tcp\", address)\n\n\t// handles static assets in the assets folder\n\thttp.Handle(\"/assets/\",\n\t\thttp.StripPrefix(\"/assets/\",\n\t\t\thttp.FileServer(http.FileSystem(http.Dir(\"/var/www/html/assets\")))))\n\n\t// route all requests to relevant PHP file\n\thttp.Handle(\"/\", gofast.NewHandler(\n\t\tgofast.NewPHPFS(\"/var/www/html\")(gofast.BasicSession),\n\t\tgofast.SimpleClientFactory(connFactory),\n\t))\n\n\t// serve at 8080 port\n\tlog.Fatal(http.ListenAndServe(\":8080\", nil))\n}\n\n```\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\n#### Customizing Request Session with Middleware\n\nEach web server request will result in a [gofast.Request][gofast-request].\nAnd each [gofast.Request][gofast-request] will first run through SessionHandler\nbefore handing to the `Do()` method of [gofast.Client][gofast-client].\n\nThe default [gofast.BasicSession][gofast-basicsession] implementation does\nnothing. The library function like [gofast.NewPHPFS][gofast-phpfs],\n[gofast.NewFileEndpoint][gofast-file-endpoint] are [gofast.Middleware][gofast-middleware]\nimplementations, which are lower level middleware chains.\n\nSo you may customize your own session by implemention [gofast.Middleware][gofast-middleware].\n\n\u003cdetails\u003e\n\u003csummary\u003eCode\u003c/summary\u003e\n\u003cdiv\u003e\n\n```go\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/yookoala/gofast\"\n)\n\nfunc main() {\n\t// Get fastcgi application server tcp address\n\t// from env FASTCGI_ADDR. Then configure\n\t// connection factory for the address.\n\taddress := os.Getenv(\"FASTCGI_ADDR\")\n\tconnFactory := gofast.SimpleConnFactory(\"tcp\", address)\n\n\t// a custom authentication handler\n\tcustomAuth := func(inner gofast.SessionHandler) gofast.SessionHandler {\n\t\treturn func(client gofast.Client, req *gofast.Request) (*gofast.ResponsePipe, error) {\n\t\t\tuser, err := someCustomAuth(\n\t\t\t\treq.Raw.Header.Get(\"Authorization\"))\n\t\t\tif err != nil {\n\t\t\t\t// if login not success\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\t// set REMOTE_USER accordingly\n\t\t\treq.Params[\"REMOTE_USER\"] = user\n\t\t\t// run inner session handler\n\t\t\treturn inner(client, req)\n\t\t}\n\t}\n\n\t// session handler\n\tsess := gofast.Chain(\n\t\tcustomAuth,            // maps REMOTE_USER\n\t\tgofast.BasicParamsMap, // maps common CGI parameters\n\t\tgofast.MapHeader,      // maps header fields into HTTP_* parameters\n\t\tgofast.MapRemoteHost,  // maps REMOTE_HOST\n\t)(gofast.BasicSession)\n\n\t// route all requests to a single php file\n\thttp.Handle(\"/\", gofast.NewHandler(\n\t\tgofast.NewFileEndpoint(\"/var/www/html/index.php\")(sess),\n\t\tgofast.SimpleClientFactory(connFactory),\n\t))\n\n\t// serve at 8080 port\n\tlog.Fatal(http.ListenAndServe(\":8080\", nil))\n}\n\n```\n\u003c/div\u003e\n\u003c/details\u003e\n\n[gofast-basicsession]: https://godoc.org/github.com/yookoala/gofast#BasicSession\n[gofast-request]: https://godoc.org/github.com/yookoala/gofast#Request\n[gofast-client]: https://godoc.org/github.com/yookoala/gofast#Client\n[gofast-phpfs]: https://godoc.org/github.com/yookoala/gofast#NewPHPFS\n[gofast-file-endpoint]: https://godoc.org/github.com/yookoala/gofast#NewFileEndpoint\n[gofast-middleware]: https://godoc.org/github.com/yookoala/gofast#Middleware\n\n#### FastCGI Authorizer\n\nFastCGI specified an [authorizer role][fastcgi-authorizer] for authorizing\nan HTTP request with an \"authorizer application\". As different from a usual\nFastCGI application (i.e. **responder**), it only does authorization check.\n\n\u003cdetails\u003e\n\u003csummary\u003eSummary of Spec\u003c/summary\u003e\n\u003cdiv\u003e\n\nBefore actually serving an HTTP request, a web server can format a normal\nFastCGI request to the Authorizer application with only FastCGI parameters\n(`FCGI_PARAMS` stream). This application is responsible to determine if the\nrequest is properly authenticated and authorized for the request.\n\nIf valid,\n\n* The authorizer application should response with HTTP status `200` (OK).\n\n* It may add additional variables (e.g. `SOME-HEADER`) to the subsequence\n  request by adding `Variable-SOME-HEADER` header field to its response to\n  web server.\n\n* The web server will create a new HTTP request from the old one, appending\n  the additional header variables (e.g. `Some-Header`), then send the modified\n  request to the subquence application.\n\nIf invalid,\n\n* The authorizer application should response with HTTP status that is NOT\n  `200`, and the content to display for failed login.\n\n* The webserver will skip the responder and directly show the authorizer's\n  response.\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eCode\u003c/summary\u003e\n\u003cdiv\u003e\n\n```go\n\npackage main\n\nimport (\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/yookoala/gofast\"\n)\n\nfunc myApp() http.Handler {\n  // ... any normal http.Handler, using gofast or not\n\treturn h\n}\n\nfunc main() {\n\taddress := os.Getenv(\"FASTCGI_ADDR\")\n\tconnFactory := gofast.SimpleConnFactory(\"tcp\", address)\n\tclientFactory := gofast.SimpleClientFactory(connFactory)\n\n\t// authorization with php\n\tauthSess := gofast.Chain(\n\t\tgofast.NewAuthPrepare(),\n\t\tgofast.NewFileEndpoint(\"/var/www/html/authorization.php\"),\n\t)(gofast.BasicSession)\n\tauthorizer := gofast.NewAuthorizer(\n\t\tauthSess,\n\t\tgofast.SimpleConnFactory(network, address)\n\t)\n\n\t// wrap the actual app\n\thttp.Handle(\"/\", authorizer.Wrap(myApp()))\n\n\t// serve at 8080 port\n\tlog.Fatal(http.ListenAndServe(\":8080\", nil))\n}\n\n```\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n\n[fastcgi-authorizer]: http://www.mit.edu/~yandros/doc/specs/fcgi-spec.html#S6.3\n\n\n#### FastCGI Filter\n\nFastCGI specified a [filter role][fastcgi-filter] for filtering web server\nassets before sending out. As different from a usual FastCGI application\n(i.e. **responder**), the requested data is on the web server side. So the\nweb server will pass those data to the application when requested.\n\n\u003cdetails\u003e\n\u003csummary\u003eCode\u003c/summary\u003e\n\u003cdiv\u003e\n\n```go\n\npackage main\n\nimport (\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/yookoala/gofast\"\n)\n\nfunc main() {\n\taddress := os.Getenv(\"FASTCGI_ADDR\")\n\tconnFactory := gofast.SimpleConnFactory(\"tcp\", address)\n\tclientFactory := gofast.SimpleClientFactory(connFactory)\n\n\t// Note: The local file system \"/var/www/html/\" only need to be\n\t// local to web server. No need for the FastCGI application to access\n\t// it directly.\n\tconnFactory := gofast.SimpleConnFactory(network, address)\n\thttp.Handle(\"/\", gofast.NewHandler(\n\t\tgofast.NewFilterLocalFS(\"/var/www/html/\")(gofast.BasicSession),\n\t\tclientFactory,\n\t))\n\n\t// serve at 8080 port\n\tlog.Fatal(http.ListenAndServe(\":8080\", nil))\n}\n\n```\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n[fastcgi-filter]: http://www.mit.edu/~yandros/doc/specs/fcgi-spec.html#S6.4\n\n\n#### Pooling Clients\n\nTo have a better, more controlled, scaling property, you may\nscale the clients with ClientPool.\n\n\u003cdetails\u003e\n\u003csummary\u003eCode\u003c/summary\u003e\n\u003cdiv\u003e\n\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/yookoala/gofast\"\n)\n\nfunc main() {\n\t// Get fastcgi application server tcp address\n\t// from env FASTCGI_ADDR. Then configure\n\t// connection factory for the address.\n\taddress := os.Getenv(\"FASTCGI_ADDR\")\n\tconnFactory := gofast.SimpleConnFactory(\"tcp\", address)\n\n\t// handles static assets in the assets folder\n\thttp.Handle(\"/assets/\",\n\t\thttp.StripPrefix(\"/assets/\",\n\t\t\thttp.FileSystem(http.Dir(\"/var/www/html/assets\"))))\n\n\t// handle all scripts in document root\n\t// extra pooling layer\n\tpool := gofast.NewClientPool(\n\t\tgofast.SimpleClientFactory(connFactory),\n\t\t10, // buffer size for pre-created client-connection\n\t\t30*time.Second, // life span of a client before expire\n\t)\n\thttp.Handle(\"/\", gofast.NewHandler(\n\t\tgofast.NewPHPFS(\"/var/www/html\")(gofast.BasicSession),\n\t\tpool.CreateClient,\n\t))\n\n\t// serve at 8080 port\n\tlog.Fatal(http.ListenAndServe(\":8080\", nil))\n}\n\n```\n\n\u003c/div\u003e\n\u003c/details\u003e\n\n### Full Examples\n\nPlease see the example usages:\n\n* [PHP]\n* [Python3]\n* [nodejs]\n\n[PHP]: example/php\n[Python3]: example/python3\n[nodejs]: example/nodejs\n\n\n## Author\n\nThis library is written by [Koala Yeung][author@github].\n\n[author@github]: https://github.com/yookoala/\n\n\n## Contributing\n\nYour are welcome to contribute to this library.\n\nTo report bug, please use the [issue tracker][issue tracker].\n\nTo fix an existing bug or implement a new feature, please:\n\n1. Check the [issue tracker][issue tracker] and [pull requests][pull requests] for existing discussion.\n2. If not, please open a new issue for discussion.\n3. Write tests.\n4. Open a pull request referencing the issue.\n5. Have fun :-)\n\n[issue tracker]: https://github.com/yookoala/gofast/issues\n[pull requests]: https://github.com/yookoala/gofast/pulls\n\n\n## Licence\n\nThis library is release under a BSD-like licence. Please find the\n[LICENCE][LICENCE] file in this repository\n\n[LICENCE]: /LICENCE\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyookoala%2Fgofast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyookoala%2Fgofast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyookoala%2Fgofast/lists"}