{"id":13491478,"url":"https://github.com/mtrudel/bandit","last_synced_at":"2025-05-12T13:28:33.255Z","repository":{"id":41315410,"uuid":"220852206","full_name":"mtrudel/bandit","owner":"mtrudel","description":"Bandit is a pure Elixir HTTP server for Plug \u0026 WebSock applications","archived":false,"fork":false,"pushed_at":"2025-05-09T19:17:26.000Z","size":15827,"stargazers_count":1780,"open_issues_count":3,"forks_count":89,"subscribers_count":26,"default_branch":"main","last_synced_at":"2025-05-10T03:14:43.687Z","etag":null,"topics":["elixir","elixir-phoenix","elixir-plug","h2spec","http","http-server","http2","http2-server","https","rfc-2616","rfc-6455","rfc-7540","rfc-9110","rfc-9112","rfc-9113","websocket"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtrudel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-11-10T21:14:23.000Z","updated_at":"2025-05-09T19:17:29.000Z","dependencies_parsed_at":"2023-12-20T16:38:03.332Z","dependency_job_id":"9bdddb1f-7a4c-4cb8-9ae0-d69857bc1ee9","html_url":"https://github.com/mtrudel/bandit","commit_stats":{"total_commits":437,"total_committers":13,"mean_commits":33.61538461538461,"dds":0.08924485125858128,"last_synced_commit":"959b6fe5a7dd376919067de415a26ccadca8014a"},"previous_names":[],"tags_count":110,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtrudel%2Fbandit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtrudel%2Fbandit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtrudel%2Fbandit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtrudel%2Fbandit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtrudel","download_url":"https://codeload.github.com/mtrudel/bandit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253747355,"owners_count":21957745,"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":["elixir","elixir-phoenix","elixir-plug","h2spec","http","http-server","http2","http2-server","https","rfc-2616","rfc-6455","rfc-7540","rfc-9110","rfc-9112","rfc-9113","websocket"],"created_at":"2024-07-31T19:00:57.377Z","updated_at":"2025-05-12T13:28:33.232Z","avatar_url":"https://github.com/mtrudel.png","language":"Elixir","funding_links":[],"categories":["Elixir"],"sub_categories":[],"readme":"![Bandit](https://github.com/mtrudel/bandit/raw/main/assets/readme_logo.png#gh-light-mode-only)\n![Bandit](https://github.com/mtrudel/bandit/raw/main/assets/readme_logo-darkmode.png#gh-dark-mode-only)\n\n[![Build Status](https://github.com/mtrudel/bandit/workflows/Elixir%20CI/badge.svg)](https://github.com/mtrudel/bandit/actions)\n[![Docs](https://img.shields.io/badge/api-docs-green.svg?style=flat)](https://hexdocs.pm/bandit)\n[![Hex.pm](https://img.shields.io/hexpm/v/bandit.svg?style=flat\u0026color=blue)](https://hex.pm/packages/bandit)\n\nBandit is an HTTP server for Plug and WebSock apps.\n\nBandit is written entirely in Elixir and is built atop [Thousand\nIsland](https://github.com/mtrudel/thousand_island). It can serve HTTP/1.x,\nHTTP/2 and WebSocket clients over both HTTP and HTTPS. It is written with\ncorrectness, clarity \u0026 performance as fundamental goals. It is the default HTTP\nserver for [Phoenix](https://github.com/phoenixframework/phoenix) since release 1.7.11 of the framework.\n\nIn [ongoing automated performance\ntests](https://github.com/mtrudel/bandit/actions/workflows/manual_benchmark.yml),\nBandit's HTTP/1.x engine is up to 4x faster than Cowboy depending on the number of concurrent\nrequests. When comparing HTTP/2 performance, Bandit is up to 1.5x faster than Cowboy. This is\npossible because Bandit has been built from the ground up for use with Plug applications; this\nfocus pays dividends in both performance and also in the approachability of the code base.\n\nBandit also emphasizes correctness. Its HTTP/2 implementation scores 100% on the\n[h2spec](https://github.com/summerwind/h2spec) suite in strict mode, and its\nWebSocket implementation scores 100% on the\n[Autobahn](https://github.com/crossbario/autobahn-testsuite) test suite, both of\nwhich run as part of Bandit's comprehensive CI suite. Extensive unit test,\ncredo, dialyzer, and performance regression test coverage round out a test suite\nthat ensures that Bandit is and will remain a platform you can count on.\n\nLastly, Bandit exists to demystify the lower layers of infrastructure code. In a world where\nThe New Thing is nearly always adding abstraction on top of abstraction, it's important to have\nfoundational work that is approachable \u0026 understandable by users above it in the stack.\n\n## Project Goals\n\n* Implement comprehensive support for HTTP/1.0 through HTTP/2 \u0026 WebSockets (and\n  beyond) backed by obsessive RFC literacy and automated conformance testing\n* Aim for minimal internal policy and HTTP-level configuration. Delegate to Plug \u0026 WebSock as much as\n  possible, and only interpret requests to the extent necessary to safely manage a connection\n  \u0026 fulfill the requirements of safely supporting protocol correctness\n* Prioritize (in order): correctness, clarity, performance. Seek to remove the mystery of\n  infrastructure code by being approachable and easy to understand\n* Along with our companion library [Thousand\n  Island](https://github.com/mtrudel/thousand_island), become the go-to HTTP\n  \u0026 low-level networking stack of choice for the Elixir community by being\n  reliable, efficient, and approachable\n\n## Project Status\n\n* Complete support for [Phoenix](https://github.com/phoenixframework/phoenix) applications (WebSocket\n  support requires Phoenix 1.7+)\n* Complete support of the [Plug API](https://github.com/elixir-plug/plug)\n* Complete support of the [WebSock API](https://github.com/phoenixframework/websock)\n* Complete server support for HTTP/1.x as defined in [RFC\n  9112](https://datatracker.ietf.org/doc/html/rfc9112) \u0026 [RFC\n  9110](https://datatracker.ietf.org/doc/html/rfc9110)\n* Complete server support for HTTP/2 as defined in [RFC\n  9113](https://datatracker.ietf.org/doc/html/rfc9113) \u0026 [RFC\n  9110](https://datatracker.ietf.org/doc/html/rfc9110), comprehensively covered\n  by automated [h2spec](https://github.com/summerwind/h2spec) conformance testing\n* Support for HTTP content encoding compression on both HTTP/1.x and HTTP/2.\n  gzip and deflate methods are supported per\n  [RFC9110§8.4.1.{2,3}](https://www.rfc-editor.org/rfc/rfc9110.html#section-8.4.1.2)\n* Complete server support for WebSockets as defined in [RFC\n  6455](https://datatracker.ietf.org/doc/html/rfc6455), comprehensively covered by automated\n  [Autobahn](https://github.com/crossbario/autobahn-testsuite) conformance testing. Per-message\n  compression as defined in [RFC 7692](https://datatracker.ietf.org/doc/html/rfc7692) is also\n  supported\n* Extremely scalable and performant client handling at a rate up to 4x that of Cowboy for the same\n  workload with as-good-or-better memory use\n\nAny Phoenix or Plug app should work with Bandit as a drop-in replacement for\nCowboy; exceptions to this are errors (if you find one, please [file an\nissue!](https://github.com/mtrudel/bandit/issues)).\n\n\u003c!-- MDOC --\u003e\n\n## Using Bandit With Phoenix\n\nBandit fully supports Phoenix. Phoenix applications which use WebSockets for\nfeatures such as Channels or LiveView require Phoenix 1.7 or later.\n\nUsing Bandit to host your Phoenix application couldn't be simpler:\n\n1. Add Bandit as a dependency in your Phoenix application's `mix.exs`:\n\n    ```elixir\n    {:bandit, \"~\u003e 1.0\"}\n    ```\n2. Add the following `adapter:` line to your endpoint configuration in `config/config.exs`, as in the following example:\n\n     ```elixir\n     # config/config.exs\n\n     config :your_app, YourAppWeb.Endpoint,\n       adapter: Bandit.PhoenixAdapter, # \u003c---- ADD THIS LINE\n       url: [host: \"localhost\"],\n       render_errors: ...\n     ```\n3. That's it! **You should now see messages at startup indicating that Phoenix is\n   using Bandit to serve your endpoint**, and everything should 'just work'. Note\n   that if you have set any exotic configuration options within your endpoint,\n   you may need to update that configuration to work with Bandit; see the\n   [Bandit.PhoenixAdapter](https://hexdocs.pm/bandit/Bandit.PhoenixAdapter.html)\n   documentation for more information.\n\n## Using Bandit With Plug Applications\n\nUsing Bandit to host your own Plug is very straightforward. Assuming you have\na Plug module implemented already, you can host it within Bandit by adding\nsomething similar to the following to your application's `Application.start/2`\nfunction:\n\n```elixir\n# lib/my_app/application.ex\n\ndefmodule MyApp.Application do\n  use Application\n\n  def start(_type, _args) do\n    children = [\n      {Bandit, plug: MyApp.MyPlug}\n    ]\n\n    opts = [strategy: :one_for_one, name: MyApp.Supervisor]\n    Supervisor.start_link(children, opts)\n  end\nend\n```\n\nFor less formal usage, you can also start Bandit using the same configuration\noptions via the `Bandit.start_link/1` function:\n\n```elixir\n# Start an http server on the default port 4000, serving MyApp.MyPlug\nBandit.start_link(plug: MyPlug)\n```\n\n## Configuration\n\nA number of options are defined when starting a server. The complete list is\ndefined by the [`t:Bandit.options/0`](https://hexdocs.pm/bandit/Bandit.html#summary) type.\n\n## Setting up an HTTPS Server\n\nBy far the most common stumbling block encountered when setting up an HTTPS\nserver involves configuring key and certificate data. Bandit is comparatively\neasy to set up in this regard, with a working example looking similar to the\nfollowing:\n\n```elixir\n# lib/my_app/application.ex\n\ndefmodule MyApp.Application do\n  use Application\n\n  def start(_type, _args) do\n    children = [\n      {Bandit,\n       plug: MyApp.MyPlug,\n       scheme: :https,\n       certfile: \"/absolute/path/to/cert.pem\",\n       keyfile: \"/absolute/path/to/key.pem\"}\n    ]\n\n    opts = [strategy: :one_for_one, name: MyApp.Supervisor]\n    Supervisor.start_link(children, opts)\n  end\nend\n```\n\n## WebSocket Support\n\nIf you're using Bandit to run a Phoenix application as suggested above, there is\nnothing more for you to do; WebSocket support will 'just work'.\n\nIf you wish to interact with WebSockets at a more fundamental level, the\n[WebSock](https://hexdocs.pm/websock/WebSock.html) and\n[WebSockAdapter](https://hexdocs.pm/websock_adapter/WebSockAdapter.html) libraries\nprovides a generic abstraction for WebSockets (very similar to how Plug is\na generic abstraction on top of HTTP). Bandit fully supports all aspects of\nthese libraries.\n\n## Receiving messages in your Plug process: A word of warning\n\nThe Plug specification is concerned only with the shape of the `c:Plug.init/1`\nand `c:Plug.call/2` functions; it says nothing about the process model that\nunderlies the call, nor about how the Plug function should respond to any\nmessages it may receive. Although it is occasionally necessary to receive\nmessages from within your Plug call, this must be done with caution as Bandit\nmakes extensive use of messaging internally, especially with HTTP/2 based\nrequests.\n\nIn particular, you must ensure that your code *never* receives messages that\nmatch the patterns `{:bandit, _}` or `{:plug_conn, :sent}`. Any `receive` calls\nyou make should be appropriately guarded to ensure that these messages remain in\nthe process' mailbox for Bandit to process them when required.\n\n\u003c!-- MDOC --\u003e\n\n## Implementation Details\n\nBandit primarily consists of three protocol-specific implementations, one each\nfor [HTTP/1][], [HTTP/2][] and [WebSockets][]. Each of these implementations is\nlargely distinct from one another, and is described in its own README linked\nabove.\n\nIf you're just taking a casual look at Bandit or trying to understand how an\nHTTP server works, the [HTTP/1][] implementation is likely the best place to\nstart exploring.\n\n[HTTP/1]: lib/bandit/http1/README.md\n[HTTP/2]: lib/bandit/http2/README.md\n[WebSockets]: lib/bandit/websocket/README.md\n\n## Contributing\n\nContributions to Bandit are very much welcome! Before undertaking any substantial work, please\nopen an issue on the project to discuss ideas and planned approaches so we can ensure we keep\nprogress moving in the same direction.\n\nAll contributors must agree and adhere to the project's [Code of\nConduct](https://github.com/mtrudel/bandit/blob/main/CODE_OF_CONDUCT.md).\n\nSecurity disclosures should be handled per Bandit's published [security policy](https://github.com/mtrudel/bandit/blob/main/SECURITY.md).\n\n## Installation\n\nBandit is [available in Hex](https://hex.pm/docs/publish). The package can be installed\nby adding `bandit` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:bandit, \"~\u003e 1.0\"}\n  ]\nend\n```\n\nDocumentation can be found at [https://hexdocs.pm/bandit](https://hexdocs.pm/bandit).\n\n# License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtrudel%2Fbandit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtrudel%2Fbandit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtrudel%2Fbandit/lists"}