{"id":13764105,"url":"https://github.com/yarf-framework/yarf","last_synced_at":"2025-05-10T17:31:35.548Z","repository":{"id":57487526,"uuid":"41804101","full_name":"yarf-framework/yarf","owner":"yarf-framework","description":"Yet Another REST Framework","archived":false,"fork":false,"pushed_at":"2019-03-07T20:28:46.000Z","size":139,"stargazers_count":68,"open_issues_count":2,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-16T23:32:36.250Z","etag":null,"topics":["api","framework","go","golang","micro-framework","rest","yarf"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yarf-framework.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-02T13:56:47.000Z","updated_at":"2024-11-11T17:06:47.000Z","dependencies_parsed_at":"2022-09-02T00:10:40.457Z","dependency_job_id":null,"html_url":"https://github.com/yarf-framework/yarf","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/yarf-framework%2Fyarf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yarf-framework%2Fyarf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yarf-framework%2Fyarf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yarf-framework%2Fyarf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yarf-framework","download_url":"https://codeload.github.com/yarf-framework/yarf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253453334,"owners_count":21911080,"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":["api","framework","go","golang","micro-framework","rest","yarf"],"created_at":"2024-08-03T15:01:13.972Z","updated_at":"2025-05-10T17:31:35.189Z","avatar_url":"https://github.com/yarf-framework.png","language":"Go","readme":"[![GoDoc](https://godoc.org/github.com/yarf-framework/yarf?status.svg)](https://godoc.org/github.com/yarf-framework/yarf)\n[![Version](https://badge.fury.io/gh/yarf-framework%2Fyarf.svg)](https://badge.fury.io/gh/yarf-framework%2Fyarf)\n[![Build Status](https://travis-ci.org/yarf-framework/yarf.svg?branch=master)](https://travis-ci.org/yarf-framework/yarf)\n[![Coverage Status](https://coveralls.io/repos/github/yarf-framework/yarf/badge.svg?branch=master)](https://coveralls.io/github/yarf-framework/yarf?branch=master)\n[![Go Report Card](https://goreportcard.com/badge/github.com/yarf-framework/yarf)](https://goreportcard.com/report/github.com/yarf-framework/yarf)\n[![Join the chat at https://gitter.im/jinzhu/gorm](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/yarf-framework/yarf) \n\n\n# YARF: Yet Another REST Framework\n\nYARF is a fast micro-framework designed to build REST APIs and web services in a fast and simple way. \nDesigned after Go's composition features, takes a new approach to write simple and DRY code.\n\n\n## Getting started\n\nHere's a transcription from our examples/simple package. \nThis is a very simple Hello World web application example. \n\n\n```go\npackage main\n\nimport (\n    \"github.com/yarf-framework/yarf\"\n)\n\n// Define a simple resource\ntype Hello struct {\n    yarf.Resource\n}\n\n// Implement the GET method\nfunc (h *Hello) Get(c *yarf.Context) error {\n    c.Render(\"Hello world!\")\n    \n    return nil\n}\n\n// Run app server on http://localhost:8080\nfunc main() {\n    y := yarf.New()\n    \n    y.Add(\"/\", new(Hello))\n    \n    y.Start(\":8080\")\n}\n\n```\n\nFor more code and examples demonstrating all YARF features, please refer to the 'examples' directory.\n\n\n\n## Features\n\n\n### Struct composition based design\n\nYARF resources are custom structs that act as handlers for HTTP methods. \nEach resource can implement one, several or all HTTP methods needed (GET, POST, DELETE, etc.).\nResources are created using Go's struct composition and you only have to declare the yarf.Resource type into your own struct.\n\nExample: \n\n```go\n\nimport \"github.com/yarf-framework/yarf\"\n\n// Define a simple resource\ntype Hello struct {\n    yarf.Resource\n}\n\n// Implement the GET method\nfunc (h *Hello) Get(c *yarf.Context) error {\n    c.Render(\"Hello world!\")\n    \n    return nil\n}\n\n```\n\n\n### Simple router\n\nUsing a strict match model, it matches exact URLs against resources for increased performance and clarity during routing. \nThe routes supports parameters in the form '/:param'.\n\nThe route: \n\n```go\n/hello/:name\n```\n\nWill match: \n\n```\n/hello/Joe\n/hello/nobody\n/hello/somebody/\n/hello/:name\n/hello/etc\n```\n\nBut it won't match: \n\n```\n/\n/hello\n/hello/Joe/AndMark\n/Joe/:name\n/any/thing\n```\n\nYou can define optional parameters using multiple routes on the same Resource.\n\n\n### Route parameters\n\nAt this point you know how to define parameters in your routes using the /:param naming convention. \nNow you'll see how easy is to get these parameters by their name from your resources using the Context.Param() method. \n\nExample: \n\nFor the route: \n\n```\n/hello/:name\n```\n\nYou can have this resource:\n\n```go\nimport \"github.com/yarf-framework/yarf\"\n\ntype Hello struct {\n    yarf.Resource\n}\n\nfunc (h *Hello) Get(c *yarf.Context) error {\n    name := c.Param(\"name\")\n\n    c.Render(\"Hello, \" + name)\n\n    return nil\n}\n\n```\n\n\n### Route wildcards\n\nWhen some extra freedom is needed on your routes, you can use a `*` as part of your routes to match anything where the wildcard is present. \n\nThe route: \n\n```\n/something/*/here\n```\n\nWill match the routes\n\n```\n/something/is/here\n/something/happen/here\n/something/isnt/here\n/something/was/here\n```\n\nAnd so on... \n\nYou can also combine this with parameters inside the routes for extra complexity.\n\n\n### Catch-All wildcard\n\nWhen using the `*` at the end of any route, the router will match everything from the wildcard and forward. \n\nThe route: \n\n```\n/match/from/here/*\n```\n\nWill match: \n\n```\n/match/from/here\n/match/from/here/please\n/match/from/here/and/forward\n/match/from/here/and/forward/for/ever/and/ever\n```\n\nAnd so on...\n\n\n#### Note about the wildcard\n\nThe `*` can only be used by itself and it doesn't works for single character matching like in regex. \n\nSo the route:\n \n```\n/match/some*\n```\n\nWill **NOT** match:\n\n```\n/match/some\n/match/something\n/match/someone\n/match/some/please\n```\n\n\n### Context\n\nThe Context object is passed as a parameter to all Resource methods and contains all the information related to the ongoing request. \n\nCheck the Context docs for a reference of the object: [https://godoc.org/github.com/yarf-framework/yarf#Context](https://godoc.org/github.com/yarf-framework/yarf#Context)\n\n\n\n### Middleware support\n\nMiddleware support is implemented in a similar way as Resources, by using composition.  \nRoutes will be pre-filtered and post-filtered by Middleware handlers when they're inserted in the router.\n\nExample: \n\n```go\nimport \"github.com/yarf-framework/yarf\"\n\n// Define your middleware and composite yarf.Middleware\ntype HelloMiddleware struct {\n    yarf.Middleware\n}\n\n// Implement only the PreDispatch method, PostDispatch not needed.\nfunc (m *HelloMiddleware) PreDispatch(c *yarf.Context) error {\n    c.Render(\"Hello from middleware! \\n\") // Render to response.\n\n    return nil\n}\n\n// Insert your middlewares to the server\nfunc main() {\n    y := yarf.New()\n\n    // Add middleware\n    y.Insert(new(HelloMiddleware))\n    \n    // Define routes\n    // ...\n    // ...\n    \n    // Start the server\n    y.Start()\n}\n```\n\n\n### Route groups\n\nRoutes can be grouped into a route prefix and handle their own middleware.\n\n\n### Nested groups\n\nAs routes can be grouped into a route prefix, other groups can be also grouped allowing for nested prefixes and middleware layers.\n\nExample: \n\n```go\nimport \"github.com/yarf-framework/yarf\"\n\n// Entry point of the executable application\n// It runs a default server listening on http://localhost:8080\n//\n// URLs after configuration:\n// http://localhost:8080\n// http://localhost:8080/hello/:name\n// http://localhost:8080/v2\n// http://localhost:8080/v2/hello/:name\n// http://localhost:8080/extra/v2\n// http://localhost:8080/extra/v2/hello/:name\n//\nfunc main() {\n    // Create a new empty YARF server\n    y := yarf.New()\n\n    // Create resources\n    hello := new(Hello)\n    hellov2 := new(HelloV2)\n\n    // Add main resource to multiple routes at root level.\n    y.Add(\"/\", hello)\n    y.Add(\"/hello/:name\", hello)\n\n    // Create /v2 prefix route group\n    g := yarf.RouteGroup(\"/v2\")\n\n    // Add /v2/ routes to the group\n    g.Add(\"/\", hellov2)\n    g.Add(\"/hello/:name\", hellov2)\n\n    // Use middleware only on the /v2/ group\n    g.Insert(new(HelloMiddleware))\n\n    // Add group to Yarf routes\n    y.AddGroup(g)\n\n    // Create another group for nesting into it.\n    n := yarf.RouteGroup(\"/extra\")\n\n    // Nest /v2 group into /extra/v2\n    n.AddGroup(g)\n\n    // Use another middleware only for this /extra/v2 group\n    n.Insert(new(ExtraMiddleware))\n\n    // Add group to Yarf\n    y.AddGroup(n)\n\n    // Start server listening on port 8080\n    y.Start(\":8080\")\n}\n```\n\nCheck the ./examples/routegroups demo for the complete working implementation.\n\n\n### Route caching\n\nA route cache is enabled by default to improve dispatch speed, but sacrificing memory space. \nIf you're running out of RAM memory and/or your app has too many possible routes that may not fit, you should disable the route cache.\n\nTo enable/disable the route cache, just set the UseCache flag of the Yarf object: \n\n```go\ny := yarf.New()\ny.UseCache = false\n```\n\n\n### Chain and extend\n\nJust use the Yarf object as any http.Handler on a chain. \nSet another http.Handler on the Yarf.Follow property to be followed in case this Yarf router can't match the request. \n\nHere's an example on how to follow the request to a public file server: \n\n```go\npackage main \n\nimport (\n    \"github.com/yarf-framework/yarf\"\n    \"net/http\"\n)\n\nfunc main() {\n    y := yarf.New()\n\n    // Add some routes\n    y.Add(\"/hello/:name\", new(Hello))\n    \n    //... more routes here\n    \n    // Follow to file server\n    y.Follow = http.FileServer(http.Dir(\"/var/www/public\"))\n    \n    // Start the server\n    y.Start(\":8080\")\n}\n```\n\n\n### Custom NotFound error handler\n\nYou can handle all 404 errors returned by any resource/middleware during the request flow of a Yarf server. \nTo do so, you only have to implement a function with the func(c *yarf.Context) signature and set it to your server's Yarf.NotFound property.\n\n```go\ny := yarf.New()\n\n// ...\n\ny.NotFound = func(c *yarf.Context) {\n    c.Render(\"This is a custom Not Found handler\")\n}\n\n// ...\n``` \n\n\n## Performance\n\nOn initial benchmarks, the framework seems to perform very well compared with other similar frameworks. \nEven when there are faster frameworks, under high load conditions and thanks to the route caching method, \nYARF seems to perform as good or even better than the fastests that work better under simpler conditions.\n\nCheck the benchmarks repository to run your own:\n\n[https://github.com/yarf-framework/benchmarks](https://github.com/yarf-framework/benchmarks)\n\n\n\n## HTTPS support\n\nSupport for running HTTPS server from the net/http package. \n\n### Using the default server\n\n```go\nfunc main() {\n    y := yarf.New()\n    \n    // Setup the app\n    // ...\n    // ...\n    \n    // Start https listening on port 443\n    y.StartTLS(\":443\", certFile, keyFile)\n}\n\n```\n\n### Using a custom server\n\n```go\nfunc main() {\n    y := yarf.New()\n\n    // Setup the app\n    // ...\n    // ...\n\n    // Configure custom http server and set the yarf object as Handler.\n    s := \u0026http.Server{\n        Addr:           \":443\",\n        Handler:        y,\n        ReadTimeout:    10 * time.Second,\n        WriteTimeout:   10 * time.Second,\n        MaxHeaderBytes: 1 \u003c\u003c 20,\n    }\n    s.ListenAndServeTLS(certFile, keyFile)\n}\n\n```\n\n\n## Why another micro-framework? \n\nWhy not?\n\nNo, seriously, i've researched for small/fast frameworks in the past for a Go project that I was starting. \nI found several options, but at the same time, none seemed to suit me. \nSome of them make you write weird function wrappers to fit the net/http package style. \nActually, most of them seem to be function-based handlers. \nWhile that's not wrong, I feel more comfortable with the resource-based design, and this I also feel aligns better with the spirit of REST. \n\nIn Yarf you create a resource struct that represents a REST resource and it has all HTTP methods available. \nNo need to create different routes for GET/POST/DELETE/etc. methods. \n\nBy using composition, you don't need to wrap functions inside functions over and over again to implement simple things like middleware or extension to your methods. \nYou can abuse composition to create a huge OO-like design for your business model without sacrifying performance and code readability. \n \nEven while the code style differs from the net/http package, the framework is fully compatible with it and couldn't run without it. \nExtensions and utilities from other frameworks or even the net/http package can be easily implemented into Yarf by just wraping them up into a Resource, \njust as you would do on any other framework by wrapping functions.\n  \nContext handling also shows some weird designs across frameworks. Some of them rely on reflection to receive any kind of handlers and context types. \nOthers make you receive some extra parameter in the handler function that actually brokes the net/http compatibility, and you have to carry that context parameter through all middleware/handler-wrapper functions just to make it available. \nIn Yarf, the Context is automatically sent as a parameter to all Resource methods by the framework. \n\nFor all the reasons above, among some others, there is a new framework in town. \n","funding_links":[],"categories":["Web Frameworks","Web框架","Web 框架","web框架","Utility","web框架`web 框架`"],"sub_categories":["HTTP Clients","实用程序/Miscellaneous","高級控制台界面","版本控制","Fail injection","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","Utility/Miscellaneous","版本控制`版本控制相关库`","Advanced Console UIs","交流","高级控制台界面"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyarf-framework%2Fyarf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyarf-framework%2Fyarf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyarf-framework%2Fyarf/lists"}