{"id":13634771,"url":"https://github.com/paulbellamy/mango","last_synced_at":"2025-04-07T07:18:47.474Z","repository":{"id":57496988,"uuid":"1797692","full_name":"paulbellamy/mango","owner":"paulbellamy","description":"Mango is a modular web-application framework for Go, inspired by Rack, and PEP333.","archived":false,"fork":false,"pushed_at":"2017-10-17T08:18:44.000Z","size":147,"stargazers_count":372,"open_issues_count":9,"forks_count":38,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-03-31T06:06:42.133Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://github.com/paulbellamy/mango","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/paulbellamy.png","metadata":{"files":{"readme":"README.markdown","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":"2011-05-25T07:26:46.000Z","updated_at":"2024-08-03T22:10:09.000Z","dependencies_parsed_at":"2022-09-03T03:33:47.314Z","dependency_job_id":null,"html_url":"https://github.com/paulbellamy/mango","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulbellamy%2Fmango","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulbellamy%2Fmango/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulbellamy%2Fmango/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paulbellamy%2Fmango/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paulbellamy","download_url":"https://codeload.github.com/paulbellamy/mango/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247608160,"owners_count":20965953,"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":[],"created_at":"2024-08-02T00:00:33.665Z","updated_at":"2025-04-07T07:18:47.436Z","avatar_url":"https://github.com/paulbellamy.png","language":"Go","funding_links":[],"categories":["Web Frameworks","Food","Web框架","Utility","web框架","web框架`web 框架`"],"sub_categories":["HTTP Clients","交流","Utility/Miscellaneous","Advanced Console UIs","实用程序/Miscellaneous","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","版本控制","Fail injection","版本控制`版本控制相关库`"],"readme":"# Mango\n\nMango is a modular web-application framework for Go, inspired by [Rack](http://github.com/rack/rack) and [PEP333](http://www.python.org/dev/peps/pep-0333/).\n\n*Note: Not actively maintained.*\n\n## Overview\n\nMango is most of all a framework for other modules, and apps.  It takes a list of middleware, and an application and compiles them into a single http server object. The middleware and apps are written in a functional style, which keeps everything very self-contained.\n\nMango aims to make building reusable modules of HTTP functionality as easy as possible by enforcing a simple and unified API for web frameworks, web apps, middleware.\n\n## API\n\nAs in Rack, the API is very minimal.\n\nApplications are of the form:\n\n```go\nfunc Hello(env mango.Env) (mango.Status, mango.Headers, mango.Body) {\n  return 200, mango.Headers{}, mango.Body(\"Hello World!\")\n}\n```\n\nWhere:\n\n* mango.Env is a map[string]interface{} of the environment\n  * It also has accessors for several other environment attributes:\n    * mango.Env.Request() is the http.Request object\n    * mango.Env.Session() is the map[string]interface for the session (only if using the Sessions middleware)\n    * mango.Env.Logger() is the default logger for the app (or your custom logger if using the Logger middleware)\n* mango.Status is an integer for the HTTP status code for the response\n* mango.Headers is a map[string][]string of the response headers (similar to http.Header)\n* mango.Body is a string for the response body\n\n## Installation\n\n   $ go install github.com/paulbellamy/mango\n\n\n## Available Modules\n\n* Sessions\n\n  Usage: `mango.Sessions(app_secret, cookie_name, cookie_domain string)`\n\n  Basic session management. Provides a mango.Env.Session() helper which returns a map[string]interface{} representing the session.  Any data stored in here will be serialized into the response session cookie.\n  \n* Logger\n\n  Usage: `mango.Logger(custom_logger \\*log.Logger)`\n\n  Provides a way to set a custom log.Logger object for the app. If this middleware is not provided Mango will set up a default logger to os.Stdout for the app to log to.\n\n* ShowErrors\n\n  Usage: `mango.ShowErrors(templateString string)`\n\n  Catch any panics thrown from the app, and display them in an HTML template. If templateString is \"\", a default template is used. Not recommended to use the default template in production as it could provide information helpful to attackers.\n\n* Routing\n\n  Usage: `mango.Routing(routes map[string]App)`\n\n  \"routes\" is of the form { \"/path1(.\\*)\": sub-stack1, \"/path2(.\\*)\": sub-stack2 }.  It lets us route different requests to different mango sub-stacks based on regexing the path.\n\n* Static\n\n  Usage: `mango.Static(directory string)`\n\n  Serves static files from the directory provided.\n\n* JSONP\n\n  Usage: `mango.JSONP`\n\n  Provides JSONP support. If a request has a 'callback' parameter, and your application responds with a Content-Type of \"application/json\", the JSONP middleware will wrap the response in the callback function and set the Content-Type to \"application/javascript\".\n\n* Basic Auth\n\n  Usage: mango.BasicAuth(auth func(username string, password string, Request, error) bool, failure func(Env) (Status, Headers, Body))\n\n  Performs HTTP Basic Auth. The auth function returns true if the username and password are accepted. If failure is nil, a default failure page will be used.\n\n## Example App\n\n```go\npackage main\n\nimport (\n  \"github.com/paulbellamy/mango\"\n)\n\nfunc Hello(env mango.Env) (mango.Status, mango.Headers, mango.Body) {\n  env.Logger().Println(\"Got a\", env.Request().Method, \"request for\", env.Request().RequestURI)\n  return 200, mango.Headers{}, mango.Body(\"Hello World!\")\n}\n\nfunc main() {\n  stack := new(mango.Stack)\n  stack.Address = \":3000\"\n  stack.Middleware(mango.ShowErrors(\"\"))\n  stack.Run(Hello)\n}\n```\n\n## Mango Stacks\n\nMango revolves around the idea of a \"stack\", which is a collection of middleware and an application.  Stacks can be compiled without being run.  When you compile a stack it returns a Mango App which incorporates all of the middleware and the application.  We can compile a Mango stack like:\n\n```go\nstack := new(mango.Stack)\nvar compiled mango.App = stack.Compile(Hello)\n```\n\nThis compiled stack can be passed to the Routing middleware as a \"sub-stack\".\n\nStack can also be compiled into an http.HandlerFunc by calling:\n\n```go\nstack := new(mango.Stack)\nvar listener http.HandlerFunc = stack.HandlerFunc(Hello)\n```\n\nThis returns a http.HandlerFunc ready to be passed to http.ListenAndServe, which incorporates the entire Mango stack.\n\n## Custom Middleware\n\nBuilding middleware for Mango is fairly straightforward.\n\nIf you build some middleware and think others might find it useful, please let me know so I can include it in the core Mango source.  The success of Mango really depends on having excellent middleware packages.\n\nAn extremely basic middleware package is simply a function:\n\n```go\nfunc SilenceErrors(env mango.Env, app mango.App) (mango.Status, mango.Headers, mango.Body) {\n  // Call our upstream app\n  status, headers, body := app(env)\n\n  // If we got an error\n  if status == 500 {\n    // Silence it!\n    status = 200\n    headers = mango.Headers{}\n    body = \"Silence is golden!\"\n  }\n\n  // Pass the response back to the client\n  return status, headers, body\n}\n```\n\nTo use this middleware we would do:\n\n```go\nfunc main() {\n  stack := new(mango.Stack)\n  stack.Address = \":3000\"\n\n  stack.Middleware(SilenceErrors) // Include our custom middleware\n\n  stack.Run(Hello)\n}\n```\n\nFor more complex middleware we may want to pass it configuration parameters. An example middleware package is one which will replace any image tags with funny pictures of cats:\n\n```go\nfunc Cats(cat_images []string) mango.Middleware {\n  // Initial setup stuff here\n  // Done on application setup\n\n  // Initialize our regex for finding image links\n  regex := regexp.MustCompile(\"[^\\\"']+(.jpg|.png|.gif)\")\n\n  // This is our middleware's request handler\n  return func(env mango.Env, app mango.App) (mango.Status, mango.Headers, mango.Body) {\n    // Call the upstream application\n    status, headers, body := app(env)\n\n    // Pick a random cat image\n    image_url := cat_images[rand.Int()%len(cat_images)]\n\n    // Substitute in our cat picture\n    body = mango.Body(regex.ReplaceAllString(string(body), image_url))\n\n    // Send the modified response onwards\n    return status, headers, body\n  }\n}\n```\n\nThis works by building a closure (function) based on the parameters we pass, and returning it as the middleware. Through the magic of closures, the value we pass for cat_images gets built into the function returned.\n\nTo use our middleware we would do:\n\n```go\nfunc main() {\n\n  stack := new(mango.Stack)\n  stack.Address = \":3000\"\n\n  // Initialize our cats middleware with our list of cat_images\n  cat_images := []string{\"ceiling_cat.jpg\", \"itteh_bitteh_kittehs.jpg\", \"monorail_cat.jpg\"}\n  cats_middleware := Cats(cat_images)\n\n  stack.Middleware(cats_middleware) // Include the Cats middleware in our stack\n\n  stack.Run(Hello)\n}\n```\n\n## Routing example\n\nThe following example routes \"/hello\" traffic to the hello handler and\n\"/bye\" traffic to the bye handler, any other traffic goes to\nrouteNotFound handler returning a 404.\n\n```go\npackage main\n\nimport(\n  \"github.com/paulbellamy/mango\"\n  \"fmt\"\n)\n\nfunc hello(env mango.Env) (mango.Status, mango.Headers, mango.Body) {\n  env.Logger().Println(\"Got a\", env.Request().Method, \"request for\", env.Request().RequestURI)\n  return 200, mango.Headers{}, mango.Body(\"Hello World!\")\n}\n\nfunc bye(env mango.Env) (mango.Status, mango.Headers, mango.Body) {\n  return 200, mango.Headers{}, mango.Body(\"Bye Bye!\")\n}\n\nfunc routeNotFound(env mango.Env) (mango.Status, mango.Headers, mango.Body) {\n  return 404, mango.Headers{}, mango.Body(\"You probably got lost :(\")\n}\n\nfunc main() {\n  routes := make(map[string]mango.App)\n  routes[\"/hello\"] = new(mango.Stack).Compile(hello)\n  routes[\"/bye\"] = new(mango.Stack).Compile(bye)\n\n  testServer := new(mango.Stack)\n  testServer.Middleware(mango.ShowErrors(\"\u003chtml\u003e\u003cbody\u003e{Error|html}\u003c/body\u003e\u003c/html\u003e\"), mango.Routing(routes))\n  testServer.Address = \"localhost:3000\"\n  testServer.Run(routeNotFound)\n  fmt.Printf(\"Running server on: %s\\n\", testServer.Address)\n}\n```\n\n## About\n\nMango was written by [Paul Bellamy](http://paulbellamy.com). \n\nFollow me on [Twitter](http://www.twitter.com/pyrhho)!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulbellamy%2Fmango","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaulbellamy%2Fmango","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaulbellamy%2Fmango/lists"}