{"id":13508215,"url":"https://github.com/hexedpackets/trot","last_synced_at":"2025-04-13T02:18:52.430Z","repository":{"id":31955933,"uuid":"35525814","full_name":"hexedpackets/trot","owner":"hexedpackets","description":"An Elixir web micro-framework.","archived":false,"fork":false,"pushed_at":"2019-09-09T15:33:44.000Z","size":122,"stargazers_count":420,"open_issues_count":15,"forks_count":29,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-04T04:11:52.593Z","etag":null,"topics":["elixir","plug"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hexedpackets.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-13T03:18:16.000Z","updated_at":"2025-03-05T20:01:36.000Z","dependencies_parsed_at":"2022-08-08T14:00:35.454Z","dependency_job_id":null,"html_url":"https://github.com/hexedpackets/trot","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/hexedpackets%2Ftrot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexedpackets%2Ftrot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexedpackets%2Ftrot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexedpackets%2Ftrot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hexedpackets","download_url":"https://codeload.github.com/hexedpackets/trot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654266,"owners_count":21140271,"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","plug"],"created_at":"2024-08-01T02:00:49.866Z","updated_at":"2025-04-13T02:18:52.398Z","avatar_url":"https://github.com/hexedpackets.png","language":"Elixir","readme":"# trot\n[![Hex.pm](https://img.shields.io/hexpm/v/trot.svg)](https://hex.pm/packages/trot) [![Build Status](https://travis-ci.org/hexedpackets/trot.svg?branch=master)](https://travis-ci.org/hexedpackets/trot) [![Inline docs](http://inch-ci.org/github/hexedpackets/trot.svg)](http://inch-ci.org/github/hexedpackets/trot)\n\nTrot is an Elixir web micro-framework based on Plug and Cowboy. The goal of Trot is to make common patterns in Plug easier to use, particularly when writing APIs, without sacrificing flexibility.\n\n## Usage\nAdd Trot as a dependency to your `mix.exs` file:\n\n```Elixir\n    defp deps do\n      [{:trot, github: \"hexedpackets/trot\"}]\n    end\n```\n\nThe following configuration options are supported by the server:\n\n`config :trot, :port, 4000`: port to listen on for incoming HTTP requests. Defaults to \"4000\".\n\n`config :trot, :router, MyApp.Router`: module to route requests to. Defaults to \"Trot.NotFound\".\n\n`config :trot, :heartbeat, \"/heartbeat\"`: path to setup a heartbeat route. This will always return 200 with a body of\n\"OK\". Defaults to \"/heartbeat\". NOTE: This value will only have an effect when PlugHeartbeat is part of the plug list.\n\n`config :trot, :pre_routing, [\"Elixir.CustomPlug\": [plug_arg: value]]`: Plugs that should be run before routing a request along with their arguments. Defaults to setting up \"Trot.LiveReload\", \"Plug.Logger\", \"Plug.Parsers\", and \"PlugHeartbeat\" in that order.\n\n`config :trot, :post_routing, [\"Elixir.CustomPlug\": [plug_arg: value]]`: Plugs that should be run after routing a request along with their arguments. Defaults to \"[]\".\n\nFinally, put `use Trot.Router` to the top of your module. This will add route macros and setup the plug pipeline at compile time.\n\n\n## Getting started\nTo get a basic devserver up and running, make sure you add a Router module in the config as described above, and then simply\n```\n$ mix trot.server\n```\n\n_Note: You can also start the server as well as an iex shell by running `iex -S mix`_\n\n## Routes\nRoutes are specified using one of the HTTP method macros: `get/3`, `post/3`, `put/3`, `patch/3`, `delete/3`, `options/3`. The first argument is a the path to route to, the second (optional) argument is a keyword list of any options to match against,  and the last argument is the block of code to execute. Examples are below.\n\nIf `@path_root` is specified, it will be prefixed to all routes in that module.\n\nRoutes can be setup in different modules and imported into the main router with the `import_routes/1` macro, which takes a module name as the only argument. Note that ordering matters as normal Elixir pattern matching rules apply to imported routes.\n\nA default 404 response can be enabled by putting `import_routes Trot.NotFound` or `use Trot.NotFound` at the end of the module.\n\n### Responses\nAll of the following are valid return values from handlers and will be parsed into full HTTP responses:\n- String of response body\n- Status code, either numeric or an atom from `Plug.Conn.Status`\n- `{code, body}`\n- `{code, body, headers}`\n- JSONable object\n- `{code, object}`\n- `{code, object, headers}`\n- `{:redirect, location}`\n- `{:badrpc, error}`\n- `%Plug.Conn{}`\n\n### Example router application\n\n```Elixir\n    defmodule SoLoMoApp.Router do\n      use Trot.Router\n\n      # Setup a static route to priv/static/assets\n      static \"/css\", \"assets\"\n\n      # Returns an empty body with a status code of 400\n      get \"/bad\" do\n        :bad_request\n      end\n\n      # Sets the status code to 200 with a text body\n      get \"/text\" do\n        \"Thank you for your question.\"\n      end\n\n      # Redirect the incoming request\n      get \"/text/body\", headers: [\"x-text-type\": \"question\"] do\n        {:redirect, \"/text\"}\n      end\n\n      # Sets the status code to 201 with a text body\n      get \"/text/body\" do\n        {201, \"optimal tip-to-tip efficiency\"}\n      end\n\n      # Sets status code to 200 with a JSON-encoded body\n      get \"/json\" do\n        %{\"hyper\" =\u003e \"social\"}\n      end\n\n      # Pattern match part of the path into a variable\n      get \"/presenter/:name\" do\n        \"The presenter is #{name}\"\n      end\n\n      import_routes Trot.NotFound\n    end\n```\n\n## Templating\nTo add templating in a router, add `use Trot.Template` and set `@template_root` to the top-level directory containing your templates. By default, `@template_root` is \"priv/templates/\".\n\nTrot can be used to render EEx templates (the default engine include with Elixir), HAML templates through [Calliope](https://github.com/nurugger07/calliope), or a combination of both. When the application is compiled a `render_template/2` function is generated for every template under `@template_root`. `render_template/2` expects the name of the template relative to `@template_root` as the first argument and a keyword list of variables to assign as the second argument.\n\nWhen `MIX_ENV=prod` all of templates are loaded and pre-compiled for faster rendering.\n\n### Example app using templates\n\n```Elixir\n    defmodule PiedPiper do\n      use Trot.Router\n      use Trot.Template\n      @template_root \"priv/templates/root\"\n\n      get \"/compression/pied_piper\" do\n        render_template(\"compression_results.html.eex\", [weissman_score: 5.2])\n      end\n\n      get \"/compression/nucleus\" do\n        render_template(\"compression_results.html.haml\", [weissman_score: 2.89])\n      end\n    end\n\n    # compression_results.html.eex\n    \u003chtml\u003e\u003cbody\u003ePied piper has a Weissman Score of \u003c%= @weissman_score %\u003e\u003c/body\u003e\u003c/html\u003e\n\n    # compression_results.html.haml\n    %html\n      %body Nucleaus has a Weissman Score of \u003c%= @weissman_score %\u003e\n```\n\n## Additional plugs\nThe plug/2 macro is available within a Trot router, allowing any plug to be inserted into the pipeline. Anything after `Trot.Router` will likely have a closed connection, so most uses cases will involve pulling in `Plug.Builder` first.\n\n### Example plug before Trot\n\n```Elixir\n    defmodule SoLoMoApp.Router do\n      use Plug.Builder\n      plug Plug.RequestId\n\n      use Trot.Router\n      get \"/hello\", do: \"hello\"\n    end\n```\n\n## API versioning\nAdding `use Trot.Versioning` to your module will enable API version parsing and pattern matching. The first part of the path for all requests in the module is assumed to be the version. It is parsed into the `conn[:assigns]` dictionary, making it easy to access. Routes can also be configured to only match a particular version.\n\n### Example versioned app\n\n```Elixir\n    defmodule Nucleus do\n      use Trot.Router\n      use Trot.Versioning\n\n      get \"/version\" do\n        conn.assigns[:version]\n      end\n\n      get \"/current\", version: \"v1\" do\n        :ok\n      end\n\n      get \"/current\" do\n        :bad_request\n      end\n    end\n```\n\nIn the above example, \"/v1/version\" will return \"v1\" as the response body. A request to \"/v1/current\" will return a 200 but \"/v2/current\" will return a 400.\n","funding_links":[],"categories":["Frameworks","Elixir"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexedpackets%2Ftrot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhexedpackets%2Ftrot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexedpackets%2Ftrot/lists"}