{"id":13676553,"url":"https://github.com/celrenheit/lion","last_synced_at":"2025-09-19T09:10:05.109Z","repository":{"id":57481112,"uuid":"54291794","full_name":"celrenheit/lion","owner":"celrenheit","description":"Lion is a fast HTTP router for building modern scalable modular REST APIs in Go","archived":false,"fork":false,"pushed_at":"2019-11-15T10:27:03.000Z","size":771,"stargazers_count":741,"open_issues_count":2,"forks_count":31,"subscribers_count":28,"default_branch":"master","last_synced_at":"2025-08-13T17:43:21.051Z","etag":null,"topics":["fast","golang","handler","http","router","subdomain"],"latest_commit_sha":null,"homepage":"","language":"Go","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/celrenheit.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2016-03-19T23:30:47.000Z","updated_at":"2025-07-01T01:58:55.000Z","dependencies_parsed_at":"2022-09-26T17:50:38.412Z","dependency_job_id":null,"html_url":"https://github.com/celrenheit/lion","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/celrenheit/lion","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/celrenheit%2Flion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/celrenheit%2Flion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/celrenheit%2Flion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/celrenheit%2Flion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/celrenheit","download_url":"https://codeload.github.com/celrenheit/lion/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/celrenheit%2Flion/sbom","scorecard":{"id":270632,"data":{"date":"2025-08-11","repo":{"name":"github.com/celrenheit/lion","commit":"69ee5db2c99e558f257e3eec542861c27087ec0f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 1/29 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T13:15:24.799Z","repository_id":57481112,"created_at":"2025-08-17T13:15:24.799Z","updated_at":"2025-08-17T13:15:24.799Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275910645,"owners_count":25550818,"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","status":"online","status_checked_at":"2025-09-19T02:00:09.700Z","response_time":108,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["fast","golang","handler","http","router","subdomain"],"created_at":"2024-08-02T13:00:29.524Z","updated_at":"2025-09-19T09:10:05.021Z","avatar_url":"https://github.com/celrenheit.png","language":"Go","readme":"# Lion [![Build Status](https://img.shields.io/travis/celrenheit/lion.svg?style=flat-square)](https://travis-ci.org/celrenheit/lion) [![GoDoc](https://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](https://godoc.org/github.com/celrenheit/lion) [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE) [![Go Report Card](https://goreportcard.com/badge/github.com/celrenheit/lion?style=flat-square)](https://goreportcard.com/report/github.com/celrenheit/lion)\n\nLion is a [fast](#benchmarks) HTTP router for building modern scalable modular REST APIs written in Go (golang).\n\n## Features\n\n* **Go1-like guarantee**: The API will **not** change in Lion v2.x (once released).\n* **Modular**: You can define your own modules to easily build a scalable architecture\n* **RESTful**: You can define modules to groups http resources together.\n* **Subdomains**: Select which subdomains, hosts a router can match. You can specify it a param or a wildcard e.g. `*.example.org`. More infos [here](#match-hosts).\n* **Near zero garbage**: Lion generates near zero garbage[*](#benchmarks). The allocations generated comes from the net/http.Request.WithContext() works.\nIt makes a shallow copy of the request.\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n## Table of contents\n\n- [Install/Update](#installupdate)\n- [Hello World](#hello-world)\n- [Getting started with modules and resources](#getting-started-with-modules-and-resources)\n  - [Using net/http.Handler](#using-nethttphandler)\n  - [Using net/http.HandlerFunc](#using-nethttphandlerfunc)\n- [Middlewares](#middlewares)\n  - [Using Named Middlewares](#using-named-middlewares)\n  - [Using Third-Party Middlewares](#using-third-party-middlewares)\n    - [Negroni](#negroni)\n- [Matching Subdomains/Hosts](#matching-subdomainshosts)\n- [Resources](#resources)\n- [Examples](#examples)\n  - [Using GET, POST, PUT, DELETE http methods](#using-get-post-put-delete-http-methods)\n  - [Using middlewares](#using-middlewares)\n  - [Group routes by a base path](#group-routes-by-a-base-path)\n  - [Mounting a router into a base path](#mounting-a-router-into-a-base-path)\n  - [Default middlewares](#default-middlewares)\n  - [Custom Middlewares](#custom-middlewares)\n    - [Custom Logger example](#custom-logger-example)\n- [Benchmarks](#benchmarks)\n- [Contributing](#contributing)\n- [License](#license)\n- [Todo](#todo)\n- [Credits](#credits)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n\n## Install/Update\n\nLion requires Go 1.7+:\n\n```shell\n$ go get -u github.com/celrenheit/lion\n```\n\nNext versions of Lion will support the latest Go version and the previous one. \nFor example, when Go 1.8 is out, Lion will support Go 1.7 and Go 1.8.\n\n## Hello World\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/celrenheit/lion\"\n\t\"context\"\n)\n\nfunc Home(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintf(w, \"Home\")\n}\n\nfunc Hello(w http.ResponseWriter, r *http.Request) {\n\tname := lion.Param(r, \"name\")\n\tfmt.Fprintf(w, \"Hello %s!\",name)\n}\n\nfunc main() {\n\tl := lion.Classic()\n\tl.GetFunc(\"/\", Home)\n\tl.GetFunc(\"/hello/:name\", Hello)\n\tl.Run()\n}\n```\n\nTry it yourself by running the following command from the current directory:\n\n```shell\n$ go run examples/hello/hello.go\n```\n\n## Getting started with modules and resources\n\nWe are going to build a sample products listing REST api (without database handling to keep it simple):\n\n```go\n\nfunc main() {\n\tl := lion.Classic()\n\tapi := l.Group(\"/api\")\n\tapi.Module(Products{})\n\tl.Run()\n}\n\n// Products module is accessible at url: /api/products\n// It handles getting a list of products or creating a new product\ntype Products struct{}\n\nfunc (p Products) Base() string {\n\treturn \"/products\"\n}\n\nfunc (p Products) Get(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintf(w, \"Fetching all products\")\n}\n\nfunc (p Products) Post(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintf(w, \"Creating a new product\")\n}\n\nfunc (p Products) Routes(r *lion.Router) {\n\t// Defining a resource for getting, editing and deleting a single product\n\tr.Resource(\"/:id\", OneProduct{})\n}\n\n// OneProduct resource is accessible at url: /api/products/:id\n// It handles getting, editing and deleting a single product\ntype OneProduct struct{}\n\nfunc (p OneProduct) Get(w http.ResponseWriter, r *http.Request) {\n\tid := lion.Param(r, \"id\")\n\tfmt.Fprintf(w, \"Getting product: %s\", id)\n}\n\nfunc (p OneProduct) Put(w http.ResponseWriter, r *http.Request) {\n\tid := lion.Param(r, \"id\")\n\tfmt.Fprintf(w, \"Updating article: %s\", id)\n}\n\nfunc (p OneProduct) Delete(w http.ResponseWriter, r *http.Request) {\n\tid := lion.Param(r, \"id\")\n\tfmt.Fprintf(w, \"Deleting article: %s\", id)\n}\n```\n\nTry it yourself. Run:\n```shell\n$ go run examples/modular-hello/modular-hello.go\n```\n\nOpen your web browser to [http://localhost:3000/api/products](http://localhost:3000/api/products) or [http://localhost:3000/api/products/123](http://localhost:3000/api/products/123). You should see \"_Fetching all products_\" or \"_Getting product: 123_\".\n\n\n### Using net/http.Handler\n\nHandlers should implement the native net/http.Handler:\n\n```go\nl.Get(\"/get\", get)\nl.Post(\"/post\", post)\nl.Put(\"/put\", put)\nl.Delete(\"/delete\", delete)\n```\n\n### Using net/http.HandlerFunc\n\nYou can use native net/http.Handler (`func(w http.ResponseWriter, r *http.Request)`):\n\n```go\nfunc myHandlerFunc(w http.ResponseWriter, r *http.Request)  {\n  fmt.Fprintf(w, \"Hi!\")\n}\n\nl.GetFunc(\"/get\", myHandlerFunc)\nl.PostFunc(\"/post\", myHandlerFunc)\nl.PutFunc(\"/put\", myHandlerFunc)\nl.DeleteFunc(\"/delete\", myHandlerFunc)\n```\n\n## Middlewares\n\nMiddlewares should implement the Middleware interface:\n\n```go\ntype Middleware interface {\n\tServeNext(http.Handler) http.Handler\n}\n```\n\nThe ServeNext function accepts a http.Handler and returns a http.Handler.\n\nYou can also use MiddlewareFuncs which are basically just `func(http.Handler) http.Handler` \n\nFor example:\n\n```go\nfunc middlewareFunc(next Handler) Handler  {\n\treturn next\n}\n```\n\n### Using Named Middlewares\n\nNamed middlewares are designed to be able to reuse a previously defined middleware. For example, if you have a EnsureAuthenticated middleware that check whether a user is logged in.\nYou can define it once and reuse later in your application.\n\n```go\nl := lion.New()\nl.Define(\"EnsureAuthenticated\", NewEnsureAuthenticatedMiddleware())\n```\n\nTo reuse it later in your application, you can use the `UseNamed` method. \nIf it cannot find the named middleware if the current Router instance it will try to find it in the parent router.\nIf a named middleware is not found it will panic.\n\n```go\napi := l.Group(\"/api\")\napi.UseNamed(\"EnsureAuthenticated\")\n```\n\n### Using Third-Party Middlewares\n\n#### Negroni \n\nIn v1, negroni was supported directly using UseNegroni.\nIt still works but you will have to use .UseNext and pass it a [negroni.HandlerFunc](https://godoc.org/github.com/urfave/negroni#HandlerFunc): \n`func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)`\n\nThis way if you prefer to use this kind of middleware, you can.\n\nYou can use [Negroni](https://github.com/codegangsta/negroni) middlewares\nyou can find a list of third party middlewares [here](https://github.com/codegangsta/negroni#third-party-middleware)\n\n```go\nl := lion.New()\nl.UseNext(negroni.NewRecovery().ServeHTTP)\nl.Run()\n```\n\n## Matching Subdomains/Hosts\n\nYou can match a specific or multiple hosts. You can use patterns in the same way they are currently used for routes with only some [edge cases](https://godoc.org/github.com/celrenheit/lion#Router.Host).\nThe main difference is that you will have to use the '**$**' character instead of '**:**' to define a parameter.\n\n\nadmin.example.com\t\t\twill match\t\t\tadmin.example.com\n$username.blog.com\t\t\twill match\t\t\tmessi.blog.com\n\t\t\t\t\twill not match\t\t\tmy.awesome.blog.com\n*.example.com\t\t\t\twill match\t\t\tmy.admin.example.com\n\n```go\nl := New()\n\n// Group by /api basepath\napi := l.Group(\"/api\")\n\n// Specific to v1\nv1 := api.Subrouter().\n\tHost(\"v1.example.org\")\n\nv1.Get(\"/\", v1Handler)\n\n// Specific to v2\nv2 := api.Subrouter().\n\tHost(\"v2.example.org\")\n\nv2.Get(\"/\", v2Handler)\nl.Run()\n```\n\n## Resources\n\nYou can define a resource to represent a REST, CRUD api resource.\nYou define global middlewares using Uses() method. For defining custom middlewares for each http method, you have to create a function which name is composed of the http method suffixed by \"Middlewares\". For example, if you want to define middlewares for the Get method you will have to create a method called: **GetMiddlewares()**.\n\nA resource is defined by the following methods. **Everything is optional**:\n```go\n\n// Global middlewares for the resource (Optional)\nUses() Middlewares\n\n// Middlewares for the http methods (Optional)\nGetMiddlewares() Middlewares\nPostMiddlewares() Middlewares\nPutMiddlewares() Middlewares\nDeleteMiddlewares() Middlewares\n\n\n// HandlerFuncs for each HTTP Methods (Optional)\nGet(w http.ResponseWriter, r *http.Request)\nPost(w http.ResponseWriter, r *http.Request)\nPut(w http.ResponseWriter, r *http.Request)\nDelete(w http.ResponseWriter, r *http.Request)\n```\n\n**_Example_**:\n\n```go\npackage main\n\ntype todolist struct{}\n\nfunc (t todolist) Uses() lion.Middlewares {\n\treturn lion.Middlewares{lion.NewLogger()}\n}\n\nfunc (t todolist) Get(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintf(w, \"getting todos\")\n}\n\nfunc main() {\n\tl := lion.New()\n\tl.Resource(\"/todos\", todolist{})\n\tl.Run()\n}\n```\n\n\n## Modules\n\nModules are a way to modularize an api which can then define submodules, subresources and custom routes.\nA module is defined by the following methods:\n\n```go\n// Required: Base url pattern of the module\nBase() string\n\n// Routes accepts a Router instance. This method is used to define the routes of this module.\n// Each routes defined are relative to the Base() url pattern\nRoutes(*Router)\n\n// Optional: Requires named middlewares. Refer to Named Middlewares section\nRequires() []string\n```\n\n```go\npackage main\n\ntype api struct{}\n\n// Required: Base url\nfunc (t api) Base() string { return \"/api\" }\n\n// Required: Here you can declare sub-resources, submodules and custom routes.\nfunc (t api) Routes(r *lion.Router) {\n\tr.Module(v1{})\n\tr.Get(\"/custom\", t.CustomRoute)\n}\n\n// Optional: Attach Get method to this Module.\n// ====\u003e A Module is also a Resource.\nfunc (t api) Get(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintf(w, \"This also a resource accessible at http://localhost:3000/api\")\n}\n\n// Optional: Defining custom routes\nfunc (t api) CustomRoute(w http.ResponseWriter, r *http.Request) {\n\tfmt.Fprintf(w, \"This a custom route for this module http://localhost:3000/api/\")\n}\n\nfunc main() {\n\tl := lion.New()\n\t// Registering the module\n\tl.Module(api{})\n\tl.Run()\n}\n```\n\n## Examples\n\n### Using GET, POST, PUT, DELETE http methods\n\n```go\nl := lion.Classic()\n\n// Using Handlers\nl.Get(\"/get\", get)\nl.Post(\"/post\", post)\nl.Put(\"/put\", put)\nl.Delete(\"/delete\", delete)\n\n// Using functions\nl.GetFunc(\"/get\", getFunc)\nl.PostFunc(\"/post\", postFunc)\nl.PutFunc(\"/put\", putFunc)\nl.DeleteFunc(\"/delete\", deleteFunc)\n\nl.Run()\n```\n\n### Using middlewares\n\n```go\nfunc main() {\n\tl := lion.Classic()\n\n\t// Using middleware\n\tl.Use(lion.NewLogger())\n\n\t// Using middleware functions\n\tl.UseFunc(someMiddlewareFunc)\n\n\tl.GetFunc(\"/hello/:name\", Hello)\n\n\tl.Run()\n}\n```\n\n\n### Group routes by a base path\n\n```go\nl := lion.Classic()\napi := l.Group(\"/api\")\n\nv1 := l.Group(\"/v1\")\nv1.GetFunc(\"/somepath\", gettingFromV1)\n\nv2 := l.Group(\"/v2\")\nv2.GetFunc(\"/somepath\", gettingFromV2)\n\nl.Run()\n```\n\n### Mounting a router into a base path\n\n\n```go\nl := lion.Classic()\n\nsub := lion.New()\nsub.GetFunc(\"/somepath\", getting)\n\n\nl.Mount(\"/api\", sub)\n```\n\n### Default middlewares\n\n`lion.Classic()` creates a router with default middlewares (Recovery, RealIP, Logger, Static).\nIf you wish to create a blank router without any middlewares you can use `lion.New()`.\n\n```go\nfunc main()  {\n\t// This a no middlewares registered\n\tl := lion.New()\n\tl.Use(lion.NewLogger())\n\n\tl.GetFunc(\"/hello/:name\", Hello)\n\n\tl.Run()\n}\n```\n\n### Custom Middlewares\n\nCustom middlewares should implement the Middleware interface:\n\n```go\ntype Middleware interface {\n\tServeNext(Handler) Handler\n}\n```\n\nYou can also make MiddlewareFuncs to use using `.UseFunc()` method.\nIt has to accept a Handler and return a Handler:\n```go\nfunc(next Handler) Handler\n```\n\n\n#### Custom Logger example\n\n```go\ntype logger struct{}\n\nfunc (*logger) ServeNext(next lion.Handler) lion.Handler {\n\treturn lion.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tstart := time.Now()\n\n\t\tnext.ServeHTTPC(c, w, r)\n\n\t\tfmt.Printf(\"Served %s in %s\\n\", r.URL.Path, time.Since(start))\n\t})\n}\n```\n\nThen in the main function you can use the middleware using:\n\n```go\nl := lion.New()\n\nl.Use(\u0026logger{})\nl.GetFunc(\"/hello/:name\", Hello)\nl.Run()\n```\n\n## Benchmarks\n\nTODO: Update this when v2 is released.\n\n## Contributing\n\nWant to contribute to Lion ? Awesome! Feel free to submit an issue or a pull request.\n\nHere are some ways you can help:\n* Report bugs\n* Share a middleware or a module\n* Improve code/documentation\n* Propose new features\n* and more...\n\n## License\n\nThe project is licensed under the MIT license available here: https://github.com/celrenheit/lion/blob/master/LICENSE.\n\nThe benchmarks present in _bench\\_test.go_ is licensed under a BSD-style license available here: https://github.com/julienschmidt/go-http-routing-benchmark/blob/master/LICENSE.\n\n## Todo\n\n* [x] Support for Go 1.7 context\n* [x] Host matching\n* [x] Automatic OPTIONS handler\n* [ ] Modules\n  * [ ] JWT Auth module\n* [x] Better static file handling\n* [ ] More documentation\n\n## Credits\n\nLion v1 was inspired by [pressly/chi](https://github.com/pressly/chi). \nIf Lion is not the right http router for you, check out chi.\n\nParts of Lion taken for other projects:\n* [Negroni](https://github.com/codegangsta/negroni)\n\t* Static and Recovery middlewares are taken from Negroni\n* [Goji](https://github.com/zenazn/goji/)\n\t* RealIP middleware is taken from goji\n* [Gin](https://github.com/gin-gonic/gin)\n\t* ResponseWriter and Logger inspiration are inspired by gin\n","funding_links":[],"categories":["Multiplexers","Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcelrenheit%2Flion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcelrenheit%2Flion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcelrenheit%2Flion/lists"}