github.com/System-Glitch/goyave/v3@v3.6.1-0.20210226143142-ac2fe42ee80e/README.md (about)

     1  <p align="center">
     2      <img src="resources/img/logo/goyave_text.png" alt="Goyave Logo" width="550"/>
     3  </p>
     4  
     5  <p align="center">
     6      <a href="https://github.com/System-Glitch/goyave/releases"><img src="https://img.shields.io/github/v/release/System-Glitch/goyave?include_prereleases" alt="Version"/></a>
     7      <a href="https://github.com/System-Glitch/goyave/actions"><img src="https://github.com/System-Glitch/goyave/workflows/Test/badge.svg?branch=develop" alt="Build Status"/></a>
     8      <a href="https://coveralls.io/github/System-Glitch/goyave?branch=master"><img src="https://coveralls.io/repos/github/System-Glitch/goyave/badge.svg" alt="Coverage Status"/></a>
     9      <a href="https://goreportcard.com/report/github.com/System-Glitch/goyave"><img src="https://goreportcard.com/badge/github.com/System-Glitch/goyave" alt="Go Report"/></a>
    10      
    11  </p>
    12  
    13  <p align="center">
    14      <a href="https://github.com/System-Glitch/goyave/blob/master/LICENSE"><img src="https://img.shields.io/dub/l/vibe-d.svg" alt="License"/></a>
    15      <a href="https://github.com/avelino/awesome-go"><img src="https://awesome.re/mentioned-badge.svg" alt="Awesome"/></a>
    16      <a href="https://discord.gg/mfemDMc"><img src="https://img.shields.io/discord/744264895209537617?logo=discord" alt="Discord"/></a>
    17  </p>
    18  
    19  <h2 align="center">An Elegant Golang Web Framework</h2>
    20  
    21  Goyave is a progressive and accessible web application framework focused on REST APIs, aimed at making backend development easy and enjoyable. It has a philosophy of cleanliness and conciseness to make programs more elegant, easier to maintain and more focused. Goyave is an **opinionated** framework, helping your applications keeping a uniform architecture and limit redundancy. With Goyave, expect a full package with minimum setup.
    22  
    23  - **Clean Code**: Goyave has an expressive, elegant syntax, a robust structure and conventions. Minimalist calls and reduced redundancy are among the Goyave's core principles.
    24  - **Fast Development**: Develop faster and concentrate on the business logic of your application thanks to the many helpers and built-in functions.
    25  - **Powerful functionalities**: Goyave is accessible, yet powerful. The framework includes routing, request parsing, validation, localization, testing, authentication, and more!
    26  - **Reliability**: Error reporting is made easy thanks to advanced error handling and panic recovery. The framework is deeply tested.
    27  
    28  ## Table of contents
    29  
    30  - [Learning Goyave](#learning-goyave)
    31  - [Getting started](#getting-started)
    32  - [Features tour](#features-tour)
    33  - [Contributing](#contributing)
    34  - [License](#license)
    35  
    36  ## Learning Goyave
    37  
    38  The Goyave framework has an extensive documentation covering in-depth subjects and teaching you how to run a project using Goyave from setup to deployment.
    39  
    40  <a href="https://goyave.dev/guide/installation"><h3 align="center">Read the documentation</h3></a>
    41  
    42  <a href="https://pkg.go.dev/github.com/System-Glitch/goyave/v3"><h3 align="center">pkg.go.dev</h3></a>
    43  
    44  <a href="https://github.com/go-goyave/goyave-blog-example"><h3 align="center">Example project</h3></a>
    45  
    46  ## Getting started
    47  
    48  ### Requirements
    49  
    50  - Go 1.13+
    51  - Go modules
    52  
    53  ### Install using the template project
    54  
    55  You can bootstrap your project using the [Goyave template project](https://github.com/System-Glitch/goyave-template). This project has a complete directory structure already set up for you.
    56  
    57  #### Linux / MacOS
    58  
    59  ```
    60  $ curl https://raw.githubusercontent.com/System-Glitch/goyave/master/install.sh | bash -s github.com/username/projectname
    61  ```
    62  
    63  #### Windows (Powershell)
    64  
    65  ```
    66  > & ([scriptblock]::Create((curl "https://raw.githubusercontent.com/System-Glitch/goyave/master/install.ps1").Content)) -moduleName github.com/username/projectname
    67  ```
    68  
    69  ---
    70  
    71  Run `go run .` in your project's directory to start the server, then try to request the `hello` route.
    72  ```
    73  $ curl http://localhost:8080/hello
    74  Hi!
    75  ```
    76  
    77  There is also an `echo` route, with basic validation of the request body.
    78  ```
    79  $ curl -H "Content-Type: application/json" -X POST -d '{"text":"abc 123"}' http://localhost:8080/echo
    80  abc 123
    81  ```
    82  
    83  ## Features tour
    84  
    85  This section's goal is to give a **brief** look at the main features of the framework. It doesn't describe everything the framework has to offer, so don't consider this documentation. If you want a complete reference and documentation, head to [pkg.go.dev](https://pkg.go.dev/github.com/System-Glitch/goyave/v3) and the [official documentation](https://goyave.dev/guide/).
    86  
    87  - [Hello world from scratch](#hello-world-from-scratch)
    88  - [Configuration](#configuration)
    89  - [Routing](#routing)
    90  - [Controller](#controller)
    91  - [Middleware](#middleware)
    92  - [Validation](#validation)
    93  - [Database](#database)
    94  - [Localization](#localization)
    95  - [Testing](#testing)
    96  - [Status handlers](#status-handlers)
    97  - [CORS](#cors)
    98  - [Authentication](#authentication)
    99  - [Rate limiting](#rate-limiting)
   100  
   101  ### Hello world from scratch
   102  
   103  The example below shows a basic `Hello world` application using Goyave.
   104  
   105  ``` go
   106  import "github.com/System-Glitch/goyave/v3"
   107  
   108  func registerRoutes(router *goyave.Router) {
   109      router.Get("/hello", func(response *goyave.Response, request *goyave.Request) {
   110          response.String(http.StatusOK, "Hello world!")
   111      })
   112  }
   113  
   114  func main() {
   115      if err := goyave.Start(registerRoutes); err != nil {
   116          os.Exit(err.(*goyave.Error).ExitCode)
   117      }
   118  }
   119  ```
   120  
   121  ### Configuration
   122  
   123  To configure your application, use the `config.json` file at your project's root. If you are using the template project, copy `config.example.json` to `config.json`. The following code is an example of configuration for a local development environment:
   124  
   125  ```json
   126  {
   127      "app": {
   128          "name": "goyave_template",
   129          "environment": "localhost",
   130          "debug": true,
   131          "defaultLanguage": "en-US"
   132      },
   133      "server": {
   134          "host": "127.0.0.1",
   135          "maintenance": false,
   136          "protocol": "http",
   137          "domain": "",
   138          "port": 8080,
   139          "httpsPort": 8081,
   140          "timeout": 10,
   141          "maxUploadSize": 10
   142      },
   143      "database": {
   144          "connection": "mysql",
   145          "host": "127.0.0.1",
   146          "port": 3306,
   147          "name": "goyave",
   148          "username": "root",
   149          "password": "root",
   150          "options": "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local",
   151          "maxOpenConnections": 20,
   152          "maxIdleConnections": 20,
   153          "maxLifetime": 300,
   154          "autoMigrate": false
   155      }
   156  }
   157  ```
   158  
   159  If this config file misses some config entries, the default values will be used. 
   160  
   161  All entries are **validated**. That means that the application will not start if you provided an invalid value in your config (for example if the specified port is not a number). That also means that a goroutine trying to change a config entry with the incorrect type will panic.  
   162  Entries can be registered with a default value, their type and authorized values from any package. 
   163  
   164  **Getting a value:**
   165  ```go
   166  config.GetString("app.name") // "goyave"
   167  config.GetBool("app.debug") // true
   168  config.GetInt("server.port") // 80
   169  config.Has("app.name") // true
   170  ```
   171  
   172  **Setting a value:**
   173  ```go
   174  config.Set("app.name", "my awesome app")
   175  ```
   176  
   177  **Using environment variables:**
   178  ```json
   179  {
   180    "database": {
   181      "host": "${DB_HOST}"
   182    }
   183  }
   184  ```
   185  
   186  **Learn more about configuration in the [documentation](https://goyave.dev/guide/configuration.html).**
   187  
   188  ### Routing
   189  
   190  Routing is an essential part of any Goyave application. Routes definition is the action of associating a URI, sometimes having parameters, with a handler which will process the request and respond to it. Separating and naming routes clearly is important to make your API or website clear and expressive.
   191  
   192  Routes are defined in **routes registrer functions**. The main route registrer is passed to `goyave.Start()` and is executed automatically with a newly created root-level **router**.
   193  
   194  ``` go
   195  func Register(router *goyave.Router) {
   196      // Register your routes here
   197  
   198      // With closure, not recommended
   199      router.Get("/hello", func(response *goyave.Response, r *goyave.Request) {
   200          response.String(http.StatusOK, "Hi!")
   201      })
   202  
   203      router.Get("/hello", myHandlerFunction)
   204      router.Post("/user", user.Register).Validate(user.RegisterRequest)
   205      router.Route("PUT|PATCH", "/user", user.Update).Validate(user.UpdateRequest)
   206      router.Route("POST", "/product", product.Store).Validate(product.StoreRequest).Middleware(middleware.Trim)
   207  }
   208  ```
   209  
   210  URIs can have parameters, defined using the format `{name}` or `{name:pattern}`. If a regular expression pattern is not defined, the matched variable will be anything until the next slash. 
   211  
   212  **Example:**
   213  ``` go
   214  router.Get("/product/{key}", product.Show)
   215  router.Get("/product/{id:[0-9]+}", product.ShowById)
   216  router.Get("/category/{category}/{id:[0-9]+}", category.Show)
   217  ```
   218  
   219  Route parameters can be retrieved as a `map[string]string` in handlers using the request's `Params` attribute.
   220  ``` go
   221  func myHandlerFunction(response *goyave.Response, request *goyave.Request) {
   222      category := request.Params["category"]
   223      id, _ := strconv.Atoi(request.Params["id"])
   224      //...
   225  }
   226  ```
   227  
   228  **Learn more about routing in the [documentation](https://goyave.dev/guide/basics/routing.html).**
   229  
   230  ### Controller
   231  
   232  Controllers are files containing a collection of Handlers related to a specific feature. Each feature should have its own package. For example, if you have a controller handling user registration, user profiles, etc, you should create a `http/controller/user` package. Creating a package for each feature has the advantage of cleaning up route definitions a lot and helps keeping a clean structure for your project.
   233  
   234  A `Handler` is a `func(*goyave.Response, *goyave.Request)`. The first parameter lets you write a response, and the second contains all the information extracted from the raw incoming request.
   235  
   236  Handlers receive a `goyave.Response` and a `goyave.Request` as parameters.  
   237  `goyave.Request` can give you a lot of information about the incoming request, such as its headers, cookies, or body. Learn more [here](https://goyave.dev/guide/basics/requests.html).  
   238  `goyave.Response` implements `http.ResponseWriter` and is used to write a response. If you didn't write anything before the request lifecycle ends, `204 No Content` is automatically written. Learn everything about reponses [here](https://goyave.dev/guide/basics/responses.html).
   239  
   240  Let's take a very simple CRUD as an example for a controller definition:
   241  **http/controller/product/product.go**:
   242  ``` go
   243  func Index(response *goyave.Response, request *goyave.Request) {
   244      products := []model.Product{}
   245      result := database.Conn().Find(&products)
   246      if response.HandleDatabaseError(result) {
   247          response.JSON(http.StatusOK, products)
   248      }
   249  }
   250  
   251  func Show(response *goyave.Response, request *goyave.Request) {
   252      product := model.Product{}
   253      result := database.Conn().First(&product, request.Params["id"])
   254      if response.HandleDatabaseError(result) {
   255          response.JSON(http.StatusOK, product)
   256      }
   257  }
   258  
   259  func Store(response *goyave.Response, request *goyave.Request) {
   260      product := model.Product{
   261          Name:  request.String("name"),
   262          Price: request.Numeric("price"),
   263      }
   264      if err := database.Conn().Create(&product).Error; err != nil {
   265          response.Error(err)
   266      } else {
   267          response.JSON(http.StatusCreated, map[string]uint{"id": product.ID})
   268      }
   269  }
   270  
   271  func Update(response *goyave.Response, request *goyave.Request) {
   272      product := model.Product{}
   273      db := database.Conn()
   274      result := db.Select("id").First(&product, request.Params["id"])
   275      if response.HandleDatabaseError(result) {
   276          if err := db.Model(&product).Update("name", request.String("name")).Error; err != nil {
   277              response.Error(err)
   278          }
   279      }
   280  }
   281  
   282  func Destroy(response *goyave.Response, request *goyave.Request) {
   283      product := model.Product{}
   284      db := database.Conn()
   285      result := db.Select("id").First(&product, request.Params["id"])
   286      if response.HandleDatabaseError(result) {
   287          if err := db.Delete(&product).Error; err != nil {
   288              response.Error(err)
   289          }
   290      }
   291  }
   292  ```
   293  
   294  **Learn more about controllers in the [documentation](https://goyave.dev/guide/basics/controllers.html).**
   295  
   296  ### Middleware
   297  
   298  Middleware are handlers executed before the controller handler. They are a convenient way to filter, intercept or alter HTTP requests entering your application. For example, middleware can be used to authenticate users. If the user is not authenticated, a message is sent to the user even before the controller handler is reached. However, if the user is authenticated, the middleware will pass to the next handler. Middleware can also be used to sanitize user inputs, by trimming strings for example, to log all requests into a log file, to automatically add headers to all your responses, etc.
   299  
   300  ``` go
   301  func MyCustomMiddleware(next goyave.Handler) goyave.Handler {
   302      return func(response *goyave.Response, request *goyave.Request) {
   303          // Do something
   304          next(response, request) // Pass to the next handler
   305      }
   306  }
   307  ```
   308  
   309  To assign a middleware to a router, use the `router.Middleware()` function. Many middleware can be assigned at once. The assignment order is important as middleware will be **executed in order**.
   310  
   311  ``` go
   312  router.Middleware(middleware.MyCustomMiddleware)
   313  ```
   314  
   315  **Learn more about middleware in the [documentation](https://goyave.dev/guide/basics/middleware.html).**
   316  
   317  
   318  ### Validation
   319  
   320  Goyave provides a powerful, yet easy way to validate all incoming data, no matter its type or its format, thanks to a large number of validation rules.
   321  
   322  Incoming requests are validated using **rules set**, which associate rules with each expected field in the request.
   323  
   324  Validation rules can **alter the raw data**. That means that when you validate a field to be number, if the validation passes, you are ensured that the data you'll be using in your controller handler is a `float64`. Or if you're validating an IP, you get a `net.IP` object.
   325  
   326  Validation is automatic. You just have to define a rules set and assign it to a route. When the validation doesn't pass, the request is stopped and the validation errors messages are sent as a response.
   327  
   328  Rule sets are defined in the same package as the controller, typically in a separate file named `request.go`. Rule sets are named after the name of the controller handler they will be used with, and end with `Request`. For example, a rule set for the `Store` handler will be named `StoreRequest`. If a rule set can be used for multiple handlers, consider using a name suited for all of them. The rules for a store operation are often the same for update operations, so instead of duplicating the set, create one unique set called `UpsertRequest`.
   329  
   330  **Example:** (`http/controller/product/request.go`)
   331  ``` go
   332  var (
   333      StoreRequest validation.RuleSet = validation.RuleSet{
   334          "name":  {"required", "string", "between:3,50"},
   335          "price": {"required", "numeric", "min:0.01"},
   336          "image": {"nullable", "file", "image", "max:2048", "count:1"},
   337      }
   338  
   339      // ...
   340  )
   341  ```
   342  
   343  Once your rules sets are defined, you need to assign them to your routes using the `Validate()` method.
   344  
   345  ``` go
   346  router.Post("/product", product.Store).Validate(product.StoreRequest)
   347  ```
   348  
   349  
   350  **Learn more about validation in the [documentation](https://goyave.dev/guide/basics/validation.html).**
   351  
   352  ### Database
   353  
   354  Most web applications use a database. In this section, we are going to see how Goyave applications can query a database, using the awesome [Gorm ORM](https://gorm.io/).
   355  
   356  Database connections are managed by the framework and are long-lived. When the server shuts down, the database connections are closed automatically. So you don't have to worry about creating, closing or refreshing database connections in your application.
   357  
   358  Very few code is required to get started with databases. There are some [configuration](https://goyave.dev/guide/configuration.html#configuration-reference) options that you need to change though:
   359  
   360  - `database.connection`
   361  - `database.host`
   362  - `database.port`
   363  - `database.name`
   364  - `database.username`
   365  - `database.password`
   366  - `database.options`
   367  - `database.maxOpenConnection`
   368  - `database.maxIdleConnection`
   369  - `database.maxLifetime`
   370  
   371  ``` go
   372  user := model.User{}
   373  db := database.Conn()
   374  db.First(&user)
   375  
   376  fmt.Println(user)
   377  ```
   378  
   379  Models are usually just normal Golang structs, basic Go types, or pointers of them. `sql.Scanner` and `driver.Valuer` interfaces are also supported.
   380  
   381  ```go
   382  func init() {
   383      database.RegisterModel(&User{})
   384  }
   385  
   386  type User struct {
   387      gorm.Model
   388      Name         string
   389      Age          sql.NullInt64
   390      Birthday     *time.Time
   391      Email        string  `gorm:"type:varchar(100);uniqueIndex"`
   392      Role         string  `gorm:"size:255"` // set field size to 255
   393      MemberNumber *string `gorm:"unique;not null"` // set member number to unique and not null
   394      Num          int     `gorm:"autoIncrement"` // set num to auto incrementable
   395      Address      string  `gorm:"index:addr"` // create index with name `addr` for address
   396      IgnoreMe     int     `gorm:"-"` // ignore this field
   397  }
   398  ```
   399  
   400  **Learn more about using databases in the [documentation](https://goyave.dev/guide/basics/database.html).**
   401  
   402  ### Localization
   403  
   404  The Goyave framework provides a convenient way to support multiple languages within your application. Out of the box, Goyave only provides the `en-US` language.
   405  
   406  Language files are stored in the `resources/lang` directory.
   407  
   408  ```
   409  .
   410  └── resources
   411      └── lang
   412          └── en-US (language name)
   413              ├── fields.json (optional)
   414              ├── locale.json (optional)
   415              └── rules.json (optional)
   416  ```
   417  
   418  The `fields.json` file contains the field names translations and their rule-specific messages. Translating field names helps making more expressive messages instead of showing the technical field name to the user. Rule-specific messages let you override a validation rule message for a specific field.
   419  
   420  **Example:**
   421  ``` json
   422  {
   423      "email": {
   424          "name": "email address",
   425          "rules": {
   426              "required": "You must provide an :field."
   427          }
   428      }
   429  }
   430  ```
   431  
   432  The `locale.json` file contains all language lines that are not related to validation. This is the place where you should write the language lines for your user interface or for the messages returned by your controllers.
   433  
   434  **Example:**
   435  ``` json
   436  {
   437      "product.created": "The product have been created with success.",
   438      "product.deleted": "The product have been deleted with success."
   439  }
   440  ```
   441  
   442  The `rules.json` file contains the validation rules messages. These messages can have **[placeholders](https://goyave.dev/guide/basics/validation.html#placeholders)**, which will be automatically replaced by the validator with dynamic values. If you write custom validation rules, their messages shall be written in this file.
   443  
   444  **Example:**
   445  
   446  ``` json
   447  {
   448      "integer": "The :field must be an integer.",
   449      "starts_with": "The :field must start with one of the following values: :values.",
   450      "same": "The :field and the :other must match."
   451  }
   452  ```
   453  
   454  When an incoming request enters your application, the core language middleware checks if the `Accept-Language` header is set, and set the `goyave.Request`'s `Lang` attribute accordingly. Localization is handled automatically by the validator.
   455  
   456  ``` go
   457  func ControllerHandler(response *goyave.Response, request *goyave.Request) {
   458      response.String(http.StatusOK, lang.Get(request.Lang, "my-custom-message"))
   459  }
   460  ```
   461  
   462  **Learn more about localization in the [documentation](https://goyave.dev/guide/advanced/localization.html).**
   463  
   464  ### Testing
   465  
   466  Goyave provides an API to ease the unit and functional testing of your application. This API is an extension of [testify](https://github.com/stretchr/testify). `goyave.TestSuite` inherits from testify's `suite.Suite`, and sets up the environment for you. That means:
   467  
   468  - `GOYAVE_ENV` environment variable is set to `test` and restored to its original value when the suite is done.
   469  - All tests are run using your project's root as working directory. This directory is determined by the presence of a `go.mod` file.
   470  - Config and language files are loaded before the tests start. As the environment is set to `test`, you **need** a `config.test.json` in the root directory of your project.
   471  
   472  This setup is done by the function `goyave.RunTest`, so you shouldn't run your test suites using testify's `suite.Run()` function.
   473  
   474  The following example is a **functional** test and would be located in the `test` package.
   475  
   476  ``` go
   477  import (
   478      "github.com/username/projectname/http/route"
   479      "github.com/System-Glitch/goyave/v3"
   480  )
   481  
   482  type CustomTestSuite struct {
   483      goyave.TestSuite
   484  }
   485  
   486  func (suite *CustomTestSuite) TestHello() {
   487      suite.RunServer(route.Register, func() {
   488          resp, err := suite.Get("/hello", nil)
   489          suite.Nil(err)
   490          suite.NotNil(resp)
   491          if resp != nil {
   492              defer resp.Body.Close()
   493              suite.Equal(200, resp.StatusCode)
   494              suite.Equal("Hi!", string(suite.GetBody(resp)))
   495          }
   496      })
   497  }
   498  
   499  func TestCustomSuite(t *testing.T) {
   500      goyave.RunTest(t, new(CustomTestSuite))
   501  }
   502  ```
   503  
   504  When writing functional tests, you can retrieve the response body  easily using `suite.GetBody(response)`.
   505  
   506  ``` go 
   507  resp, err := suite.Get("/get", nil)
   508  suite.Nil(err)
   509  if err == nil {
   510      defer resp.Body.Close()
   511      suite.Equal("response content", string(suite.GetBody(resp)))
   512  }
   513  ```
   514  
   515  **URL-encoded requests:**
   516  
   517  ``` go
   518  headers := map[string]string{"Content-Type": "application/x-www-form-urlencoded; param=value"}
   519  resp, err := suite.Post("/product", headers, strings.NewReader("field=value"))
   520  suite.Nil(err)
   521  if err == nil {
   522      defer resp.Body.Close()
   523      suite.Equal("response content", string(suite.GetBody(resp)))
   524  }
   525  ```
   526  
   527  **JSON requests:**
   528  
   529  ``` go
   530  headers := map[string]string{"Content-Type": "application/json"}
   531  body, _ := json.Marshal(map[string]interface{}{"name": "Pizza", "price": 12.5})
   532  resp, err := suite.Post("/product", headers, bytes.NewReader(body))
   533  suite.Nil(err)
   534  if err == nil {
   535      defer resp.Body.Close()
   536      suite.Equal("response content", string(suite.GetBody(resp)))
   537  }
   538  ```
   539  
   540  **Testing JSON response:**
   541  
   542  ``` go
   543  suite.RunServer(route.Register, func() {
   544      resp, err := suite.Get("/product", nil)
   545      suite.Nil(err)
   546      if err == nil {
   547          defer resp.Body.Close()
   548          json := map[string]interface{}{}
   549          err := suite.GetJSONBody(resp, &json)
   550          suite.Nil(err)
   551          if err == nil { // You should always check parsing error before continuing.
   552              suite.Equal("value", json["field"])
   553              suite.Equal(float64(42), json["number"])
   554          }
   555      }
   556  })
   557  ```
   558  
   559  The testing API has many more features such as record generators, factories, database helpers, a middleware tester, support for multipart and file uploads...
   560  
   561  **Learn more about testing in the [documentation](https://goyave.dev/guide/advanced/testing.html).**
   562  
   563  ### Status handlers
   564  
   565  Status handlers are regular handlers executed during the finalization step of the request's lifecycle if the response body is empty but a status code has been set. Status handler are mainly used to implement a custom behavior for user or server errors (400 and 500 status codes).
   566  
   567  The following file `http/controller/status/status.go` is an example of custom 404 error handling:
   568  ``` go
   569  package status
   570  
   571  import "github.com/System-Glitch/goyave/v3"
   572  
   573  func NotFound(response *goyave.Response, request *goyave.Request) {
   574      if err := response.RenderHTML(response.GetStatus(), "errors/404.html", nil); err != nil {
   575          response.Error(err)
   576      }
   577  }
   578  ```
   579  
   580  Status handlers are registered in the **router**.
   581  
   582  ``` go
   583  // Use "status.NotFound" for empty responses having status 404 or 405.
   584  router.StatusHandler(status.NotFound, 404)
   585  ```
   586  
   587  **Learn more about status handlers in the [documentation](https://goyave.dev/guide/advanced/status-handlers.html).**
   588  
   589  
   590  ### CORS
   591  
   592  Goyave provides a built-in CORS module. CORS options are set on **routers**. If the passed options are not `nil`, the CORS core middleware is automatically added.
   593  
   594  ``` go
   595  router.CORS(cors.Default())
   596  ```
   597  
   598  CORS options should be defined **before middleware and route definition**. All of this router's sub-routers **inherit** CORS options by default. If you want to remove the options from a sub-router, or use different ones, simply create another `cors.Options` object and assign it.
   599  
   600  `cors.Default()` can be used as a starting point for custom configuration.
   601  
   602  ``` go
   603  options := cors.Default()
   604  options.AllowedOrigins = []string{"https://google.com", "https://images.google.com"}
   605  router.CORS(options)
   606  ```
   607  
   608  **Learn more about CORS in the [documentation](https://goyave.dev/guide/advanced/cors.html).**
   609  
   610  ### Authentication
   611  
   612  Goyave provides a convenient and expandable way of handling authentication in your application. Authentication can be enabled when registering your routes:
   613  
   614  ``` go
   615  import "github.com/System-Glitch/goyave/v3/auth"
   616  
   617  //...
   618  
   619  authenticator := auth.Middleware(&model.User{}, &auth.BasicAuthenticator{})
   620  router.Middleware(authenticator)
   621  ```
   622  
   623  Authentication is handled by a simple middleware calling an **Authenticator**. This middleware also needs a model, which will be used to fetch user information on a successful login.
   624  
   625  Authenticators use their model's struct fields tags to know which field to use for username and password. To make your model compatible with authentication, you must add the `auth:"username"` and `auth:"password"` tags:
   626  
   627  ``` go
   628  type User struct {
   629      gorm.Model
   630      Email    string `gorm:"type:char(100);uniqueIndex" auth:"username"`
   631      Name     string `gorm:"type:char(100)"`
   632      Password string `gorm:"type:char(60)" auth:"password"`
   633  }
   634  ```
   635  
   636  When a user is successfully authenticated on a protected route, its information is available in the controller handler, through the request `User` field.
   637  
   638  ``` go
   639  func Hello(response *goyave.Response, request *goyave.Request) {
   640      user := request.User.(*model.User)
   641      response.String(http.StatusOK, "Hello " + user.Name)
   642  }
   643  ```
   644  
   645  **Learn more about authentication in the [documentation](https://goyave.dev/guide/advanced/authentication.html).**
   646  
   647  ### Rate limiting
   648  
   649  Rate limiting is a crucial part of public API development. If you want to protect your data from being crawled, protect yourself from DDOS attacks, or provide different tiers of access to your API, you can do it using Goyave's built-in rate limiting middleware.
   650  
   651  This middleware uses either a client's IP or an authenticated client's ID (or any other way of identifying a client you may need) and maps a quota, a quota duration and a request count to it. If a client exceeds the request quota in the given quota duration, this middleware will block and return `HTTP 429 Too Many Requests`.
   652  
   653  The middleware will always add the following headers to the response:
   654  - `RateLimit-Limit`: containing the requests quota in the time window
   655  - `RateLimit-Remaining`: containing the remaining requests quota in the current window
   656  - `RateLimit-Reset`: containing the time remaining in the current window, specified in seconds
   657  
   658  ```go
   659  import "github.com/System-Glitch/goyave/v3/middleware/ratelimiter"
   660  
   661  ratelimiterMiddleware := ratelimiter.New(func(request *goyave.Request) ratelimiter.Config {
   662      return ratelimiter.Config {
   663          RequestQuota:  100,
   664          QuotaDuration: time.Minute,
   665          // 100 requests per minute allowed
   666          // Client IP will be used as identifier
   667      }
   668  })
   669  
   670  router.Middleware(ratelimiterMiddleware)
   671  ```
   672  
   673  **Learn more about rate limiting in the [documentation](https://goyave.dev/guide/advanced/rate-limiting.html).**
   674  
   675  ## Contributing
   676  
   677  Thank you for considering contributing to the Goyave framework! You can find the contribution guide in the [documentation](https://goyave.dev/guide/contribution-guide.html).
   678  
   679  I have many ideas for the future of Goyave. I would be infinitely grateful to whoever want to support me and let me continue working on Goyave and making it better and better.
   680  
   681  You can support me on Github Sponsor or Patreon.
   682  
   683  <a href="https://github.com/sponsors/System-Glitch">❤ Sponsor me!</a>
   684  
   685  <a href="https://www.patreon.com/bePatron?u=25997573">
   686      <img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
   687  </a>
   688  
   689  I'm very grateful to my patrons and donators:
   690  
   691  - Ben Hyrman
   692  - Massimiliano Bertinetti
   693  
   694  ### Contributors
   695  
   696  A big "Thank you" to the Goyave contributors:
   697  
   698  - [Kuinox](https://github.com/Kuinox) (Powershell install script)
   699  - [Alexandre GV.](https://github.com/alexandregv) (Install script MacOS compatibility)
   700  - [jRimbault](https://github.com/jRimbault) (CI and code analysis)
   701  - [Guillermo Galvan](https://github.com/gmgalvan) (Request extra data)
   702  - [Albert Shirima](https://github.com/agbaraka) (Rate limiting)
   703  
   704  ## License
   705  
   706  The Goyave framework is MIT Licensed. Copyright © 2019 Jérémy LAMBERT (SystemGlitch)