[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-4993":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":17,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":21,"hasPages":21,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":16,"starSnapshotCount":16,"syncStatus":27,"lastSyncTime":28,"discoverSource":29},4993,"martini","go-martini\u002Fmartini","go-martini","Classy web framework for Go","martini.codegangsta.io",null,"Go",11605,1090,496,15,0,1,3,69.91,"MIT License",false,"master",[],"2026-06-12 04:00:24","# Martini  [![wercker status](https:\u002F\u002Fapp.wercker.com\u002Fstatus\u002F9b7dbc6e2654b604cd694d191c3d5487\u002Fs\u002Fmaster \"wercker status\")](https:\u002F\u002Fapp.wercker.com\u002Fproject\u002Fbykey\u002F9b7dbc6e2654b604cd694d191c3d5487)[![GoDoc](https:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini?status.png)](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini)\n\n### **NOTE:** The martini framework is no longer maintained.\n\nMartini is a powerful package for quickly writing modular web applications\u002Fservices in Golang.\n\nLanguage Translations:\n* [繁體中文](translations\u002FREADME_zh_tw.md)\n* [简体中文](translations\u002FREADME_zh_cn.md)\n* [Português Brasileiro (pt_BR)](translations\u002FREADME_pt_br.md)\n* [Español](translations\u002FREADME_es_ES.md)\n* [한국어 번역](translations\u002FREADME_ko_kr.md)\n* [Русский](translations\u002FREADME_ru_RU.md)\n* [日本語](translations\u002FREADME_ja_JP.md)\n* [French](translations\u002FREADME_fr_FR.md)\n* [Turkish](translations\u002FREADME_tr_TR.md)\n* [German](translations\u002FREADME_de_DE.md)\n* [Polski](translations\u002FREADME_pl_PL.md)\n\n## Getting Started\n\nAfter installing Go and setting up your [GOPATH](http:\u002F\u002Fgolang.org\u002Fdoc\u002Fcode.html#GOPATH), create your first `.go` file. We'll call it `server.go`.\n\n~~~ go\npackage main\n\nimport \"github.com\u002Fgo-martini\u002Fmartini\"\n\nfunc main() {\n  m := martini.Classic()\n  m.Get(\"\u002F\", func() string {\n    return \"Hello world!\"\n  })\n  m.Run()\n}\n~~~\n\nThen install the Martini package (**go 1.1** or greater is required):\n~~~\ngo get github.com\u002Fgo-martini\u002Fmartini\n~~~\n\nThen run your server:\n~~~\ngo run server.go\n~~~\n\nYou will now have a Martini webserver running on `localhost:3000`.\n\n## Getting Help\n\nJoin the [Mailing list](https:\u002F\u002Fgroups.google.com\u002Fforum\u002F#!forum\u002Fmartini-go)\n\nWatch the [Demo Video](http:\u002F\u002Fmartini.codegangsta.io\u002F#demo)\n\nAsk questions on Stackoverflow using the [martini tag](http:\u002F\u002Fstackoverflow.com\u002Fquestions\u002Ftagged\u002Fmartini)\n\nGoDoc [documentation](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini)\n\n\n## Features\n* Extremely simple to use.\n* Non-intrusive design.\n* Plays nice with other Golang packages.\n* Awesome path matching and routing.\n* Modular design - Easy to add functionality, easy to rip stuff out.\n* Lots of good handlers\u002Fmiddlewares to use.\n* Great 'out of the box' feature set.\n* **Fully compatible with the [http.HandlerFunc](http:\u002F\u002Fgodoc.org\u002Fnet\u002Fhttp#HandlerFunc) interface.**\n* Default document serving (e.g., for serving AngularJS apps in HTML5 mode).\n\n## More Middleware\nFor more middleware and functionality, check out the repositories in the  [martini-contrib](https:\u002F\u002Fgithub.com\u002Fmartini-contrib) organization.\n\n## Table of Contents\n* [Classic Martini](#classic-martini)\n  * [Handlers](#handlers)\n  * [Routing](#routing)\n  * [Services](#services)\n  * [Serving Static Files](#serving-static-files)\n* [Middleware Handlers](#middleware-handlers)\n  * [Next()](#next)\n* [Martini Env](#martini-env)\n* [FAQ](#faq)\n\n## Classic Martini\nTo get up and running quickly, [martini.Classic()](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Classic) provides some reasonable defaults that work well for most web applications:\n~~~ go\n  m := martini.Classic()\n  \u002F\u002F ... middleware and routing goes here\n  m.Run()\n~~~\n\nBelow is some of the functionality [martini.Classic()](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Classic) pulls in automatically:\n  * Request\u002FResponse Logging - [martini.Logger](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Logger)\n  * Panic Recovery - [martini.Recovery](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Recovery)\n  * Static File serving - [martini.Static](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Static)\n  * Routing - [martini.Router](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Router)\n\n### Handlers\nHandlers are the heart and soul of Martini. A handler is basically any kind of callable function:\n~~~ go\nm.Get(\"\u002F\", func() {\n  println(\"hello world\")\n})\n~~~\n\n#### Return Values\nIf a handler returns something, Martini will write the result to the current [http.ResponseWriter](http:\u002F\u002Fgodoc.org\u002Fnet\u002Fhttp#ResponseWriter) as a string:\n~~~ go\nm.Get(\"\u002F\", func() string {\n  return \"hello world\" \u002F\u002F HTTP 200 : \"hello world\"\n})\n~~~\n\nYou can also optionally return a status code:\n~~~ go\nm.Get(\"\u002F\", func() (int, string) {\n  return 418, \"i'm a teapot\" \u002F\u002F HTTP 418 : \"i'm a teapot\"\n})\n~~~\n\n#### Service Injection\nHandlers are invoked via reflection. Martini makes use of *Dependency Injection* to resolve dependencies in a Handlers argument list. **This makes Martini completely  compatible with golang's `http.HandlerFunc` interface.**\n\nIf you add an argument to your Handler, Martini will search its list of services and attempt to resolve the dependency via type assertion:\n~~~ go\nm.Get(\"\u002F\", func(res http.ResponseWriter, req *http.Request) { \u002F\u002F res and req are injected by Martini\n  res.WriteHeader(200) \u002F\u002F HTTP 200\n})\n~~~\n\nThe following services are included with [martini.Classic()](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Classic):\n  * [*log.Logger](http:\u002F\u002Fgodoc.org\u002Flog#Logger) - Global logger for Martini.\n  * [martini.Context](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Context) - http request context.\n  * [martini.Params](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Params) - `map[string]string` of named params found by route matching.\n  * [martini.Routes](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Routes) - Route helper service.\n  * [martini.Route](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Route) - Current active route.\n  * [http.ResponseWriter](http:\u002F\u002Fgodoc.org\u002Fnet\u002Fhttp\u002F#ResponseWriter) - http Response writer interface.\n  * [*http.Request](http:\u002F\u002Fgodoc.org\u002Fnet\u002Fhttp\u002F#Request) - http Request.\n\n### Routing\nIn Martini, a route is an HTTP method paired with a URL-matching pattern.\nEach route can take one or more handler methods:\n~~~ go\nm.Get(\"\u002F\", func() {\n  \u002F\u002F show something\n})\n\nm.Patch(\"\u002F\", func() {\n  \u002F\u002F update something\n})\n\nm.Post(\"\u002F\", func() {\n  \u002F\u002F create something\n})\n\nm.Put(\"\u002F\", func() {\n  \u002F\u002F replace something\n})\n\nm.Delete(\"\u002F\", func() {\n  \u002F\u002F destroy something\n})\n\nm.Options(\"\u002F\", func() {\n  \u002F\u002F http options\n})\n\nm.NotFound(func() {\n  \u002F\u002F handle 404\n})\n~~~\n\nRoutes are matched in the order they are defined. The first route that\nmatches the request is invoked.\n\nRoute patterns may include named parameters, accessible via the [martini.Params](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Params) service:\n~~~ go\nm.Get(\"\u002Fhello\u002F:name\", func(params martini.Params) string {\n  return \"Hello \" + params[\"name\"]\n})\n~~~\n\nRoutes can be matched with globs:\n~~~ go\nm.Get(\"\u002Fhello\u002F**\", func(params martini.Params) string {\n  return \"Hello \" + params[\"_1\"]\n})\n~~~\n\nRegular expressions can be used as well:\n~~~go\nm.Get(\"\u002Fhello\u002F(?P\u003Cname>[a-zA-Z]+)\", func(params martini.Params) string {\n  return fmt.Sprintf (\"Hello %s\", params[\"name\"])\n})\n~~~\nTake a look at the [Go documentation](http:\u002F\u002Fgolang.org\u002Fpkg\u002Fregexp\u002Fsyntax\u002F) for more info about regular expressions syntax .\n\nRoute handlers can be stacked on top of each other, which is useful for things like authentication and authorization:\n~~~ go\nm.Get(\"\u002Fsecret\", authorize, func() {\n  \u002F\u002F this will execute as long as authorize doesn't write a response\n})\n~~~\n\nRoute groups can be added too using the Group method.\n~~~ go\nm.Group(\"\u002Fbooks\", func(r martini.Router) {\n    r.Get(\"\u002F:id\", GetBooks)\n    r.Post(\"\u002Fnew\", NewBook)\n    r.Put(\"\u002Fupdate\u002F:id\", UpdateBook)\n    r.Delete(\"\u002Fdelete\u002F:id\", DeleteBook)\n})\n~~~\n\nJust like you can pass middlewares to a handler you can pass middlewares to groups.\n~~~ go\nm.Group(\"\u002Fbooks\", func(r martini.Router) {\n    r.Get(\"\u002F:id\", GetBooks)\n    r.Post(\"\u002Fnew\", NewBook)\n    r.Put(\"\u002Fupdate\u002F:id\", UpdateBook)\n    r.Delete(\"\u002Fdelete\u002F:id\", DeleteBook)\n}, MyMiddleware1, MyMiddleware2)\n~~~\n\n### Services\nServices are objects that are available to be injected into a Handler's argument list. You can map a service on a *Global* or *Request* level.\n\n#### Global Mapping\nA Martini instance implements the inject.Injector interface, so mapping a service is easy:\n~~~ go\ndb := &MyDatabase{}\nm := martini.Classic()\nm.Map(db) \u002F\u002F the service will be available to all handlers as *MyDatabase\n\u002F\u002F ...\nm.Run()\n~~~\n\n#### Request-Level Mapping\nMapping on the request level can be done in a handler via [martini.Context](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Context):\n~~~ go\nfunc MyCustomLoggerHandler(c martini.Context, req *http.Request) {\n  logger := &MyCustomLogger{req}\n  c.Map(logger) \u002F\u002F mapped as *MyCustomLogger\n}\n~~~\n\n#### Mapping values to Interfaces\nOne of the most powerful parts about services is the ability to map a service to an interface. For instance, if you wanted to override the [http.ResponseWriter](http:\u002F\u002Fgodoc.org\u002Fnet\u002Fhttp#ResponseWriter) with an object that wrapped it and performed extra operations, you can write the following handler:\n~~~ go\nfunc WrapResponseWriter(res http.ResponseWriter, c martini.Context) {\n  rw := NewSpecialResponseWriter(res)\n  c.MapTo(rw, (*http.ResponseWriter)(nil)) \u002F\u002F override ResponseWriter with our wrapper ResponseWriter\n}\n~~~\n\n### Serving Static Files\nA [martini.Classic()](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Classic) instance automatically serves static files from the \"public\" directory in the root of your server.\nYou can serve from more directories by adding more [martini.Static](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Static) handlers.\n~~~ go\nm.Use(martini.Static(\"assets\")) \u002F\u002F serve from the \"assets\" directory as well\n~~~\n\n#### Serving a Default Document\nYou can specify the URL of a local file to serve when the requested URL is not\nfound. You can also specify an exclusion prefix so that certain URLs are ignored.\nThis is useful for servers that serve both static files and have additional\nhandlers defined (e.g., REST API). When doing so, it's useful to define the\nstatic handler as a part of the NotFound chain.\n\nThe following example serves the `\u002Findex.html` file whenever any URL is\nrequested that does not match any local file and does not start with `\u002Fapi\u002Fv`:\n~~~ go\nstatic := martini.Static(\"assets\", martini.StaticOptions{Fallback: \"\u002Findex.html\", Exclude: \"\u002Fapi\u002Fv\"})\nm.NotFound(static, http.NotFound)\n~~~\n\n## Middleware Handlers\nMiddleware Handlers sit between the incoming http request and the router. In essence they are no different than any other Handler in Martini. You can add a middleware handler to the stack like so:\n~~~ go\nm.Use(func() {\n  \u002F\u002F do some middleware stuff\n})\n~~~\n\nYou can have full control over the middleware stack with the `Handlers` function. This will replace any handlers that have been previously set:\n~~~ go\nm.Handlers(\n  Middleware1,\n  Middleware2,\n  Middleware3,\n)\n~~~\n\nMiddleware Handlers work really well for things like logging, authorization, authentication, sessions, gzipping, error pages and any other operations that must happen before or after an http request:\n~~~ go\n\u002F\u002F validate an api key\nm.Use(func(res http.ResponseWriter, req *http.Request) {\n  if req.Header.Get(\"X-API-KEY\") != \"secret123\" {\n    res.WriteHeader(http.StatusUnauthorized)\n  }\n})\n~~~\n\n### Next()\n[Context.Next()](http:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgo-martini\u002Fmartini#Context) is an optional function that Middleware Handlers can call to yield the until after the other Handlers have been executed. This works really well for any operations that must happen after an http request:\n~~~ go\n\u002F\u002F log before and after a request\nm.Use(func(c martini.Context, log *log.Logger){\n  log.Println(\"before a request\")\n\n  c.Next()\n\n  log.Println(\"after a request\")\n})\n~~~\n\n## Martini Env\n\nSome Martini handlers make use of the `martini.Env` global variable to provide special functionality for development environments vs production environments. It is recommended that the `MARTINI_ENV=production` environment variable to be set when deploying a Martini server into a production environment.\n\n## FAQ\n\n### Where do I find middleware X?\n\nStart by looking in the [martini-contrib](https:\u002F\u002Fgithub.com\u002Fmartini-contrib) projects. If it is not there feel free to contact a martini-contrib team member about adding a new repo to the organization.\n\n* [acceptlang](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Facceptlang) - Handler for parsing the `Accept-Language` HTTP header.\n* [accessflags](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Faccessflags) - Handler to enable Access Control.\n* [auth](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fauth) - Handlers for authentication.\n* [binding](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fbinding) - Handler for mapping\u002Fvalidating a raw request into a structure.\n* [cors](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fcors) - Handler that enables CORS support.\n* [csrf](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fcsrf) - CSRF protection for applications\n* [encoder](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fencoder) - Encoder service for rendering data in several formats and content negotiation.\n* [gzip](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fgzip) - Handler for adding gzip compress to requests\n* [gorelic](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fgorelic) - NewRelic middleware\n* [logstasher](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Flogstasher) - Middleware that prints logstash-compatible JSON \n* [method](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fmethod) - HTTP method overriding via Header or form fields.\n* [oauth2](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Foauth2) - Handler that provides OAuth 2.0 login for Martini apps. Google Sign-in, Facebook Connect and Github login is supported.\n* [permissions2](https:\u002F\u002Fgithub.com\u002Fxyproto\u002Fpermissions2) - Handler for keeping track of users, login states and permissions.\n* [render](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Frender) - Handler that provides a service for easily rendering JSON and HTML templates.\n* [secure](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fsecure) - Implements a few quick security wins.\n* [sessions](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fsessions) - Handler that provides a Session service.\n* [sessionauth](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fsessionauth) - Handler that provides a simple way to make routes require a login, and to handle user logins in the session\n* [strict](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fstrict) - Strict Mode \n* [strip](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fstrip) - URL Prefix stripping.\n* [staticbin](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fstaticbin) - Handler for serving static files from binary data\n* [throttle](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fthrottle) - Request rate throttling middleware.\n* [vauth](https:\u002F\u002Fgithub.com\u002Frafecolton\u002Fvauth) - Handlers for vender webhook authentication (currently GitHub and TravisCI)\n* [web](https:\u002F\u002Fgithub.com\u002Fmartini-contrib\u002Fweb) - hoisie web.go's Context\n\n### How do I integrate with existing servers?\n\nA Martini instance implements `http.Handler`, so it can easily be used to serve subtrees\non existing Go servers. For example this is a working Martini app for Google App Engine:\n\n~~~ go\npackage hello\n\nimport (\n  \"net\u002Fhttp\"\n  \"github.com\u002Fgo-martini\u002Fmartini\"\n)\n\nfunc init() {\n  m := martini.Classic()\n  m.Get(\"\u002F\", func() string {\n    return \"Hello world!\"\n  })\n  http.Handle(\"\u002F\", m)\n}\n~~~\n\n### How do I change the port\u002Fhost?\n\nMartini's `Run` function looks for the PORT and HOST environment variables and uses those. Otherwise Martini will default to localhost:3000.\nTo have more flexibility over port and host, use the `martini.RunOnAddr` function instead.\n\n~~~ go\n  m := martini.Classic()\n  \u002F\u002F ...\n  m.RunOnAddr(\":8080\")\n~~~\n\n### Live code reload?\n\n[gin](https:\u002F\u002Fgithub.com\u002Fcodegangsta\u002Fgin) and [fresh](https:\u002F\u002Fgithub.com\u002Fpilu\u002Ffresh) both live reload martini apps.\n\n## Contributing\nMartini is meant to be kept tiny and clean. Most contributions should end up in a repository in the [martini-contrib](https:\u002F\u002Fgithub.com\u002Fmartini-contrib) organization. If you do have a contribution for the core of Martini feel free to put up a Pull Request.\n\n## License\nMartini is distributed by The MIT License, see LICENSE\n\n## About\n\nInspired by [express](https:\u002F\u002Fgithub.com\u002Fvisionmedia\u002Fexpress) and [sinatra](https:\u002F\u002Fgithub.com\u002Fsinatra\u002Fsinatra)\n\nMartini is obsessively designed by none other than the [Code Gangsta](http:\u002F\u002Fcodegangsta.io\u002F)\n","Martini 是一个优雅的 Go 语言 Web 框架，用于快速构建模块化的 Web 应用程序和服务。其核心功能包括简洁易用的设计、强大的路径匹配与路由机制以及模块化特性，使得添加或移除功能变得简单快捷。此外，它还提供了丰富的中间件支持，并且完全兼容标准库中的 `http.HandlerFunc` 接口，便于与其他 Go 包集成。尽管 Martini 已不再维护，但它仍然适用于需要快速搭建原型或小型项目的场景，特别是那些希望利用 Go 语言高效并发处理能力来构建 Web 服务的情况。",2,"2026-06-11 03:01:58","top_language"]