goyave.dev/goyave/v4@v4.4.11/README.md (about) 1 <p align="center"> 2 <img src="https://raw.githubusercontent.com/go-goyave/goyave/master/resources/img/logo/goyave_text.png#gh-light-mode-only" alt="Goyave Logo" width="550"/> 3 <img src="https://raw.githubusercontent.com/go-goyave/goyave/master/resources/img/logo/goyave_text_dark.png#gh-dark-mode-only" alt="Goyave Logo" width="550"/> 4 </p> 5 6 <p align="center"> 7 <a href="https://github.com/go-goyave/goyave/releases"><img src="https://img.shields.io/github/v/release/go-goyave/goyave?include_prereleases" alt="Version"/></a> 8 <a href="https://github.com/go-goyave/goyave/actions"><img src="https://github.com/go-goyave/goyave/workflows/CI/badge.svg?branch=develop" alt="Build Status"/></a> 9 <a href="https://coveralls.io/github/go-goyave/goyave?branch=master"><img src="https://coveralls.io/repos/github/go-goyave/goyave/badge.svg" alt="Coverage Status"/></a> 10 <a href="https://goreportcard.com/report/goyave.dev/goyave"><img src="https://goreportcard.com/badge/goyave.dev/goyave" alt="Go Report"/></a> 11 </p> 12 13 <p align="center"> 14 <a href="https://github.com/go-goyave/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 - [Read the documentation](https://goyave.dev/guide/installation.html) 41 - [pkg.go.dev](https://pkg.go.dev/goyave.dev/goyave/v4) 42 - [Example project](https://github.com/go-goyave/goyave-blog-example) 43 44 ## Getting started 45 46 ### Requirements 47 48 - Go 1.18+ 49 50 ### Install using the template project 51 52 You can bootstrap your project using the [Goyave template project](https://github.com/go-goyave/goyave-template). This project has a complete directory structure already set up for you. 53 54 #### Linux / MacOS 55 56 ``` 57 $ curl https://goyave.dev/install.sh | bash -s github.com/username/projectname 58 ``` 59 60 #### Windows (Powershell) 61 62 ``` 63 > & ([scriptblock]::Create((curl "https://goyave.dev/install.ps1").Content)) -moduleName github.com/username/projectname 64 ``` 65 66 --- 67 68 Run `go run .` in your project's directory to start the server, then try to request the `hello` route. 69 ``` 70 $ curl http://localhost:8080/hello 71 Hi! 72 ``` 73 74 There is also an `echo` route, with basic validation of the request body. 75 ``` 76 $ curl -H "Content-Type: application/json" -X POST -d '{"text":"abc 123"}' http://localhost:8080/echo 77 abc 123 78 ``` 79 80 ## Features tour 81 82 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/goyave.dev/goyave/v4) and the [official documentation](https://goyave.dev/guide/). 83 84 - [Hello world from scratch](#hello-world-from-scratch) 85 - [Configuration](#configuration) 86 - [Routing](#routing) 87 - [Controller](#controller) 88 - [Middleware](#middleware) 89 - [Validation](#validation) 90 - [Database](#database) 91 - [Localization](#localization) 92 - [Testing](#testing) 93 - [Status handlers](#status-handlers) 94 - [CORS](#cors) 95 - [Authentication](#authentication) 96 - [Rate limiting](#rate-limiting) 97 - [Websocket](#websocket) 98 99 ### Hello world from scratch 100 101 The example below shows a basic `Hello world` application using Goyave. 102 103 ``` go 104 import "goyave.dev/goyave/v4" 105 106 func registerRoutes(router *goyave.Router) { 107 router.Get("/hello", func(response *goyave.Response, request *goyave.Request) { 108 response.String(http.StatusOK, "Hello world!") 109 }) 110 } 111 112 func main() { 113 if err := goyave.Start(registerRoutes); err != nil { 114 os.Exit(err.(*goyave.Error).ExitCode) 115 } 116 } 117 ``` 118 119 ### Configuration 120 121 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: 122 123 ```json 124 { 125 "app": { 126 "name": "goyave_template", 127 "environment": "localhost", 128 "debug": true, 129 "defaultLanguage": "en-US" 130 }, 131 "server": { 132 "host": "127.0.0.1", 133 "maintenance": false, 134 "protocol": "http", 135 "domain": "", 136 "port": 8080, 137 "httpsPort": 8081, 138 "timeout": 10, 139 "maxUploadSize": 10 140 }, 141 "database": { 142 "connection": "mysql", 143 "host": "127.0.0.1", 144 "port": 3306, 145 "name": "goyave", 146 "username": "root", 147 "password": "root", 148 "options": "charset=utf8mb4&collation=utf8mb4_general_ci&parseTime=true&loc=Local", 149 "maxOpenConnections": 20, 150 "maxIdleConnections": 20, 151 "maxLifetime": 300, 152 "autoMigrate": false 153 } 154 } 155 ``` 156 157 If this config file misses some config entries, the default values will be used. 158 159 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. 160 Entries can be registered with a default value, their type and authorized values from any package. 161 162 **Getting a value:** 163 ```go 164 config.GetString("app.name") // "goyave" 165 config.GetBool("app.debug") // true 166 config.GetInt("server.port") // 80 167 config.Has("app.name") // true 168 ``` 169 170 **Setting a value:** 171 ```go 172 config.Set("app.name", "my awesome app") 173 ``` 174 175 **Using environment variables:** 176 ```json 177 { 178 "database": { 179 "host": "${DB_HOST}" 180 } 181 } 182 ``` 183 184 **Learn more about configuration in the [documentation](https://goyave.dev/guide/configuration.html).** 185 186 ### Routing 187 188 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. 189 190 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**. 191 192 ``` go 193 func Register(router *goyave.Router) { 194 // Register your routes here 195 196 // With closure, not recommended 197 router.Get("/hello", func(response *goyave.Response, r *goyave.Request) { 198 response.String(http.StatusOK, "Hi!") 199 }) 200 201 router.Get("/hello", myHandlerFunction) 202 router.Post("/user", user.Register).Validate(user.RegisterRequest) 203 router.Route("PUT|PATCH", "/user", user.Update).Validate(user.UpdateRequest) 204 router.Route("POST", "/product", product.Store).Validate(product.StoreRequest).Middleware(middleware.Trim) 205 } 206 ``` 207 208 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. 209 210 **Example:** 211 ``` go 212 router.Get("/product/{key}", product.Show) 213 router.Get("/product/{id:[0-9]+}", product.ShowById) 214 router.Get("/category/{category}/{id:[0-9]+}", category.Show) 215 ``` 216 217 Route parameters can be retrieved as a `map[string]string` in handlers using the request's `Params` attribute. 218 ``` go 219 func myHandlerFunction(response *goyave.Response, request *goyave.Request) { 220 category := request.Params["category"] 221 id, _ := strconv.Atoi(request.Params["id"]) 222 //... 223 } 224 ``` 225 226 **Learn more about routing in the [documentation](https://goyave.dev/guide/basics/routing.html).** 227 228 ### Controller 229 230 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. 231 232 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. 233 234 Handlers receive a `goyave.Response` and a `goyave.Request` as parameters. 235 `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). 236 `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). 237 238 Let's take a very simple CRUD as an example for a controller definition: 239 **http/controller/product/product.go**: 240 ``` go 241 func Index(response *goyave.Response, request *goyave.Request) { 242 products := []model.Product{} 243 result := database.Conn().Find(&products) 244 if response.HandleDatabaseError(result) { 245 response.JSON(http.StatusOK, products) 246 } 247 } 248 249 func Show(response *goyave.Response, request *goyave.Request) { 250 product := model.Product{} 251 result := database.Conn().First(&product, request.Params["id"]) 252 if response.HandleDatabaseError(result) { 253 response.JSON(http.StatusOK, product) 254 } 255 } 256 257 func Store(response *goyave.Response, request *goyave.Request) { 258 product := model.Product{ 259 Name: request.String("name"), 260 Price: request.Numeric("price"), 261 } 262 if err := database.Conn().Create(&product).Error; err != nil { 263 response.Error(err) 264 } else { 265 response.JSON(http.StatusCreated, map[string]uint{"id": product.ID}) 266 } 267 } 268 269 func Update(response *goyave.Response, request *goyave.Request) { 270 product := model.Product{} 271 db := database.Conn() 272 result := db.Select("id").First(&product, request.Params["id"]) 273 if response.HandleDatabaseError(result) { 274 if err := db.Model(&product).Update("name", request.String("name")).Error; err != nil { 275 response.Error(err) 276 } 277 } 278 } 279 280 func Destroy(response *goyave.Response, request *goyave.Request) { 281 product := model.Product{} 282 db := database.Conn() 283 result := db.Select("id").First(&product, request.Params["id"]) 284 if response.HandleDatabaseError(result) { 285 if err := db.Delete(&product).Error; err != nil { 286 response.Error(err) 287 } 288 } 289 } 290 ``` 291 292 **Learn more about controllers in the [documentation](https://goyave.dev/guide/basics/controllers.html).** 293 294 ### Middleware 295 296 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. 297 298 ``` go 299 func MyCustomMiddleware(next goyave.Handler) goyave.Handler { 300 return func(response *goyave.Response, request *goyave.Request) { 301 // Do something 302 next(response, request) // Pass to the next handler 303 } 304 } 305 ``` 306 307 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**. 308 309 ``` go 310 router.Middleware(middleware.MyCustomMiddleware) 311 ``` 312 313 **Learn more about middleware in the [documentation](https://goyave.dev/guide/basics/middleware.html).** 314 315 316 ### Validation 317 318 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. 319 320 Incoming requests are validated using **rules set**, which associate rules with each expected field in the request. 321 322 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. 323 324 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. 325 326 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`. 327 328 **Example:** (`http/controller/product/request.go`) 329 ``` go 330 var ( 331 StoreRequest = validation.RuleSet{ 332 "name": validation.List{"required", "string", "between:3,50"}, 333 "price": validation.List{"required", "numeric", "min:0.01"}, 334 "image": validation.List{"nullable", "file", "image", "max:2048", "count:1"}, 335 } 336 337 // ... 338 ) 339 ``` 340 341 Once your rules sets are defined, you need to assign them to your routes using the `Validate()` method. 342 343 ``` go 344 router.Post("/product", product.Store).Validate(product.StoreRequest) 345 ``` 346 347 348 **Learn more about validation in the [documentation](https://goyave.dev/guide/basics/validation.html).** 349 350 ### Database 351 352 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/). 353 354 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. 355 356 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: 357 358 - `database.connection` 359 - `database.host` 360 - `database.port` 361 - `database.name` 362 - `database.username` 363 - `database.password` 364 - `database.options` 365 - `database.maxOpenConnection` 366 - `database.maxIdleConnection` 367 - `database.maxLifetime` 368 369 ``` go 370 user := model.User{} 371 db := database.Conn() 372 db.First(&user) 373 374 fmt.Println(user) 375 ``` 376 377 Models are usually just normal Golang structs, basic Go types, or pointers of them. `sql.Scanner` and `driver.Valuer` interfaces are also supported. 378 379 ```go 380 func init() { 381 database.RegisterModel(&User{}) 382 } 383 384 type User struct { 385 gorm.Model 386 Name string 387 Age sql.NullInt64 388 Birthday *time.Time 389 Email string `gorm:"type:varchar(100);uniqueIndex"` 390 Role string `gorm:"size:255"` // set field size to 255 391 MemberNumber *string `gorm:"unique;not null"` // set member number to unique and not null 392 Num int `gorm:"autoIncrement"` // set num to auto incrementable 393 Address string `gorm:"index:addr"` // create index with name `addr` for address 394 IgnoreMe int `gorm:"-"` // ignore this field 395 } 396 ``` 397 398 **Learn more about using databases in the [documentation](https://goyave.dev/guide/basics/database.html).** 399 400 ### Localization 401 402 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. 403 404 Language files are stored in the `resources/lang` directory. 405 406 ``` 407 . 408 └── resources 409 └── lang 410 └── en-US (language name) 411 ├── fields.json (optional) 412 ├── locale.json (optional) 413 └── rules.json (optional) 414 ``` 415 416 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. 417 418 **Example:** 419 ``` json 420 { 421 "email": { 422 "name": "email address", 423 "rules": { 424 "required": "You must provide an :field." 425 } 426 } 427 } 428 ``` 429 430 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. 431 432 **Example:** 433 ``` json 434 { 435 "product.created": "The product have been created with success.", 436 "product.deleted": "The product have been deleted with success." 437 } 438 ``` 439 440 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. 441 442 **Example:** 443 444 ``` json 445 { 446 "integer": "The :field must be an integer.", 447 "starts_with": "The :field must start with one of the following values: :values.", 448 "same": "The :field and the :other must match." 449 } 450 ``` 451 452 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. 453 454 ``` go 455 func ControllerHandler(response *goyave.Response, request *goyave.Request) { 456 response.String(http.StatusOK, lang.Get(request.Lang, "my-custom-message")) 457 } 458 ``` 459 460 **Learn more about localization in the [documentation](https://goyave.dev/guide/advanced/localization.html).** 461 462 ### Testing 463 464 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: 465 466 - `GOYAVE_ENV` environment variable is set to `test` and restored to its original value when the suite is done. 467 - All tests are run using your project's root as working directory. This directory is determined by the presence of a `go.mod` file. 468 - 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. 469 470 This setup is done by the function `goyave.RunTest`, so you shouldn't run your test suites using testify's `suite.Run()` function. 471 472 The following example is a **functional** test and would be located in the `test` package. 473 474 ``` go 475 import ( 476 "github.com/username/projectname/http/route" 477 "goyave.dev/goyave/v4" 478 ) 479 480 type CustomTestSuite struct { 481 goyave.TestSuite 482 } 483 484 func (suite *CustomTestSuite) TestHello() { 485 suite.RunServer(route.Register, func() { 486 resp, err := suite.Get("/hello", nil) 487 suite.Nil(err) 488 suite.NotNil(resp) 489 if resp != nil { 490 defer resp.Body.Close() 491 suite.Equal(200, resp.StatusCode) 492 suite.Equal("Hi!", string(suite.GetBody(resp))) 493 } 494 }) 495 } 496 497 func TestCustomSuite(t *testing.T) { 498 goyave.RunTest(t, new(CustomTestSuite)) 499 } 500 ``` 501 502 When writing functional tests, you can retrieve the response body easily using `suite.GetBody(response)`. 503 504 ``` go 505 resp, err := suite.Get("/get", nil) 506 suite.Nil(err) 507 if err == nil { 508 defer resp.Body.Close() 509 suite.Equal("response content", string(suite.GetBody(resp))) 510 } 511 ``` 512 513 **URL-encoded requests:** 514 515 ``` go 516 headers := map[string]string{"Content-Type": "application/x-www-form-urlencoded; param=value"} 517 resp, err := suite.Post("/product", headers, strings.NewReader("field=value")) 518 suite.Nil(err) 519 if err == nil { 520 defer resp.Body.Close() 521 suite.Equal("response content", string(suite.GetBody(resp))) 522 } 523 ``` 524 525 **JSON requests:** 526 527 ``` go 528 headers := map[string]string{"Content-Type": "application/json"} 529 body, _ := json.Marshal(map[string]interface{}{"name": "Pizza", "price": 12.5}) 530 resp, err := suite.Post("/product", headers, bytes.NewReader(body)) 531 suite.Nil(err) 532 if err == nil { 533 defer resp.Body.Close() 534 suite.Equal("response content", string(suite.GetBody(resp))) 535 } 536 ``` 537 538 **Testing JSON response:** 539 540 ``` go 541 suite.RunServer(route.Register, func() { 542 resp, err := suite.Get("/product", nil) 543 suite.Nil(err) 544 if err == nil { 545 defer resp.Body.Close() 546 json := map[string]interface{}{} 547 err := suite.GetJSONBody(resp, &json) 548 suite.Nil(err) 549 if err == nil { // You should always check parsing error before continuing. 550 suite.Equal("value", json["field"]) 551 suite.Equal(float64(42), json["number"]) 552 } 553 } 554 }) 555 ``` 556 557 The testing API has many more features such as record generators, factories, database helpers, a middleware tester, support for multipart and file uploads... 558 559 **Learn more about testing in the [documentation](https://goyave.dev/guide/advanced/testing.html).** 560 561 ### Status handlers 562 563 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). 564 565 The following file `http/controller/status/status.go` is an example of custom 404 error handling: 566 ``` go 567 package status 568 569 import "goyave.dev/goyave/v4" 570 571 func NotFound(response *goyave.Response, request *goyave.Request) { 572 if err := response.RenderHTML(response.GetStatus(), "errors/404.html", nil); err != nil { 573 response.Error(err) 574 } 575 } 576 ``` 577 578 Status handlers are registered in the **router**. 579 580 ``` go 581 // Use "status.NotFound" for empty responses having status 404 or 405. 582 router.StatusHandler(status.NotFound, 404) 583 ``` 584 585 **Learn more about status handlers in the [documentation](https://goyave.dev/guide/advanced/status-handlers.html).** 586 587 588 ### CORS 589 590 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. 591 592 ``` go 593 router.CORS(cors.Default()) 594 ``` 595 596 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. 597 598 `cors.Default()` can be used as a starting point for custom configuration. 599 600 ``` go 601 options := cors.Default() 602 options.AllowedOrigins = []string{"https://google.com", "https://images.google.com"} 603 router.CORS(options) 604 ``` 605 606 **Learn more about CORS in the [documentation](https://goyave.dev/guide/advanced/cors.html).** 607 608 ### Authentication 609 610 Goyave provides a convenient and expandable way of handling authentication in your application. Authentication can be enabled when registering your routes: 611 612 ``` go 613 import "goyave.dev/goyave/v4/auth" 614 615 //... 616 617 authenticator := auth.Middleware(&model.User{}, &auth.BasicAuthenticator{}) 618 router.Middleware(authenticator) 619 ``` 620 621 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. 622 623 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: 624 625 ``` go 626 type User struct { 627 gorm.Model 628 Email string `gorm:"type:char(100);uniqueIndex" auth:"username"` 629 Name string `gorm:"type:char(100)"` 630 Password string `gorm:"type:char(60)" auth:"password"` 631 } 632 ``` 633 634 When a user is successfully authenticated on a protected route, its information is available in the controller handler, through the request `User` field. 635 636 ``` go 637 func Hello(response *goyave.Response, request *goyave.Request) { 638 user := request.User.(*model.User) 639 response.String(http.StatusOK, "Hello " + user.Name) 640 } 641 ``` 642 643 **Learn more about authentication in the [documentation](https://goyave.dev/guide/advanced/authentication.html).** 644 645 ### Rate limiting 646 647 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. 648 649 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`. 650 651 The middleware will always add the following headers to the response: 652 - `RateLimit-Limit`: containing the requests quota in the time window 653 - `RateLimit-Remaining`: containing the remaining requests quota in the current window 654 - `RateLimit-Reset`: containing the time remaining in the current window, specified in seconds 655 656 ```go 657 import "goyave.dev/goyave/v4/middleware/ratelimiter" 658 659 ratelimiterMiddleware := ratelimiter.New(func(request *goyave.Request) ratelimiter.Config { 660 return ratelimiter.Config { 661 RequestQuota: 100, 662 QuotaDuration: time.Minute, 663 // 100 requests per minute allowed 664 // Client IP will be used as identifier 665 } 666 }) 667 668 router.Middleware(ratelimiterMiddleware) 669 ``` 670 671 **Learn more about rate limiting in the [documentation](https://goyave.dev/guide/advanced/rate-limiting.html).** 672 673 ### Websocket 674 675 Goyave is using [`gorilla/websocket`](https://github.com/gorilla/websocket) and adds a layer of abstraction to it to make it easier to use. You don't have to write the connection upgrading logic nor the close handshake. Just like regular HTTP handlers, websocket handlers benefit from reliable error handling and panic recovery. 676 677 Here is an example of an "echo" feature: 678 ```go 679 upgrader := websocket.Upgrader{} 680 router.Get("/websocket", upgrader.Handler(func(c *websocket.Conn, request *goyave.Request) error { 681 for { 682 mt, message, err := c.ReadMessage() 683 if err != nil { 684 return err 685 } 686 goyave.Logger.Printf("recv: %s", message) 687 err = c.WriteMessage(mt, message) 688 if err != nil { 689 return fmt.Errorf("write: %w", err) 690 } 691 } 692 })) 693 ``` 694 695 **Learn more about websockets in the [documentation](https://goyave.dev/guide/advanced/websocket.html).** 696 697 ## Contributing 698 699 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). 700 701 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. 702 703 You can support me on Github Sponsor. 704 705 <a href="https://github.com/sponsors/System-Glitch">❤ Sponsor me!</a> 706 707 I'm very grateful to my patrons, sponsors and donators: 708 709 - Ben Hyrman 710 - Massimiliano Bertinetti 711 - ethicnology 712 - Yariya 713 - sebastien-d-me 714 - Nebojša Koturović 715 716 ### Contributors 717 718 A big "Thank you" to the Goyave contributors: 719 720 - [Kuinox](https://github.com/Kuinox) (Powershell install script) 721 - [Alexandre GV.](https://github.com/alexandregv) (Install script MacOS compatibility) 722 - [jRimbault](https://github.com/jRimbault) (CI and code analysis) 723 - [Guillermo Galvan](https://github.com/gmgalvan) (Request extra data) 724 - [Albert Shirima](https://github.com/agbaraka) (Rate limiting and various contributions) 725 - [Łukasz Sowa](https://github.com/Morishiri) (Custom claims in JWT) 726 - [Zao SOULA](https://github.com/zaosoula) (Custom `gorm.Config{}` in config file) 727 - [Ajtene Kurtaliqi](https://github.com/akurtaliqi) (Documentation landing page) 728 - [Louis Laurent](https://github.com/ulphidius) ([`gyv`](https://github.com/go-goyave/gyv) productivity CLI) 729 - [Clement3](https://github.com/Clement3) (`search` feature on [`goyave.dev/filter`](https://github.com/go-goyave/filter)) 730 - [Darkweak](https://github.com/darkweak) (`HTTP cache, RFC compliant` middleware based on [Souin HTTP cache system](https://github.com/darkweak/souin)) 731 - [Jason C Keller](https://github.com/imuni4fun) (Testify interface compatibility) 732 733 ## Used by 734 735 <p align="center"> 736 <a href="https://adagio.io" target="_blank" rel="nofollow"> 737 <img src=".github/usedby/adagio.webp" alt="Adagio.io"/> 738 </a> 739 </p> 740 741 <p align="center"> 742 Do you want to be featured here? <a href="https://github.com/go-goyave/goyave/issues/new?template=used_by.md" target="_blank" rel="nofollow">Open an issue</a>. 743 </p> 744 745 ## License 746 747 The Goyave framework is MIT Licensed. Copyright © 2019 Jérémy LAMBERT (SystemGlitch)