From 8edc7a3355bd94eb95b34b74357c9e37665047e5 Mon Sep 17 00:00:00 2001 From: SystemGlitch Date: Wed, 18 Dec 2019 19:28:57 +0100 Subject: [PATCH] Build docs --- docs/404.html | 8 +- ...les.3299ef2d.css => 0.styles.591cef74.css} | 0 .../js/{10.5734a8c5.js => 10.8f124742.js} | 2 +- .../js/{11.1884cf0a.js => 11.4127e0fb.js} | 0 .../js/{12.9701ad06.js => 12.3ccb3ca2.js} | 0 docs/assets/js/13.501cb2d8.js | 1 + docs/assets/js/13.7308404a.js | 1 - docs/assets/js/14.a963d52c.js | 1 - docs/assets/js/14.e22fcc2d.js | 1 + .../js/{15.920a1396.js => 15.82da1859.js} | 2 +- .../js/{16.87fac0fb.js => 16.9d1b54dc.js} | 2 +- .../js/{17.134fa30a.js => 17.103ef510.js} | 2 +- .../js/{18.408c5054.js => 18.8a8e742b.js} | 2 +- docs/assets/js/19.157c7dbe.js | 1 - docs/assets/js/19.56b0038a.js | 1 + .../js/{2.906a9991.js => 2.6673aca7.js} | 0 .../js/{20.bee2c95f.js => 20.7f3d43e8.js} | 2 +- .../js/{21.83573c32.js => 21.f4152867.js} | 2 +- docs/assets/js/22.57006fdb.js | 1 + docs/assets/js/22.d93658d2.js | 1 - .../js/{23.52a712ea.js => 23.db2ae409.js} | 2 +- .../js/{24.1a71d20e.js => 24.8bae4600.js} | 2 +- docs/assets/js/25.0c60f0d9.js | 1 - docs/assets/js/25.2afa8687.js | 1 + docs/assets/js/26.afbc7c7d.js | 1 - docs/assets/js/26.fc20a042.js | 1 + .../js/{27.f64d5c03.js => 27.81c24ebc.js} | 2 +- .../js/{28.57bb5ec4.js => 28.a9f38de4.js} | 0 .../js/{3.e099aa3a.js => 3.7dea0142.js} | 0 .../js/{4.c70817cb.js => 4.e651b8a0.js} | 0 .../js/{5.142fa08f.js => 5.911574e0.js} | 2 +- docs/assets/js/6.26cc1488.js | 1 - docs/assets/js/6.ffa47bc6.js | 1 + .../js/{7.1f9c7719.js => 7.0624cd52.js} | 0 .../js/{8.7cf85661.js => 8.3ca2a95e.js} | 0 .../js/{9.e316c4ab.js => 9.43e11177.js} | 0 docs/assets/js/app.12b71617.js | 14 -- docs/assets/js/app.2e31ebd7.js | 14 ++ docs/guide/advanced/authentication.html | 6 +- docs/guide/advanced/helpers.html | 6 +- docs/guide/advanced/index.html | 6 +- docs/guide/advanced/localization.html | 6 +- docs/guide/advanced/multi-services.html | 6 +- docs/guide/advanced/plugins.html | 6 +- docs/guide/advanced/testing.html | 152 +++++++++++++++++- docs/guide/architecture-concepts.html | 19 ++- docs/guide/basics/controllers.html | 6 +- docs/guide/basics/database.html | 8 +- docs/guide/basics/middleware.html | 6 +- docs/guide/basics/requests.html | 6 +- docs/guide/basics/responses.html | 13 +- docs/guide/basics/routing.html | 6 +- docs/guide/basics/validation.html | 8 +- docs/guide/changelog.html | 10 +- docs/guide/configuration.html | 6 +- docs/guide/contribution-guide.html | 6 +- docs/guide/deployment.html | 8 +- docs/guide/index.html | 8 +- docs/guide/installation.html | 8 +- docs/guide/upgrade-guide.html | 6 +- docs/index.html | 8 +- 61 files changed, 269 insertions(+), 123 deletions(-) rename docs/assets/css/{0.styles.3299ef2d.css => 0.styles.591cef74.css} (100%) rename docs/assets/js/{10.5734a8c5.js => 10.8f124742.js} (99%) rename docs/assets/js/{11.1884cf0a.js => 11.4127e0fb.js} (100%) rename docs/assets/js/{12.9701ad06.js => 12.3ccb3ca2.js} (100%) create mode 100644 docs/assets/js/13.501cb2d8.js delete mode 100644 docs/assets/js/13.7308404a.js delete mode 100644 docs/assets/js/14.a963d52c.js create mode 100644 docs/assets/js/14.e22fcc2d.js rename docs/assets/js/{15.920a1396.js => 15.82da1859.js} (99%) rename docs/assets/js/{16.87fac0fb.js => 16.9d1b54dc.js} (84%) rename docs/assets/js/{17.134fa30a.js => 17.103ef510.js} (99%) rename docs/assets/js/{18.408c5054.js => 18.8a8e742b.js} (99%) delete mode 100644 docs/assets/js/19.157c7dbe.js create mode 100644 docs/assets/js/19.56b0038a.js rename docs/assets/js/{2.906a9991.js => 2.6673aca7.js} (100%) rename docs/assets/js/{20.bee2c95f.js => 20.7f3d43e8.js} (99%) rename docs/assets/js/{21.83573c32.js => 21.f4152867.js} (73%) create mode 100644 docs/assets/js/22.57006fdb.js delete mode 100644 docs/assets/js/22.d93658d2.js rename docs/assets/js/{23.52a712ea.js => 23.db2ae409.js} (99%) rename docs/assets/js/{24.1a71d20e.js => 24.8bae4600.js} (94%) delete mode 100644 docs/assets/js/25.0c60f0d9.js create mode 100644 docs/assets/js/25.2afa8687.js delete mode 100644 docs/assets/js/26.afbc7c7d.js create mode 100644 docs/assets/js/26.fc20a042.js rename docs/assets/js/{27.f64d5c03.js => 27.81c24ebc.js} (96%) rename docs/assets/js/{28.57bb5ec4.js => 28.a9f38de4.js} (100%) rename docs/assets/js/{3.e099aa3a.js => 3.7dea0142.js} (100%) rename docs/assets/js/{4.c70817cb.js => 4.e651b8a0.js} (100%) rename docs/assets/js/{5.142fa08f.js => 5.911574e0.js} (93%) delete mode 100644 docs/assets/js/6.26cc1488.js create mode 100644 docs/assets/js/6.ffa47bc6.js rename docs/assets/js/{7.1f9c7719.js => 7.0624cd52.js} (100%) rename docs/assets/js/{8.7cf85661.js => 8.3ca2a95e.js} (100%) rename docs/assets/js/{9.e316c4ab.js => 9.43e11177.js} (100%) delete mode 100644 docs/assets/js/app.12b71617.js create mode 100644 docs/assets/js/app.2e31ebd7.js diff --git a/docs/404.html b/docs/404.html index fecf3462..e35ce32c 100644 --- a/docs/404.html +++ b/docs/404.html @@ -12,11 +12,11 @@ - - + + -

404

How did we get here?
Take me home.
- +

404

Looks like we've got some broken links.
Take me home.
+ diff --git a/docs/assets/css/0.styles.3299ef2d.css b/docs/assets/css/0.styles.591cef74.css similarity index 100% rename from docs/assets/css/0.styles.3299ef2d.css rename to docs/assets/css/0.styles.591cef74.css diff --git a/docs/assets/js/10.5734a8c5.js b/docs/assets/js/10.8f124742.js similarity index 99% rename from docs/assets/js/10.5734a8c5.js rename to docs/assets/js/10.8f124742.js index 0055905c..d4f9e077 100644 --- a/docs/assets/js/10.5734a8c5.js +++ b/docs/assets/js/10.8f124742.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{227:function(a,t,e){"use strict";e.r(t);var s=e(0),n=Object(s.a)({},(function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"localization"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#localization"}},[a._v("#")]),a._v(" Localization")]),a._v(" "),e("p"),e("div",{staticClass:"table-of-contents"},[e("ul",[e("li",[e("a",{attrs:{href:"#introduction"}},[a._v("Introduction")])]),e("li",[e("a",{attrs:{href:"#writing-language-files"}},[a._v("Writing language files")]),e("ul",[e("li",[e("a",{attrs:{href:"#fields"}},[a._v("Fields")])]),e("li",[e("a",{attrs:{href:"#locale"}},[a._v("Locale")])]),e("li",[e("a",{attrs:{href:"#rules"}},[a._v("Rules")])]),e("li",[e("a",{attrs:{href:"#overrides"}},[a._v("Overrides")])])])]),e("li",[e("a",{attrs:{href:"#using-localization"}},[a._v("Using localization")]),e("ul",[e("li",[e("a",{attrs:{href:"#localization-reference"}},[a._v("Localization reference")])])])])])]),e("p"),a._v(" "),e("h2",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[a._v("#")]),a._v(" Introduction")]),a._v(" "),e("p",[a._v("The Goyave framework provides a convenient way to support multiple languages within your application. Out of the box, Goyave only provides the "),e("code",[a._v("en-US")]),a._v(" language.")]),a._v(" "),e("h2",{attrs:{id:"writing-language-files"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#writing-language-files"}},[a._v("#")]),a._v(" Writing language files")]),a._v(" "),e("p",[a._v("Language files are stored in the "),e("code",[a._v("resources/lang")]),a._v(" directory.")]),a._v(" "),e("pre",{staticClass:"vue-container"},[e("code",[e("p",[a._v(".\n└── resources\n   └── lang\n      └── en-US ("),e("em",[a._v("language name")]),a._v(")\n      ├── fields.json ("),e("em",[a._v("optional")]),a._v(")\n      ├── locale.json ("),e("em",[a._v("optional")]),a._v(")\n      └── rules.json ("),e("em",[a._v("optional")]),a._v(")")]),a._v("\n")])]),e("p",[a._v("Each language has its own directory and should be named with an "),e("a",{attrs:{href:"https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes",target:"_blank",rel:"noopener noreferrer"}},[a._v("ISO 639-1"),e("OutboundLink")],1),a._v(" language code. You can also append a variant to your languages: "),e("code",[a._v("en-US")]),a._v(", "),e("code",[a._v("en-UK")]),a._v(", "),e("code",[a._v("fr-FR")]),a._v(", "),e("code",[a._v("fr-CA")]),a._v(", ... "),e("strong",[a._v("Case is important.")])]),a._v(" "),e("p",[a._v("Each language directory contains three files. Each file is "),e("strong",[a._v("optional")]),a._v(".")]),a._v(" "),e("ul",[e("li",[e("code",[a._v("fields.json")]),a._v(": field names translations and field-specific rule messages.")]),a._v(" "),e("li",[e("code",[a._v("locale.json")]),a._v(": all other language lines.")]),a._v(" "),e("li",[e("code",[a._v("rules.json")]),a._v(": validation rules messages.")])]),a._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[a._v("TIP")]),a._v(" "),e("p",[a._v("All directories in the "),e("code",[a._v("resources/lang")]),a._v(" directory are automatically loaded when the server starts.")])]),a._v(" "),e("h3",{attrs:{id:"fields"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#fields"}},[a._v("#")]),a._v(" Fields")]),a._v(" "),e("p",[a._v("The "),e("code",[a._v("fields.json")]),a._v(" 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.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"email"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"name"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"email address"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"rules"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"required"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"You must provide an :field."')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("p",[a._v("This "),e("code",[a._v("fields.json")]),a._v(" file will change the validation message of the "),e("code",[a._v("required")]),a._v(" validation rule to "),e("code",[a._v("You must provide an email address")]),a._v(".")]),a._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[a._v("TIP")]),a._v(" "),e("p",[a._v("Learn more about validation messages placeholders in the "),e("router-link",{attrs:{to:"/guide/basics/validation.html"}},[a._v("validation")]),a._v(" section.")],1)]),a._v(" "),e("h3",{attrs:{id:"locale"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#locale"}},[a._v("#")]),a._v(" Locale")]),a._v(" "),e("p",[a._v("The "),e("code",[a._v("locale.json")]),a._v(" 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.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"product.created"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The product have been created with success."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"product.deleted"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The product have been deleted with success."')]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[a._v("TIP")]),a._v(" "),e("p",[a._v("It is a good practice to use "),e("strong",[a._v("dot-separated")]),a._v(" names for language lines to help making them clearer and more expressive.")])]),a._v(" "),e("h3",{attrs:{id:"rules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rules"}},[a._v("#")]),a._v(" Rules")]),a._v(" "),e("p",[a._v("The "),e("code",[a._v("rules.json")]),a._v(" file contains the validation rules messages. These messages can have "),e("strong",[e("router-link",{attrs:{to:"/guide/basics/validation.html#placeholders"}},[a._v("placeholders")])],1),a._v(", which will be replaced by dynamic valuesautomatically by the validator. If you write custom validation rules, their messages shall be written in this file.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"integer"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must be an integer."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"starts_with"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must start with one of the following values: :values."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"same"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field and the :other must match."')]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("h4",{attrs:{id:"type-dependent-rules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#type-dependent-rules"}},[a._v("#")]),a._v(" Type-dependent rules")]),a._v(" "),e("p",[a._v("The following rules have "),e("strong",[a._v("type-dependent")]),a._v(" messages. That means that their message is different depending on the type of the validated data.")]),a._v(" "),e("ul",[e("li",[e("code",[a._v("min")])]),a._v(" "),e("li",[e("code",[a._v("max")])]),a._v(" "),e("li",[e("code",[a._v("size")])]),a._v(" "),e("li",[e("code",[a._v("greater_than")])]),a._v(" "),e("li",[e("code",[a._v("greater_than_equal")])]),a._v(" "),e("li",[e("code",[a._v("lower_than")])]),a._v(" "),e("li",[e("code",[a._v("lower_than_equal")])])]),a._v(" "),e("p",[a._v("Type-dependent rules must have a language line for the four following types:")]),a._v(" "),e("ul",[e("li",[e("code",[a._v("string")])]),a._v(" "),e("li",[e("code",[a._v("numeric")])]),a._v(" "),e("li",[e("code",[a._v("array")])]),a._v(" "),e("li",[e("code",[a._v("file")])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.string"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must be at least :min characters."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.numeric"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must be at least :min."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must have at least :min items."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.file"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must be at least :min KiB."')]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("h4",{attrs:{id:"array-validation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#array-validation"}},[a._v("#")]),a._v(" Array validation")]),a._v(" "),e("p",[a._v("Each rule, except the file-related rules and the "),e("code",[a._v("confirmed")]),a._v(" rule, can be used to validate array values. If a rule is used to validate an array value and doesn't pass, the rule message "),e("code",[a._v("validation.rules..array")]),a._v(" (or "),e("code",[a._v("validation.rules...array")]),a._v(" if the rule is type-dependent) is returned.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.string.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field values must be at least :min characters."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.numeric.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field values must be at least :min."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.array.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field values must have at least :min items."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"digits.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field values must be digits only."')]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("h3",{attrs:{id:"overrides"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#overrides"}},[a._v("#")]),a._v(" Overrides")]),a._v(" "),e("p",[a._v("If you define the "),e("code",[a._v("en-US")]),a._v(" language in your application, the default language lines will be overriden by the ones in your language files, and all the undefined ones will be kept.")]),a._v(" "),e("p",[a._v("It is possible to load a language directory manually from another location than the stardard "),e("code",[a._v("resources/lang")]),a._v(" using the "),e("code",[a._v("lang.Load()")]),a._v(" function. If the loaded language is already available in your application, the newly loaded one will override the previous in the same manner.")]),a._v(" "),e("h2",{attrs:{id:"using-localization"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#using-localization"}},[a._v("#")]),a._v(" Using localization")]),a._v(" "),e("p",[a._v("When an incoming request enters your application, the core language middleware checks if the "),e("code",[a._v("Accept-Language")]),a._v(" header is set, and set the "),e("code",[a._v("goyave.Request")]),a._v("'s "),e("code",[a._v("Lang")]),a._v(" attribute accordingly. Localization is handled automatically by the validator.")]),a._v(" "),e("p",[a._v("To use the localization feature, import the "),e("code",[a._v("lang")]),a._v(" package:")]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("import")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"github.com/System-Glitch/goyave/v2/lang"')]),a._v("\n")])])]),e("p",[a._v("The main function of the localization feature is "),e("code",[a._v("lang.Get(language, line string)")]),a._v(". This function lets you retrieve a language entry.")]),a._v(" "),e("p",[a._v("For validation rules and attributes messages, use the following dot-separated paths:")]),a._v(" "),e("ul",[e("li",[e("code",[a._v("validation.rules.")])]),a._v(" "),e("li",[e("code",[a._v("validation.rules..string")])]),a._v(" "),e("li",[e("code",[a._v("validation.rules..numeric")])]),a._v(" "),e("li",[e("code",[a._v("validation.rules..array")])]),a._v(" "),e("li",[e("code",[a._v("validation.rules..file")])]),a._v(" "),e("li",[e("code",[a._v("validation.fields.")])]),a._v(" "),e("li",[e("code",[a._v("validation.fields..")])])]),a._v(" "),e("p",[a._v('For normal lines, just use the name of the line. Note that if you have a line called "validation", it won\'t conflict with the dot-separated paths. If the line cannot be found, or the requested language is not available, the function will return the exact '),e("code",[a._v("line")]),a._v(" attribute.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("func")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("ControllerHandler")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("response "),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("*")]),a._v("goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("Response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" request "),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("*")]),a._v("goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("Request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("StatusOK"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("Lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"my-custom-message"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("h3",{attrs:{id:"localization-reference"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#localization-reference"}},[a._v("#")]),a._v(" Localization reference")]),a._v(" "),e("div",{staticClass:"table"},[e("p",[e("a",{attrs:{href:"#lang-get"}},[a._v("Get")]),a._v(" "),e("a",{attrs:{href:"#lang-load"}},[a._v("Load")]),a._v(" "),e("a",{attrs:{href:"#lang-isavailable"}},[a._v("IsAvailable")]),a._v(" "),e("a",{attrs:{href:"#lang-getavailablelanguages"}},[a._v("GetAvailableLanguages")]),a._v(" "),e("a",{attrs:{href:"#lang-detectlanguage"}},[a._v("DetectLanguage")])])]),e("h4",{attrs:{id:"lang-get"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-get"}},[a._v("#")]),a._v(" lang.Get")]),a._v(" "),e("p",[a._v("Get a language line.")]),a._v(" "),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("lang string")])]),a._v(" "),e("td",[e("code",[a._v("string")])])]),a._v(" "),e("tr",[e("td",[e("code",[a._v("line string")])]),a._v(" "),e("td")])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("fmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"en-US"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"my-custom-message"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v('// "my message"')]),a._v("\nfmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"en-US"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"validation.rules.greater_than.string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v('// "The :field must be longer than the :other."')]),a._v("\nfmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"en-US"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"validation.fields.email"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v('// "email address"')]),a._v("\n")])])]),e("h4",{attrs:{id:"lang-load"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-load"}},[a._v("#")]),a._v(" lang.Load")]),a._v(" "),e("p",[a._v("Load a language directory.")]),a._v(" "),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("language string")])]),a._v(" "),e("td",[e("code",[a._v("void")])])]),a._v(" "),e("tr",[e("td",[e("code",[a._v("path string")])]),a._v(" "),e("td")])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Load")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"zh"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"/path/to/chinese-lang"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v("\n")])])]),e("h4",{attrs:{id:"lang-isavailable"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-isavailable"}},[a._v("#")]),a._v(" lang.IsAvailable")]),a._v(" "),e("p",[a._v("Returns true if the language is available.")]),a._v(" "),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("lang string")])]),a._v(" "),e("td",[e("code",[a._v("bool")])])])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("fmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("IsAvailable")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"zh"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// true")]),a._v("\n")])])]),e("h4",{attrs:{id:"lang-getavailablelanguages"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-getavailablelanguages"}},[a._v("#")]),a._v(" lang.GetAvailableLanguages")]),a._v(" "),e("p",[a._v("Returns a slice of all loaded languages.")]),a._v(" "),e("p",[a._v("This can be used to generate different routes for all languages supported by your applications such as:")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("/en/products\n/fr/produits\n...\n")])])]),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("lang string")])]),a._v(" "),e("td",[e("code",[a._v("bool")])])])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("fmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("GetAvailableLanguages")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// [en-US zh]")]),a._v("\n")])])]),e("h4",{attrs:{id:"lang-detectlanguage"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-detectlanguage"}},[a._v("#")]),a._v(" lang.DetectLanguage")]),a._v(" "),e("p",[a._v('DetectLanguage detects the language to use based on the given lang string.\nThe given lang string can use the HTTP "Accept-Language" header format.')]),a._v(" "),e("ul",[e("li",[a._v("If "),e("code",[a._v("*")]),a._v(" is provided, the default language will be used.")]),a._v(" "),e("li",[a._v("If multiple languages are given, the first available language will be used, and if none are available, the default language will be used.")]),a._v(" "),e("li",[a._v('If no variant is given (for example "en"), the first available variant will be used.')])]),a._v(" "),e("p",[a._v("For example, if "),e("code",[a._v("en-US")]),a._v(" and "),e("code",[a._v("en-UK")]),a._v(" are available and the request accepts "),e("code",[a._v("en")]),a._v(", "),e("code",[a._v("en-US")]),a._v(" will be used.")]),a._v(" "),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("lang string")])]),a._v(" "),e("td",[e("code",[a._v("string")])])])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("fmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("DetectLanguage")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"en, fr-FR;q=0.9"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v('// "en-US"')]),a._v("\n")])])])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{226:function(a,t,e){"use strict";e.r(t);var s=e(0),n=Object(s.a)({},(function(){var a=this,t=a.$createElement,e=a._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"localization"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#localization"}},[a._v("#")]),a._v(" Localization")]),a._v(" "),e("p"),e("div",{staticClass:"table-of-contents"},[e("ul",[e("li",[e("a",{attrs:{href:"#introduction"}},[a._v("Introduction")])]),e("li",[e("a",{attrs:{href:"#writing-language-files"}},[a._v("Writing language files")]),e("ul",[e("li",[e("a",{attrs:{href:"#fields"}},[a._v("Fields")])]),e("li",[e("a",{attrs:{href:"#locale"}},[a._v("Locale")])]),e("li",[e("a",{attrs:{href:"#rules"}},[a._v("Rules")])]),e("li",[e("a",{attrs:{href:"#overrides"}},[a._v("Overrides")])])])]),e("li",[e("a",{attrs:{href:"#using-localization"}},[a._v("Using localization")]),e("ul",[e("li",[e("a",{attrs:{href:"#localization-reference"}},[a._v("Localization reference")])])])])])]),e("p"),a._v(" "),e("h2",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[a._v("#")]),a._v(" Introduction")]),a._v(" "),e("p",[a._v("The Goyave framework provides a convenient way to support multiple languages within your application. Out of the box, Goyave only provides the "),e("code",[a._v("en-US")]),a._v(" language.")]),a._v(" "),e("h2",{attrs:{id:"writing-language-files"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#writing-language-files"}},[a._v("#")]),a._v(" Writing language files")]),a._v(" "),e("p",[a._v("Language files are stored in the "),e("code",[a._v("resources/lang")]),a._v(" directory.")]),a._v(" "),e("pre",{staticClass:"vue-container"},[e("code",[e("p",[a._v(".\n└── resources\n   └── lang\n      └── en-US ("),e("em",[a._v("language name")]),a._v(")\n      ├── fields.json ("),e("em",[a._v("optional")]),a._v(")\n      ├── locale.json ("),e("em",[a._v("optional")]),a._v(")\n      └── rules.json ("),e("em",[a._v("optional")]),a._v(")")]),a._v("\n")])]),e("p",[a._v("Each language has its own directory and should be named with an "),e("a",{attrs:{href:"https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes",target:"_blank",rel:"noopener noreferrer"}},[a._v("ISO 639-1"),e("OutboundLink")],1),a._v(" language code. You can also append a variant to your languages: "),e("code",[a._v("en-US")]),a._v(", "),e("code",[a._v("en-UK")]),a._v(", "),e("code",[a._v("fr-FR")]),a._v(", "),e("code",[a._v("fr-CA")]),a._v(", ... "),e("strong",[a._v("Case is important.")])]),a._v(" "),e("p",[a._v("Each language directory contains three files. Each file is "),e("strong",[a._v("optional")]),a._v(".")]),a._v(" "),e("ul",[e("li",[e("code",[a._v("fields.json")]),a._v(": field names translations and field-specific rule messages.")]),a._v(" "),e("li",[e("code",[a._v("locale.json")]),a._v(": all other language lines.")]),a._v(" "),e("li",[e("code",[a._v("rules.json")]),a._v(": validation rules messages.")])]),a._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[a._v("TIP")]),a._v(" "),e("p",[a._v("All directories in the "),e("code",[a._v("resources/lang")]),a._v(" directory are automatically loaded when the server starts.")])]),a._v(" "),e("h3",{attrs:{id:"fields"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#fields"}},[a._v("#")]),a._v(" Fields")]),a._v(" "),e("p",[a._v("The "),e("code",[a._v("fields.json")]),a._v(" 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.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"email"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"name"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"email address"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"rules"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"required"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"You must provide an :field."')]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("p",[a._v("This "),e("code",[a._v("fields.json")]),a._v(" file will change the validation message of the "),e("code",[a._v("required")]),a._v(" validation rule to "),e("code",[a._v("You must provide an email address")]),a._v(".")]),a._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[a._v("TIP")]),a._v(" "),e("p",[a._v("Learn more about validation messages placeholders in the "),e("router-link",{attrs:{to:"/guide/basics/validation.html"}},[a._v("validation")]),a._v(" section.")],1)]),a._v(" "),e("h3",{attrs:{id:"locale"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#locale"}},[a._v("#")]),a._v(" Locale")]),a._v(" "),e("p",[a._v("The "),e("code",[a._v("locale.json")]),a._v(" 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.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"product.created"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The product have been created with success."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"product.deleted"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The product have been deleted with success."')]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[a._v("TIP")]),a._v(" "),e("p",[a._v("It is a good practice to use "),e("strong",[a._v("dot-separated")]),a._v(" names for language lines to help making them clearer and more expressive.")])]),a._v(" "),e("h3",{attrs:{id:"rules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rules"}},[a._v("#")]),a._v(" Rules")]),a._v(" "),e("p",[a._v("The "),e("code",[a._v("rules.json")]),a._v(" file contains the validation rules messages. These messages can have "),e("strong",[e("router-link",{attrs:{to:"/guide/basics/validation.html#placeholders"}},[a._v("placeholders")])],1),a._v(", which will be replaced by dynamic valuesautomatically by the validator. If you write custom validation rules, their messages shall be written in this file.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"integer"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must be an integer."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"starts_with"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must start with one of the following values: :values."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"same"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field and the :other must match."')]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("h4",{attrs:{id:"type-dependent-rules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#type-dependent-rules"}},[a._v("#")]),a._v(" Type-dependent rules")]),a._v(" "),e("p",[a._v("The following rules have "),e("strong",[a._v("type-dependent")]),a._v(" messages. That means that their message is different depending on the type of the validated data.")]),a._v(" "),e("ul",[e("li",[e("code",[a._v("min")])]),a._v(" "),e("li",[e("code",[a._v("max")])]),a._v(" "),e("li",[e("code",[a._v("size")])]),a._v(" "),e("li",[e("code",[a._v("greater_than")])]),a._v(" "),e("li",[e("code",[a._v("greater_than_equal")])]),a._v(" "),e("li",[e("code",[a._v("lower_than")])]),a._v(" "),e("li",[e("code",[a._v("lower_than_equal")])])]),a._v(" "),e("p",[a._v("Type-dependent rules must have a language line for the four following types:")]),a._v(" "),e("ul",[e("li",[e("code",[a._v("string")])]),a._v(" "),e("li",[e("code",[a._v("numeric")])]),a._v(" "),e("li",[e("code",[a._v("array")])]),a._v(" "),e("li",[e("code",[a._v("file")])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.string"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must be at least :min characters."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.numeric"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must be at least :min."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must have at least :min items."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.file"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field must be at least :min KiB."')]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("h4",{attrs:{id:"array-validation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#array-validation"}},[a._v("#")]),a._v(" Array validation")]),a._v(" "),e("p",[a._v("Each rule, except the file-related rules and the "),e("code",[a._v("confirmed")]),a._v(" rule, can be used to validate array values. If a rule is used to validate an array value and doesn't pass, the rule message "),e("code",[a._v("validation.rules..array")]),a._v(" (or "),e("code",[a._v("validation.rules...array")]),a._v(" if the rule is type-dependent) is returned.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.string.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field values must be at least :min characters."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.numeric.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field values must be at least :min."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"min.array.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field values must have at least :min items."')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[a._v('"digits.array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v(":")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"The :field values must be digits only."')]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("h3",{attrs:{id:"overrides"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#overrides"}},[a._v("#")]),a._v(" Overrides")]),a._v(" "),e("p",[a._v("If you define the "),e("code",[a._v("en-US")]),a._v(" language in your application, the default language lines will be overriden by the ones in your language files, and all the undefined ones will be kept.")]),a._v(" "),e("p",[a._v("It is possible to load a language directory manually from another location than the stardard "),e("code",[a._v("resources/lang")]),a._v(" using the "),e("code",[a._v("lang.Load()")]),a._v(" function. If the loaded language is already available in your application, the newly loaded one will override the previous in the same manner.")]),a._v(" "),e("h2",{attrs:{id:"using-localization"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#using-localization"}},[a._v("#")]),a._v(" Using localization")]),a._v(" "),e("p",[a._v("When an incoming request enters your application, the core language middleware checks if the "),e("code",[a._v("Accept-Language")]),a._v(" header is set, and set the "),e("code",[a._v("goyave.Request")]),a._v("'s "),e("code",[a._v("Lang")]),a._v(" attribute accordingly. Localization is handled automatically by the validator.")]),a._v(" "),e("p",[a._v("To use the localization feature, import the "),e("code",[a._v("lang")]),a._v(" package:")]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("import")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"github.com/System-Glitch/goyave/v2/lang"')]),a._v("\n")])])]),e("p",[a._v("The main function of the localization feature is "),e("code",[a._v("lang.Get(language, line string)")]),a._v(". This function lets you retrieve a language entry.")]),a._v(" "),e("p",[a._v("For validation rules and attributes messages, use the following dot-separated paths:")]),a._v(" "),e("ul",[e("li",[e("code",[a._v("validation.rules.")])]),a._v(" "),e("li",[e("code",[a._v("validation.rules..string")])]),a._v(" "),e("li",[e("code",[a._v("validation.rules..numeric")])]),a._v(" "),e("li",[e("code",[a._v("validation.rules..array")])]),a._v(" "),e("li",[e("code",[a._v("validation.rules..file")])]),a._v(" "),e("li",[e("code",[a._v("validation.fields.")])]),a._v(" "),e("li",[e("code",[a._v("validation.fields..")])])]),a._v(" "),e("p",[a._v('For normal lines, just use the name of the line. Note that if you have a line called "validation", it won\'t conflict with the dot-separated paths. If the line cannot be found, or the requested language is not available, the function will return the exact '),e("code",[a._v("line")]),a._v(" attribute.")]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[a._v("func")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("ControllerHandler")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("response "),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("*")]),a._v("goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("Response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" request "),e("span",{pre:!0,attrs:{class:"token operator"}},[a._v("*")]),a._v("goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("Request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("{")]),a._v("\n response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("StatusOK"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),a._v("Lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"my-custom-message"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("}")]),a._v("\n")])])]),e("h3",{attrs:{id:"localization-reference"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#localization-reference"}},[a._v("#")]),a._v(" Localization reference")]),a._v(" "),e("div",{staticClass:"table"},[e("p",[e("a",{attrs:{href:"#lang-get"}},[a._v("Get")]),a._v(" "),e("a",{attrs:{href:"#lang-load"}},[a._v("Load")]),a._v(" "),e("a",{attrs:{href:"#lang-isavailable"}},[a._v("IsAvailable")]),a._v(" "),e("a",{attrs:{href:"#lang-getavailablelanguages"}},[a._v("GetAvailableLanguages")]),a._v(" "),e("a",{attrs:{href:"#lang-detectlanguage"}},[a._v("DetectLanguage")])])]),e("h4",{attrs:{id:"lang-get"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-get"}},[a._v("#")]),a._v(" lang.Get")]),a._v(" "),e("p",[a._v("Get a language line.")]),a._v(" "),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("lang string")])]),a._v(" "),e("td",[e("code",[a._v("string")])])]),a._v(" "),e("tr",[e("td",[e("code",[a._v("line string")])]),a._v(" "),e("td")])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("fmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"en-US"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"my-custom-message"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v('// "my message"')]),a._v("\nfmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"en-US"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"validation.rules.greater_than.string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v('// "The :field must be longer than the :other."')]),a._v("\nfmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"en-US"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"validation.fields.email"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v('// "email address"')]),a._v("\n")])])]),e("h4",{attrs:{id:"lang-load"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-load"}},[a._v("#")]),a._v(" lang.Load")]),a._v(" "),e("p",[a._v("Load a language directory.")]),a._v(" "),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("language string")])]),a._v(" "),e("td",[e("code",[a._v("void")])])]),a._v(" "),e("tr",[e("td",[e("code",[a._v("path string")])]),a._v(" "),e("td")])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Load")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"zh"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(",")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"/path/to/chinese-lang"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v("\n")])])]),e("h4",{attrs:{id:"lang-isavailable"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-isavailable"}},[a._v("#")]),a._v(" lang.IsAvailable")]),a._v(" "),e("p",[a._v("Returns true if the language is available.")]),a._v(" "),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("lang string")])]),a._v(" "),e("td",[e("code",[a._v("bool")])])])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("fmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("IsAvailable")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"zh"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// true")]),a._v("\n")])])]),e("h4",{attrs:{id:"lang-getavailablelanguages"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-getavailablelanguages"}},[a._v("#")]),a._v(" lang.GetAvailableLanguages")]),a._v(" "),e("p",[a._v("Returns a slice of all loaded languages.")]),a._v(" "),e("p",[a._v("This can be used to generate different routes for all languages supported by your applications such as:")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("/en/products\n/fr/produits\n...\n")])])]),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("lang string")])]),a._v(" "),e("td",[e("code",[a._v("bool")])])])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("fmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("GetAvailableLanguages")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v("// [en-US zh]")]),a._v("\n")])])]),e("h4",{attrs:{id:"lang-detectlanguage"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lang-detectlanguage"}},[a._v("#")]),a._v(" lang.DetectLanguage")]),a._v(" "),e("p",[a._v('DetectLanguage detects the language to use based on the given lang string.\nThe given lang string can use the HTTP "Accept-Language" header format.')]),a._v(" "),e("ul",[e("li",[a._v("If "),e("code",[a._v("*")]),a._v(" is provided, the default language will be used.")]),a._v(" "),e("li",[a._v("If multiple languages are given, the first available language will be used, and if none are available, the default language will be used.")]),a._v(" "),e("li",[a._v('If no variant is given (for example "en"), the first available variant will be used.')])]),a._v(" "),e("p",[a._v("For example, if "),e("code",[a._v("en-US")]),a._v(" and "),e("code",[a._v("en-UK")]),a._v(" are available and the request accepts "),e("code",[a._v("en")]),a._v(", "),e("code",[a._v("en-US")]),a._v(" will be used.")]),a._v(" "),e("table",[e("thead",[e("tr",[e("th",[a._v("Parameters")]),a._v(" "),e("th",[a._v("Return")])])]),a._v(" "),e("tbody",[e("tr",[e("td",[e("code",[a._v("lang string")])]),a._v(" "),e("td",[e("code",[a._v("string")])])])])]),a._v(" "),e("p",[e("strong",[a._v("Example:")])]),a._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[a._v("fmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),a._v("lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[a._v("DetectLanguage")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[a._v('"en, fr-FR;q=0.9"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[a._v(")")]),a._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[a._v('// "en-US"')]),a._v("\n")])])])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/11.1884cf0a.js b/docs/assets/js/11.4127e0fb.js similarity index 100% rename from docs/assets/js/11.1884cf0a.js rename to docs/assets/js/11.4127e0fb.js diff --git a/docs/assets/js/12.9701ad06.js b/docs/assets/js/12.3ccb3ca2.js similarity index 100% rename from docs/assets/js/12.9701ad06.js rename to docs/assets/js/12.3ccb3ca2.js diff --git a/docs/assets/js/13.501cb2d8.js b/docs/assets/js/13.501cb2d8.js new file mode 100644 index 00000000..f91ac579 --- /dev/null +++ b/docs/assets/js/13.501cb2d8.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{231:function(t,s,e){"use strict";e.r(s);var a=e(0),n=Object(a.a)({},(function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"testing"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testing"}},[t._v("#")]),t._v(" Testing "),e("Badge",{attrs:{text:"Since v2.2.0"}})],1),t._v(" "),e("p"),e("div",{staticClass:"table-of-contents"},[e("ul",[e("li",[e("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),e("li",[e("a",{attrs:{href:"#http-tests"}},[t._v("HTTP Tests")]),e("ul",[e("li",[e("a",{attrs:{href:"#request-and-response"}},[t._v("Request and response")])]),e("li",[e("a",{attrs:{href:"#timeout"}},[t._v("Timeout")])]),e("li",[e("a",{attrs:{href:"#testing-json-reponses"}},[t._v("Testing JSON reponses")])]),e("li",[e("a",{attrs:{href:"#multipart-and-file-upload"}},[t._v("Multipart and file upload")])])])]),e("li",[e("a",{attrs:{href:"#testing-middleware"}},[t._v("Testing middleware")])]),e("li",[e("a",{attrs:{href:"#testsuite-reference"}},[t._v("TestSuite reference")])]),e("li",[e("a",{attrs:{href:"#database-testing"}},[t._v("Database testing")]),e("ul",[e("li",[e("a",{attrs:{href:"#generators"}},[t._v("Generators")])]),e("li",[e("a",{attrs:{href:"#using-factories"}},[t._v("Using factories")])]),e("li",[e("a",{attrs:{href:"#seeders"}},[t._v("Seeders")])])])])])]),e("p"),t._v(" "),e("h2",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),e("p",[t._v("Goyave provides an API to ease the unit and functional testing of your application. This API is an extension of "),e("a",{attrs:{href:"https://github.com/stretchr/testify",target:"_blank",rel:"noopener noreferrer"}},[t._v("testify"),e("OutboundLink")],1),t._v(". "),e("code",[t._v("goyave.TestSuite")]),t._v(" inherits from testify's "),e("code",[t._v("suite.Suite")]),t._v(", and sets up the environment for you. That means:")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("GOYAVE_ENV")]),t._v(" environment variable is set to "),e("code",[t._v("test")]),t._v(" and restored to its original value when the suite is done.")]),t._v(" "),e("li",[t._v("All tests are run using your project's root as working directory. This directory is determined by the presence of a "),e("code",[t._v("go.mod")]),t._v(" file.")]),t._v(" "),e("li",[t._v("Config and language files are loaded before the tests start. As the environment is set to "),e("code",[t._v("test")]),t._v(", you "),e("strong",[t._v("need")]),t._v(" a "),e("code",[t._v("config.test.json")]),t._v(" in the root directory of your project.")])]),t._v(" "),e("p",[t._v("This setup is done by the function "),e("code",[t._v("goyave.RunTest")]),t._v(", so you shouldn't run your test suites using testify's "),e("code",[t._v("suite.Run()")]),t._v(" function.")]),t._v(" "),e("p",[t._v("The following example is a "),e("strong",[t._v("functional")]),t._v(" test and would be located in the "),e("code",[t._v("test")]),t._v(" package.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my-project/http/route"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" CustomTestSuite "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tgoyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("TestSuite\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("suite "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("CustomTestSuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("TestHello")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("RunServer")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("route"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tresp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/hello"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NotNil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" resp "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("200")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" resp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusCode"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hi!"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetBody")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("TestCustomSuite")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("testing"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("T"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tgoyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("RunTest")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("CustomTestSuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("We will explain in more details what this test does in the following sections, but in short, this test runs the server, registers all your application routes and executes the second parameter as a server startup hook. The test requests the "),e("code",[t._v("/hello")]),t._v(" route with the method "),e("code",[t._v("GET")]),t._v(" and checks the content of the response. The server automatically shuts down after the hook is executed and before "),e("code",[t._v("RunServer")]),t._v(" returns. See the available assertions in the "),e("a",{attrs:{href:"https://godoc.org/github.com/stretchr/testify",target:"_blank",rel:"noopener noreferrer"}},[t._v("testify's documentation"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("p",[t._v("This test is a "),e("strong",[t._v("functional")]),t._v(" test. Therefore, it requires route registration and should be located in the "),e("code",[t._v("test")]),t._v(" package.")]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),e("p",[t._v("You cannot run Goyave test suites in parallel.")])]),t._v(" "),e("h2",{attrs:{id:"http-tests"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#http-tests"}},[t._v("#")]),t._v(" HTTP Tests")]),t._v(" "),e("p",[t._v("As shown in the example in the introduction, you can easily run a test server and send requests to it using the "),e("code",[t._v("suite.RunServer()")]),t._v(" function.")]),t._v(" "),e("p",[t._v("This function takes two parameters.")]),t._v(" "),e("ul",[e("li",[t._v("The first is a route registrer function. You should always use your main route registrer to avoid unexpected problems with inherited middleware and route groups.")]),t._v(" "),e("li",[t._v("The second parameter is a startup hook for the server, in which you will be running your test procedure.")])]),t._v(" "),e("p",[t._v("This function is the equivalent of "),e("code",[t._v("goyave.Start")]),t._v(", but doesn't require a "),e("code",[t._v("goyave.Stop()")]),t._v(" call: the server stops automatically when the startup hook is finished. All startup hooks are then cleared. The function returns when the server is properly shut down.")]),t._v(" "),e("p",[t._v("If you registered startup hooks in your main function, these won't be executed. If you need them for your tests, you need to register them before calling "),e("code",[t._v("suite.RunServer()")]),t._v(".")]),t._v(" "),e("h3",{attrs:{id:"request-and-response"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#request-and-response"}},[t._v("#")]),t._v(" Request and response")]),t._v(" "),e("p",[t._v("There are helper functions for the following HTTP methods:")]),t._v(" "),e("ul",[e("li",[t._v("GET")]),t._v(" "),e("li",[t._v("POST")]),t._v(" "),e("li",[t._v("PUT")]),t._v(" "),e("li",[t._v("PATCH")]),t._v(" "),e("li",[t._v("DELETE")])]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("route string")])]),t._v(" "),e("td",[e("code",[t._v("*http.Response")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("headers map[string]string")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("body io.Reader")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("em",[t._v("Note")]),t._v(": The "),e("code",[t._v("Get")]),t._v(" function doesn't have a third parameter as GET requests shouldn't have a body. The headers and body are optional, and can be "),e("code",[t._v("nil")]),t._v(".")]),t._v(" "),e("p",[t._v("The response body can be retrieved easily using "),e("a",{attrs:{href:"#suite-getbody"}},[e("code",[t._v("suite.GetBody(response)")])]),t._v(".")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("resp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/get"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"response content"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetBody")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("headers "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Content-Type"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"application/x-www-form-urlencoded; param=value"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nresp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Post")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/product"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headers"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" strings"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewReader")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field=value"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"response content"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetBody")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("If you need to test another method, you can use the "),e("a",{attrs:{href:"#testsuite-request"}},[e("code",[t._v("suite.Request()")])]),t._v(" function.")]),t._v(" "),e("h3",{attrs:{id:"timeout"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#timeout"}},[t._v("#")]),t._v(" Timeout")]),t._v(" "),e("p",[e("code",[t._v("goyave.TestSuite")]),t._v(" has a default timeout value of "),e("strong",[t._v("5 seconds")]),t._v(". This timeout is used for the "),e("code",[t._v("RunServer")]),t._v(" function as well as for the request functions("),e("code",[t._v("Get")]),t._v(", "),e("code",[t._v("Post")]),t._v(", etc.). If the timeout expires, the test fails. This prevents your test from freezing if something goes wrong.")]),t._v(" "),e("p",[t._v("The timeout can be modified as needed using "),e("code",[t._v("suite.SetTimeout()")]),t._v(":")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetTimeout")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" time"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h3",{attrs:{id:"testing-json-reponses"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testing-json-reponses"}},[t._v("#")]),t._v(" Testing JSON reponses")]),t._v(" "),e("p",[t._v("It is very likely that you will need to check the content of a JSON response when testing your application. Instead of unmarshaling the JSON yourself, Goyave provides the "),e("a",{attrs:{href:"#suite-getjsonbody"}},[e("code",[t._v("suite.GetJSONBody")])]),t._v(" function. This function decodes the raw body of the request. If the data cannot be decoded, or is invalid JSON, the test fails and the function retuns "),e("code",[t._v("nil")]),t._v(".")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("RunServer")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("route"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tresp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/product"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tjson "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\terr "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetJSONBody")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("json"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You should always check parsing error before continuing.")]),t._v("\n\t\t\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" json"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("float64")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("42")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" json"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"number"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h3",{attrs:{id:"multipart-and-file-upload"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#multipart-and-file-upload"}},[t._v("#")]),t._v(" Multipart and file upload")]),t._v(" "),e("p",[t._v("You may need to test requests requiring file uploads. The best way to do this is using Go's "),e("code",[t._v("multipart.Writer")]),t._v(". Goyave provides functions to help you create a Multipart form.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("RunServer")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("route"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" path "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"profile.png"')]),t._v("\n\tbody "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("bytes"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\twriter "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" multipart"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewWriter")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("body"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("WriteField")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("writer"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"email"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"johndoe@example.org"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("WriteFile")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("writer"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" path"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"profile_picture"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" filepath"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Base")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\terr "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" writer"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Don\'t forget to set the "Content-Type" header!')]),t._v("\n\theaders "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Content-Type"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" writer"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("FormDataContentType")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\tresp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Post")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/register"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" headers"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" body"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Welcome!"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetBody")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("resp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("You can write a multi-file upload by calling "),e("code",[t._v("suite.WriteFile")]),t._v(" successively using the same field name.")])]),t._v(" "),e("h2",{attrs:{id:"testing-middleware"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testing-middleware"}},[t._v("#")]),t._v(" Testing middleware")]),t._v(" "),e("p",[t._v("You can unit-test middleware using the "),e("a",{attrs:{href:"#suite-middleware"}},[e("code",[t._v("suite.Middleware")])]),t._v(" function. This function passes a "),e("code",[t._v("*goyave.Request")]),t._v(" to your middlware and returns the "),e("code",[t._v("*http.Response")]),t._v(". This function also takes a test procedure function as a parameter. This function will simulate a "),e("strong",[t._v("controller handler")]),t._v(", so you can test if the middleware alters the request.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("rawRequest "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" httptest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewRequest")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/test-route"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrawRequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Set")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Content-Type"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"application/json"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrequest "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("CreateTestRequest")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("rawRequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"text"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('" \\n test \\t"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\nresult "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Trim"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"application/json"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Header")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Content-Type"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"text"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Equal")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("200")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" result"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusCode"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("If you want to test a blocking middleware, flag the test as failed in the test procedure. Indeed, the procedure shouldn't be executed if your middleware doesn't pass to the next handler.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("request "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" suite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("CreateTestRequest")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Auth"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fail")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Auth middleware passed"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h2",{attrs:{id:"testsuite-reference"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-reference"}},[t._v("#")]),t._v(" TestSuite reference")]),t._v(" "),e("div",{staticClass:"table"},[e("p",[e("a",{attrs:{href:"#testsuite-runserver"}},[t._v("RunServer")]),t._v(" "),e("a",{attrs:{href:"#testsuite-timeout"}},[t._v("Timeout")]),t._v(" "),e("a",{attrs:{href:"#testsuite-settimeout"}},[t._v("SetTimeout")]),t._v(" "),e("a",{attrs:{href:"#testsuite-middleware"}},[t._v("Middleware")]),t._v(" "),e("a",{attrs:{href:"#testsuite-get"}},[t._v("Get")]),t._v(" "),e("a",{attrs:{href:"#testsuite-post"}},[t._v("Post")]),t._v(" "),e("a",{attrs:{href:"#testsuite-put"}},[t._v("Put")]),t._v(" "),e("a",{attrs:{href:"#testsuite-patch"}},[t._v("Patch")]),t._v(" "),e("a",{attrs:{href:"#testsuite-delete"}},[t._v("Delete")]),t._v(" "),e("a",{attrs:{href:"#testsuite-request"}},[t._v("Request")]),t._v(" "),e("a",{attrs:{href:"#testsuite-getbody"}},[t._v("GetBody")]),t._v(" "),e("a",{attrs:{href:"#testsuite-getjsonbody"}},[t._v("GetJSONBody")]),t._v(" "),e("a",{attrs:{href:"#testsuite-createtestfiles"}},[t._v("CreateTestFiles")]),t._v(" "),e("a",{attrs:{href:"#testsuite-createtestrequest"}},[t._v("CreateTestRequest")]),t._v(" "),e("a",{attrs:{href:"#testsuite-createtestResponse"}},[t._v("CreateTestResponse")]),t._v(" "),e("a",{attrs:{href:"#testsuite-writefile"}},[t._v("WriteFile")]),t._v(" "),e("a",{attrs:{href:"#testsuite-writefield"}},[t._v("WriteField")]),t._v(" "),e("a",{attrs:{href:"#testsuite-cleardatabase"}},[t._v("ClearDatabase")]),t._v(" "),e("a",{attrs:{href:"#goyave-runtest"}},[t._v("RunTest")])])]),e("h4",{attrs:{id:"testsuite-runserver"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-runserver"}},[t._v("#")]),t._v(" TestSuite.RunServer")]),t._v(" "),e("p",[t._v("RunServer start the application and run the given functional test procedure.")]),t._v(" "),e("p",[t._v("This function is the equivalent of "),e("code",[t._v("goyave.Start()")]),t._v("."),e("br"),t._v("\nThe test fails if the suite's timeout is exceeded."),e("br"),t._v("\nThe server automatically shuts down when the function ends."),e("br"),t._v("\nThis function is synchronized, that means that the server is properly stopped when the function returns.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("routeRegistrer func(*goyave.Router)")])]),t._v(" "),e("td",[e("code",[t._v("void")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("procedure func()")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-timeout"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-timeout"}},[t._v("#")]),t._v(" TestSuite.Timeout")]),t._v(" "),e("p",[t._v("Get the timeout for test failure when using RunServer or requests.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td"),t._v(" "),e("td",[e("code",[t._v("time.Duration")])])])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-settimeout"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-settimeout"}},[t._v("#")]),t._v(" TestSuite.SetTimeout")]),t._v(" "),e("p",[t._v("Set the timeout for test failure when using RunServer or requests.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("time.Duration")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-middleware"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-middleware"}},[t._v("#")]),t._v(" TestSuite.Middleware")]),t._v(" "),e("p",[t._v("Executes the given middleware and returns the HTTP response. Core middleware (recovery, parsing and language) is not executed.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("middleware goyave.Middleware")])]),t._v(" "),e("td",[e("code",[t._v("*http.Response")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("request *goyave.Request")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("procedure goyave.Handler")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-get"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-get"}},[t._v("#")]),t._v(" TestSuite.Get")]),t._v(" "),e("p",[t._v("Execute a GET request on the given route. Headers are optional.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("route string")])]),t._v(" "),e("td",[e("code",[t._v("*http.Response")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("headers map[string]string")])]),t._v(" "),e("td",[e("code",[t._v("error")])])])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-post"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-post"}},[t._v("#")]),t._v(" TestSuite.Post")]),t._v(" "),e("p",[t._v("Execute a POST request on the given route. Headers and body are optional.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("route string")])]),t._v(" "),e("td",[e("code",[t._v("*http.Response")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("headers map[string]string")])]),t._v(" "),e("td",[e("code",[t._v("error")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("body io.Reader")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-put"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-put"}},[t._v("#")]),t._v(" TestSuite.Put")]),t._v(" "),e("p",[t._v("Execute a PUT request on the given route. Headers and body are optional.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("route string")])]),t._v(" "),e("td",[e("code",[t._v("*http.Response")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("headers map[string]string")])]),t._v(" "),e("td",[e("code",[t._v("error")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("body io.Reader")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-patch"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-patch"}},[t._v("#")]),t._v(" TestSuite.Patch")]),t._v(" "),e("p",[t._v("Execute a PATCH request on the given route. Headers and body are optional.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("route string")])]),t._v(" "),e("td",[e("code",[t._v("*http.Response")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("headers map[string]string")])]),t._v(" "),e("td",[e("code",[t._v("error")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("body io.Reader")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-delete"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-delete"}},[t._v("#")]),t._v(" TestSuite.Delete")]),t._v(" "),e("p",[t._v("Execute a DELETE request on the given route. Headers and body are optional.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("route string")])]),t._v(" "),e("td",[e("code",[t._v("*http.Response")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("headers map[string]string")])]),t._v(" "),e("td",[e("code",[t._v("error")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("body io.Reader")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-request"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-request"}},[t._v("#")]),t._v(" TestSuite.Request")]),t._v(" "),e("p",[t._v("Execute a request on the given route. Headers and body are optional.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("method string")])]),t._v(" "),e("td",[e("code",[t._v("*http.Response")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("route string")])]),t._v(" "),e("td",[e("code",[t._v("error")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("headers map[string]string")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("body io.Reader")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-getbody"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-getbody"}},[t._v("#")]),t._v(" TestSuite.GetBody")]),t._v(" "),e("p",[t._v("Read the whole body of a response. If read failed, test fails and return empty byte slice.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("response *http.Response")])]),t._v(" "),e("td",[e("code",[t._v("[]byte")])])])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-getjsonbody"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-getjsonbody"}},[t._v("#")]),t._v(" TestSuite.GetJSONBody")]),t._v(" "),e("p",[t._v("Read the whole body of a response and decode it as JSON. If read or decode failed, test fails. The "),e("code",[t._v("data")]),t._v(" parameter should be a pointer.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("response *http.Response")])]),t._v(" "),e("td",[e("code",[t._v("error")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("data interface{}")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-createtestfiles"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-createtestfiles"}},[t._v("#")]),t._v(" TestSuite.CreateTestFiles")]),t._v(" "),e("p",[t._v("Create a slice of "),e("code",[t._v("filesystem.File")]),t._v(" from the given paths. Files are passed to a temporary http request and parsed as Multipart form, to reproduce the way files are obtained in real scenarios.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("paths ...string")])]),t._v(" "),e("td",[e("code",[t._v("[]filesystem.File")])])])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-createtestrequest"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-createtestrequest"}},[t._v("#")]),t._v(" TestSuite.CreateTestRequest")]),t._v(" "),e("p",[t._v("Create a "),e("code",[t._v("*goyave.Request")]),t._v(" from the given raw request. This function is aimed at making it easier to unit test Requests.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("rawRequest *http.Request")])]),t._v(" "),e("td",[e("code",[t._v("*goyave.Request")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("rawRequest "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" httptest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewRequest")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/test-route"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrawRequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Set")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Content-Type"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"application/json"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrequest "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("CreateTestRequest")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("rawRequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lang "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"en-US"')]),t._v("\nrequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h4",{attrs:{id:"testsuite-createtestresponse"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-createtestresponse"}},[t._v("#")]),t._v(" TestSuite.CreateTestResponse")]),t._v(" "),e("p",[t._v("Create an empty response with the given response writer. This function is aimed at making it easier to unit test Responses.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("recorder http.ResponseWriter")])]),t._v(" "),e("td",[e("code",[t._v("*goyave.Response")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("writer "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" httptest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewRecorder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nresponse "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("CreateTestResponse")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("writer"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nresponse"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusNoContent"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nresult "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" writer"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Result")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nfmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusCode"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 204")]),t._v("\n")])])]),e("h4",{attrs:{id:"testsuite-writefile"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-writefile"}},[t._v("#")]),t._v(" TestSuite.WriteFile")]),t._v(" "),e("p",[t._v("Write a file to the given writer. This function is handy for file upload testing. The test fails if an error occurred.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("write *multipart.Writer")])]),t._v(" "),e("td",[e("code",[t._v("void")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("path string")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("fieldName string")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("fileName string")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-writefield"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-writefield"}},[t._v("#")]),t._v(" TestSuite.WriteField")]),t._v(" "),e("p",[t._v("Create and write a new multipart form field. The test fails if the field couldn't be written.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("write *multipart.Writer")])]),t._v(" "),e("td",[e("code",[t._v("void")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("fieldName string")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("value string")])]),t._v(" "),e("td")])])]),t._v(" "),e("h4",{attrs:{id:"testsuite-cleardatabase"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#testsuite-cleardatabase"}},[t._v("#")]),t._v(" TestSuite.ClearDatabase")]),t._v(" "),e("p",[t._v("delete all records in all tables. This function only clears the tables of registered models.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td"),t._v(" "),e("td",[e("code",[t._v("void")])])])])]),t._v(" "),e("h4",{attrs:{id:"goyave-runtest"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#goyave-runtest"}},[t._v("#")]),t._v(" goyave.RunTest")]),t._v(" "),e("p",[t._v('Run a test suite with prior initialization of a test environment. The GOYAVE_ENV environment variable is automatically set to "test" and restored to its original value at the end of the test run.')]),t._v(" "),e("p",[t._v("All tests are run using your project's root as working directory. This directory is determined by the presence of a "),e("code",[t._v("go.mod")]),t._v(" file.")]),t._v(" "),e("p",[t._v("The function returns true if the test passed.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("t *testing.T")])]),t._v(" "),e("td",[e("code",[t._v("bool")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("suite ITestSuite")])]),t._v(" "),e("td")])])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[e("code",[t._v("ITestSuite")]),t._v(" is the interface "),e("code",[t._v("TestSuite")]),t._v(" is implementing.")])]),t._v(" "),e("h2",{attrs:{id:"database-testing"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#database-testing"}},[t._v("#")]),t._v(" Database testing")]),t._v(" "),e("p",[t._v("You may need to test features interacting with your database. Goyave provides a handy way to generate and save records in your database: "),e("strong",[t._v("factories")]),t._v(".")]),t._v(" "),e("p",[e("strong",[t._v("All registered models records are automatically deleted from the database when each test suite completes.")])]),t._v(" "),e("p",[t._v("It is a good practice to use a separate database dedicated for testing, named "),e("code",[t._v("myapp_test")]),t._v(" for example. Don't forget to change the database information in your "),e("code",[t._v("config.test.json")]),t._v(" file.")]),t._v(" "),e("p",[t._v("All functions below require the "),e("code",[t._v("database")]),t._v("package to be imported.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/database"')]),t._v("\n")])])]),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("You may want to use a clean database for each of your tests. You can clear your database before each test using "),e("a",{attrs:{href:"https://godoc.org/github.com/stretchr/testify/suite#SetupTestSuite",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("suite.SetupTest()")]),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("suite "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("CustomTestSuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetupTest")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tsuite"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("ClearDatabase")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]),t._v(" "),e("h3",{attrs:{id:"generators"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#generators"}},[t._v("#")]),t._v(" Generators")]),t._v(" "),e("p",[t._v("Factories need a "),e("strong",[t._v("generator function")]),t._v(". These functions generate a single random record. You can use the faking library of your choice, but in this example we are going to use "),e("a",{attrs:{href:"https://github.com/bxcodec/faker",target:"_blank",rel:"noopener noreferrer"}},[e("code",[t._v("github.com/bxcodec/faker")]),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/bxcodec/faker/v3"')]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("UserGenerator")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tuser "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("User"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tuser"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Name "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" faker"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\tfaker"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetGenerateUniqueValues")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tuser"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Email "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" faker"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Email")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfaker"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetGenerateUniqueValues")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" user\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("database.Generator")]),t._v(" is an alias for "),e("code",[t._v("func() interface{}")]),t._v(".")]),t._v(" "),e("li",[t._v("Generator functions should be declared in the same file as the model it is generating.")])])]),t._v(" "),e("p",[t._v("Generators can also create associated records. Associated records should be generated using their respective generators. In the following example, we are generating users for an application allowing users to write blog posts.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("UserGenerator")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tuser "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("User"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ... Generate users fields ...")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate between 0 and 10 blog posts")]),t._v("\n\trand"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Seed")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Now")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("UnixNano")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tuser"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Posts "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" database"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewFactory")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("PostGenerator"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Generate")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("rand"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Intn")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" user\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h3",{attrs:{id:"using-factories"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#using-factories"}},[t._v("#")]),t._v(" Using factories")]),t._v(" "),e("p",[t._v("You can create a factory from any "),e("code",[t._v("database.Generator")]),t._v(".")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("factory "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" database"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewFactory")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("model"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("UserGenerator"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate 5 random users")]),t._v("\nrecords "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" factory"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Generate")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate and insert 5 random users into the database")]),t._v("\ninsertedRecords "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" factory"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Save")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("p",[t._v("Note that generated records will not have an ID if they are not inserted into the database.")]),t._v(" "),e("p",[t._v("Associated records created by the generator will also be inserted on "),e("code",[t._v("factory.Save")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"overrides"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#overrides"}},[t._v("#")]),t._v(" Overrides")]),t._v(" "),e("p",[t._v("It is possible to override some of the generated data if needed, for example if you need to test the behavior of a function with a specific value. All generated structures will be merged with the override.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("override "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("model"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tName"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Jérémy"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nrecords "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" factory"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Override")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("override"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Generate")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// All generated records will have the same name: "Jérémy"')]),t._v("\n")])])]),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),e("p",[t._v("Overrides must be of the "),e("strong",[t._v("same type")]),t._v(" as the generated record.")])]),t._v(" "),e("h4",{attrs:{id:"factory-reference"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#factory-reference"}},[t._v("#")]),t._v(" Factory reference")]),t._v(" "),e("div",{staticClass:"table"},[e("p",[e("a",{attrs:{href:"#database-newfactory"}},[t._v("NewFactory")]),t._v(" "),e("a",{attrs:{href:"#factory-override"}},[t._v("Override")])])]),e("h4",{attrs:{id:"database-newfactory"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#database-newfactory"}},[t._v("#")]),t._v(" database.NewFactory")]),t._v(" "),e("p",[t._v("Create a new Factory. The given generator function will be used to generate records.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("generator database.Generator")])]),t._v(" "),e("td",[e("code",[t._v("database.Factory")])])])])]),t._v(" "),e("h4",{attrs:{id:"factory-override"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#factory-override"}},[t._v("#")]),t._v(" Factory.Override")]),t._v(" "),e("p",[t._v("Set an override model for generated records. Values present in the override model will replace the ones in the generated records. This function expects a struct "),e("strong",[t._v("pointer")]),t._v(" as parameter. This function returns the same instance of "),e("code",[t._v("Factory")]),t._v(" so this method can be chained.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("override interface{}")])]),t._v(" "),e("td",[e("code",[t._v("database.Factory")])])])])]),t._v(" "),e("h4",{attrs:{id:"factory-generate"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#factory-generate"}},[t._v("#")]),t._v(" Factory.Generate")]),t._v(" "),e("p",[t._v("Generate a number of records using the given factory.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("count uint")])]),t._v(" "),e("td",[e("code",[t._v("[]interface{}")])])])])]),t._v(" "),e("h4",{attrs:{id:"factory-save"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#factory-save"}},[t._v("#")]),t._v(" Factory.Save")]),t._v(" "),e("p",[t._v("Generate a number of records using the given factory and return the inserted records.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("count uint")])]),t._v(" "),e("td",[e("code",[t._v("[]interface{}")])])])])]),t._v(" "),e("h3",{attrs:{id:"seeders"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#seeders"}},[t._v("#")]),t._v(" Seeders")]),t._v(" "),e("p",[t._v("Seeders are functions which create a number of random records in the database in order to create a full and realistic test environment. Seeders are written in the "),e("code",[t._v("database/seeder")]),t._v(" package.")]),t._v(" "),e("p",[t._v("Each seeder should have its own file. A seeder's responsabilities are limited to a single table or model. For example, the "),e("code",[t._v("seeder.User")]),t._v(" should only seed the "),e("code",[t._v("users")]),t._v(" table. Moreover, seeders should have the same name as the model they are using.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" seeder\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my-project/database/model"')]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/database"')]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("User")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tdatabase"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewFactory")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("model"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("UserGenerator"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Save")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/13.7308404a.js b/docs/assets/js/13.7308404a.js deleted file mode 100644 index 378ec43b..00000000 --- a/docs/assets/js/13.7308404a.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{217:function(t,e,s){"use strict";s.r(e);var a=s(0),r=Object(a.a)({},(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"testing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#testing"}},[t._v("#")]),t._v(" Testing")]),t._v(" "),s("p",{staticStyle:{"text-align":"center"}},[s("img",{attrs:{src:t.$withBase("/undraw_in_progress_ql66.svg"),height:"150",alt:"In progress"}})]),t._v(" "),s("div",{staticClass:"custom-block warning"},[s("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),s("p",[t._v("This feature is not implemented yet and is coming in a future release.")]),t._v(" "),s("p",[s("a",{attrs:{href:"https://github.com/System-Glitch/goyave",target:"_blank",rel:"noopener noreferrer"}},[t._v("Watch"),s("OutboundLink")],1),t._v(" the github repository to stay updated.")])]),t._v(" "),s("h2",{attrs:{id:"database-testing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#database-testing"}},[t._v("#")]),t._v(" Database testing")]),t._v(" "),s("h3",{attrs:{id:"factories"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#factories"}},[t._v("#")]),t._v(" Factories")]),t._v(" "),s("h3",{attrs:{id:"seeders"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#seeders"}},[t._v("#")]),t._v(" Seeders")])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/14.a963d52c.js b/docs/assets/js/14.a963d52c.js deleted file mode 100644 index 596074cb..00000000 --- a/docs/assets/js/14.a963d52c.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{228:function(e,t,a){"use strict";a.r(t);var r=a(0),o=Object(r.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"architecture-concepts"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#architecture-concepts"}},[e._v("#")]),e._v(" Architecture Concepts")]),e._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[e._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#terminology"}},[e._v("Terminology")])]),a("li",[a("a",{attrs:{href:"#lifecycle"}},[e._v("Lifecycle")]),a("ul",[a("li",[a("a",{attrs:{href:"#server"}},[e._v("Server")])]),a("li",[a("a",{attrs:{href:"#requests"}},[e._v("Requests")])])])]),a("li",[a("a",{attrs:{href:"#directory-structure"}},[e._v("Directory structure")]),a("ul",[a("li",[a("a",{attrs:{href:"#database-directory"}},[e._v("Database directory")])]),a("li",[a("a",{attrs:{href:"#http-directory"}},[e._v("HTTP directory")])]),a("li",[a("a",{attrs:{href:"#resources-directory"}},[e._v("Resources directory")])]),a("li",[a("a",{attrs:{href:"#custom-directories"}},[e._v("Custom directories")])])])]),a("li",[a("a",{attrs:{href:"#database"}},[e._v("Database")])])])]),a("p"),e._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),a("p",[e._v("Understanding your development tools and knowing what happens in the background is crucial. Mastering your tools and environment incredibily decreases the risk of errors, the ease of debugging and helps making your code work in harmony with the framework. The goal of this section is to give you an overview of the general functioning and design of the framework, to make you more comfortable and confident using it.")]),e._v(" "),a("h2",{attrs:{id:"terminology"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#terminology"}},[e._v("#")]),e._v(" Terminology")]),e._v(" "),a("p",[e._v("This section will briefly explain the technical words used in the following sections.")]),e._v(" "),a("p",[a("strong",[e._v("Lifecycle")]),e._v(": An execution from start to finish, with intermediary steps.")]),e._v(" "),a("p",[a("strong",[e._v("Framework core")]),e._v(": Features and behaviors executed internally and that are invisible to the application developer.")]),e._v(" "),a("p",[a("strong",[e._v("Handler")]),e._v(": A function receiving incoming requests and a response writer. Multiple handlers can be executed for the same request.")]),e._v(" "),a("p",[a("strong",[e._v("Router")]),e._v(": The root-level handler responsible for the execution of the correct controller handler.")]),e._v(" "),a("p",[a("strong",[e._v("Route")]),e._v(": A URI definition linked to a controller handler. If a request matches the definition, the router will execute the associated controller handler.")]),e._v(" "),a("p",[a("strong",[e._v("Controller")]),e._v(": A source file implementing the business logic linked to a specific resource and associated routes.")]),e._v(" "),a("p",[a("strong",[e._v("Middleware")]),e._v(": A handler executed before controller handlers. Middleware can intercept the request, modify its data, and send a response before the controller handler is reached.")]),e._v(" "),a("p",[a("strong",[e._v("Application")]),e._v(": A program using the Goyave framework as a library.")]),e._v(" "),a("p",[a("strong",[e._v("Model")]),e._v(": A structure reflecting a database table structure. An instance of a model is a single database record.")]),e._v(" "),a("h2",{attrs:{id:"lifecycle"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#lifecycle"}},[e._v("#")]),e._v(" Lifecycle")]),e._v(" "),a("h3",{attrs:{id:"server"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#server"}},[e._v("#")]),e._v(" Server")]),e._v(" "),a("p",[e._v("The very first step of the server lifecycle is the "),a("strong",[e._v("server setup")]),e._v(", taking place when you call "),a("code",[e._v("goyave.Start(route.Register)")]),e._v(" in your application's main function.")]),e._v(" "),a("p",[e._v("Goyave starts by loading the "),a("router-link",{attrs:{to:"/guide/configuration.html"}},[e._v("configuration")]),e._v(" file from the core of the framework. The application's configuration file is then loaded, overriding the default values.")],1),e._v(" "),a("p",[e._v("The second step of the initialization takes a very similar approach to load the "),a("a",{attrs:{href:"./advanced/localization.hmtl"}},[e._v("language")]),e._v(" files. The "),a("code",[e._v("en-US")]),e._v(" language is available by default inside the framework and is used as the default language. When it's loaded, the framework will look for custom language files inside the working directory and will override the "),a("code",[e._v("en-US")]),e._v(" language entries if needed.")]),e._v(" "),a("p",[e._v("Then, if enabled, the automatic migrations are run, thus creating the "),a("router-link",{attrs:{to:"/guide/basics/database.html"}},[e._v("database")]),e._v(" connection pool. If the automatic migrations are not enabled, no connection to the database will be established until the application requires one.")],1),e._v(" "),a("p",[e._v("That is only now that "),a("router-link",{attrs:{to:"/guide/basics/routing.html"}},[e._v("routes")]),e._v(" are registered using the route registrer provided to the "),a("code",[e._v("Start()")]),e._v(" function. That means that at this registrer has already access to all the configuration and language features, which can be handy if you want to generate different routes based on the languages your application supports.")],1),e._v(" "),a("p",[e._v("Finally, the framework starts listening for incoming HTTP requests and serves them. The server also listens for interruption and termination signals so it can finish serving ongoing requests before shutting down gracefully. In the next section, we will get into more details about the lifecycle of each request.")]),e._v(" "),a("h3",{attrs:{id:"requests"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#requests"}},[e._v("#")]),e._v(" Requests")]),e._v(" "),a("p",[e._v("When an incoming request is received, it's first passed through the "),a("a",{attrs:{href:"https://github.com/gorilla/mux",target:"_blank",rel:"noopener noreferrer"}},[e._v("Gorilla Mux"),a("OutboundLink")],1),e._v(" router so your server knows which handler to execute when a user requests a specific URI. Then, the framework's internal handler creates a "),a("code",[e._v("goyave.Request")]),e._v(" object and a "),a("code",[e._v("goyave.Response")]),e._v(" object from the raw request. These two objects are fundamental features of the framework as you are going to use them to retrieve the requests' data and write your responses.")]),e._v(" "),a("p",[e._v("Before executing the handler, the middleware are executed. The framework features a few core middleware, which are executed "),a("strong",[e._v("first")]),e._v(" and for all routes and all requests.")]),e._v(" "),a("h4",{attrs:{id:"_1-recovery"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-recovery"}},[e._v("#")]),e._v(" 1. Recovery")]),e._v(" "),a("p",[e._v("The "),a("strong",[e._v("recovery")]),e._v(" middleware is executed. This middleware ensures that any unrecovered panic is handled. Instead of never returning a response in case of a panic, the server will then return an HTTP 500 Error. If debugging is enabled if the configuration, the response will contain the error message and the stacktrace will be printed in the console. It's important to keep this behavior in mind when handling errors in your handlers.")]),e._v(" "),a("h4",{attrs:{id:"_2-parsing"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-parsing"}},[e._v("#")]),e._v(" 2. Parsing")]),e._v(" "),a("p",[e._v("The request is "),a("strong",[e._v("parsed")]),e._v(" by a second middleware. This middleware will automatically detect the request's body format based on the headers and attempt to parse it. If the request can't be parsed, the request's data is simply set to "),a("code",[e._v("nil")]),e._v(". This middleware supports JSON requests.")]),e._v(" "),a("h4",{attrs:{id:"_3-language"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_3-language"}},[e._v("#")]),e._v(" 3. Language")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("Accept-Language")]),e._v(" header is checked. If it's there, its value is parsed and the request's language attribute is set accordingly so localization is easy in the following handlers. If the header is missing, invalid, or asks for an unsupported language, the framework falls back to the default language defined in the configuration. Learn more "),a("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h4",{attrs:{id:"_4-application-middlewares"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_4-application-middlewares"}},[e._v("#")]),e._v(" 4. Application middlewares")]),e._v(" "),a("p",[e._v("Application middlewares are executed. These middlewares are implemented and defined by the application developer. Note that some application middleware are already available in the framework. Learn more in the "),a("router-link",{attrs:{to:"/guide/basics/middleware.html"}},[e._v("middlewares")]),e._v(" section. At this stage of the lifecycle, the request is not validated yet, so application middleware can be used for authentication or automatic string trimming for example. Bear in mind that manipulating unvalidated data can be dangerous, especially in form-data where the data types are not converted by the validator yet.")],1),e._v(" "),a("h4",{attrs:{id:"_5-validation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_5-validation"}},[e._v("#")]),e._v(" 5. Validation")]),e._v(" "),a("p",[e._v("The data is validated last. The validation middleware immediately passes if no rules have been defined for the current route, else, it check if the data parsing was successful. An automatic response is sent if that is not the case. The data is passed through the validator, which converts the data types and validates it. The request is stopped if the validation is not successful, and the validation errors are sent as a response. Be careful when working with unvalidated requests (which you should never do!) because if the request's parsing fails, "),a("code",[e._v("request.Data")]),e._v(" will be "),a("code",[e._v("nil")]),e._v(".")]),e._v(" "),a("h4",{attrs:{id:"_6-controller-handler"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_6-controller-handler"}},[e._v("#")]),e._v(" 6. Controller handler")]),e._v(" "),a("p",[e._v("Finally, if the request has not been stopped by a middleware, the controller handler is executed.\nIf the controller handler didn't write anything as a response, an empty response with the HTTP status code 204 \"No Content\" is automatically sent, so you don't have to do it yourself.")]),e._v(" "),a("h2",{attrs:{id:"directory-structure"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#directory-structure"}},[e._v("#")]),e._v(" Directory structure")]),e._v(" "),a("p",[e._v('Goyave follows the principle of "'),a("strong",[e._v("Convention is better than configuration")]),e._v('". That means that the framework will attempt to automatically get the resources it needs from predefined directories.\nThe typical and recommended directory structure for Goyave applications is as follows:')]),e._v(" "),a("pre",{staticClass:"vue-container"},[a("code",[a("p",[e._v(".\n├── database\n│   └── model\n│   └── "),a("em",[e._v("...")]),e._v("\n├── http\n│   ├── controller\n│   │ └── "),a("em",[e._v("...")]),e._v("\n│   ├── middleware\n│   │ └── "),a("em",[e._v("...")]),e._v("\n│   ├── request\n│   │   ├── placeholders.go ("),a("em",[e._v("optional")]),e._v(")\n│   │   ├── validation.go ("),a("em",[e._v("optional")]),e._v(")\n│   │ └── "),a("em",[e._v("...")]),e._v("\n│   └── route\n│   └── routes.go\n│\n├── resources\n│   ├── lang\n│   │   └── en-US ("),a("em",[e._v("language name")]),e._v(")\n│   │   ├── fields.json ("),a("em",[e._v("optional")]),e._v(")\n│   │   ├── locale.json ("),a("em",[e._v("optional")]),e._v(")\n│   │   └── rules.json ("),a("em",[e._v("optional")]),e._v(")\n│   └── img ("),a("em",[e._v("optional")]),e._v(")\n│      └── "),a("em",[e._v("...")]),e._v("\n│ \n├── .gitignore\n├── config.json\n├── go.mod\n└── kernel.go")]),e._v("\n")])]),a("h3",{attrs:{id:"database-directory"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database-directory"}},[e._v("#")]),e._v(" Database directory")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("database")]),e._v(" directory stores the models. Each model should have its own file in the "),a("code",[e._v("models")]),e._v(" package. This directory can also contain database-related code such as repositories, if you want to use this pattern.")]),e._v(" "),a("h3",{attrs:{id:"http-directory"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-directory"}},[e._v("#")]),e._v(" HTTP directory")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http")]),e._v(" directory contains all the HTTP-related code. This is where most of your code will be written.")]),e._v(" "),a("h4",{attrs:{id:"http-controllers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-controllers"}},[e._v("#")]),e._v(" HTTP controllers")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http/controller")]),e._v(" directory contains the controller packages. Each feature should have its own package. For example, if you have a controller handling user registration, user profiles, etc, you should create a "),a("code",[e._v("http/controller/user")]),e._v(" 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. Learn more "),a("router-link",{attrs:{to:"/guide/basics/controllers.html"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h4",{attrs:{id:"http-middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-middleware"}},[e._v("#")]),e._v(" HTTP middleware")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http/middleware")]),e._v(" directory contains the application middleware. Each middleware should have its own file. Learn more "),a("router-link",{attrs:{to:"/guide/basics/middleware.html"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h4",{attrs:{id:"http-request"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-request"}},[e._v("#")]),e._v(" HTTP request")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http/request")]),e._v(" directory contains the requests validation rules sets. You should have one package per feature, regrouping all requests handled by the same controller.")]),e._v(" "),a("p",[e._v("This directory can also contain a "),a("code",[e._v("placeholders.go")]),e._v(" file, which will define validation rule messages placeholders. Learn more "),a("router-link",{attrs:{to:"/guide/basics/validation.html#placeholders"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("p",[e._v("This directory can also contain a "),a("code",[e._v("validation.go")]),e._v(" file, which will define custom validation rules. Learn more "),a("router-link",{attrs:{to:"/guide/basics/validation.html#custom-rules"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h4",{attrs:{id:"http-routes"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-routes"}},[e._v("#")]),e._v(" HTTP Routes")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http/route")]),e._v(" directory contains the routes définitions. By default, all routes are registered in the "),a("code",[e._v("route.go")]),e._v(" file, but for bigger projects, split the route definitions into multiple files.")]),e._v(" "),a("h3",{attrs:{id:"resources-directory"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#resources-directory"}},[e._v("#")]),e._v(" Resources directory")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("resources")]),e._v(" directory is meant to store static resources such as images, HTML documents and language files. This directory shouldn't be used as a storage for dynamic content such as user profile pictures.")]),e._v(" "),a("h4",{attrs:{id:"language-resources-directory"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#language-resources-directory"}},[e._v("#")]),e._v(" Language resources directory")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("resources/lang")]),e._v(" directory contains your application's supported languages and translations. Each language has its own directory and should be named with an "),a("a",{attrs:{href:"https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes",target:"_blank",rel:"noopener noreferrer"}},[e._v("ISO 639-1"),a("OutboundLink")],1),e._v(" language code. You can also append a variant to your languages: "),a("code",[e._v("en-US")]),e._v(", "),a("code",[e._v("en-UK")]),e._v(", "),a("code",[e._v("fr-FR")]),e._v(", "),a("code",[e._v("fr-CA")]),e._v(", ... "),a("strong",[e._v("Case is important.")])]),e._v(" "),a("p",[e._v("Each language directory contains three files. Each file is "),a("strong",[e._v("optional")]),e._v(".")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("fields.json")]),e._v(": field names translations and field-specific rule messages.")]),e._v(" "),a("li",[a("code",[e._v("locale.json")]),e._v(": all other language lines.")]),e._v(" "),a("li",[a("code",[e._v("rules.json")]),e._v(": validation rules messages.")])]),e._v(" "),a("p",[e._v("Learn more about localization "),a("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h3",{attrs:{id:"custom-directories"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#custom-directories"}},[e._v("#")]),e._v(" Custom directories")]),e._v(" "),a("p",[e._v("You may add custom directories for your custom utilities, as they don't belong to any of the above directories. For example, if you develop a service manipulating images, the image processing code shouldn't be written in controller handlers, they are not part of the business logic. You would then create a "),a("code",[e._v("processing")]),e._v(" directory, containing your code in "),a("code",[e._v("images.go")]),e._v(" for example.")]),e._v(" "),a("h2",{attrs:{id:"database"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database"}},[e._v("#")]),e._v(" Database")]),e._v(" "),a("p",[e._v("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.")]),e._v(" "),a("p",[e._v("If automatic migrations are enabled, all registered models at the time of startup will be auto-migrated. They must be registered before the server starts, ideally from an "),a("code",[e._v("init()")]),e._v(" function next to each model definition.")]),e._v(" "),a("p",[e._v("Learn more in the "),a("router-link",{attrs:{to:"/guide/basics/database.html"}},[e._v("database")]),e._v(" section.")],1)])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/14.e22fcc2d.js b/docs/assets/js/14.e22fcc2d.js new file mode 100644 index 00000000..0c77a40a --- /dev/null +++ b/docs/assets/js/14.e22fcc2d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{227:function(e,t,a){"use strict";a.r(t);var r=a(0),o=Object(r.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"architecture-concepts"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#architecture-concepts"}},[e._v("#")]),e._v(" Architecture Concepts")]),e._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[e._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#terminology"}},[e._v("Terminology")])]),a("li",[a("a",{attrs:{href:"#lifecycle"}},[e._v("Lifecycle")]),a("ul",[a("li",[a("a",{attrs:{href:"#server"}},[e._v("Server")])]),a("li",[a("a",{attrs:{href:"#requests"}},[e._v("Requests")])])])]),a("li",[a("a",{attrs:{href:"#directory-structure"}},[e._v("Directory structure")]),a("ul",[a("li",[a("a",{attrs:{href:"#database-directory"}},[e._v("Database directory")])]),a("li",[a("a",{attrs:{href:"#http-directory"}},[e._v("HTTP directory")])]),a("li",[a("a",{attrs:{href:"#resources-directory"}},[e._v("Resources directory")])]),a("li",[a("a",{attrs:{href:"#test-directory"}},[e._v("Test directory")])]),a("li",[a("a",{attrs:{href:"#custom-directories"}},[e._v("Custom directories")])])])]),a("li",[a("a",{attrs:{href:"#database"}},[e._v("Database")])])])]),a("p"),e._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),a("p",[e._v("Understanding your development tools and knowing what happens in the background is crucial. Mastering your tools and environment incredibily decreases the risk of errors, the ease of debugging and helps making your code work in harmony with the framework. The goal of this section is to give you an overview of the general functioning and design of the framework, to make you more comfortable and confident using it.")]),e._v(" "),a("h2",{attrs:{id:"terminology"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#terminology"}},[e._v("#")]),e._v(" Terminology")]),e._v(" "),a("p",[e._v("This section will briefly explain the technical words used in the following sections.")]),e._v(" "),a("p",[a("strong",[e._v("Lifecycle")]),e._v(": An execution from start to finish, with intermediary steps.")]),e._v(" "),a("p",[a("strong",[e._v("Framework core")]),e._v(": Features and behaviors executed internally and that are invisible to the application developer.")]),e._v(" "),a("p",[a("strong",[e._v("Handler")]),e._v(": A function receiving incoming requests and a response writer. Multiple handlers can be executed for the same request.")]),e._v(" "),a("p",[a("strong",[e._v("Router")]),e._v(": The root-level handler responsible for the execution of the correct controller handler.")]),e._v(" "),a("p",[a("strong",[e._v("Route")]),e._v(": A URI definition linked to a controller handler. If a request matches the definition, the router will execute the associated controller handler.")]),e._v(" "),a("p",[a("strong",[e._v("Controller")]),e._v(": A source file implementing the business logic linked to a specific resource and associated routes.")]),e._v(" "),a("p",[a("strong",[e._v("Middleware")]),e._v(": A handler executed before controller handlers. Middleware can intercept the request, modify its data, and send a response before the controller handler is reached.")]),e._v(" "),a("p",[a("strong",[e._v("Application")]),e._v(": A program using the Goyave framework as a library.")]),e._v(" "),a("p",[a("strong",[e._v("Model")]),e._v(": A structure reflecting a database table structure. An instance of a model is a single database record.")]),e._v(" "),a("p",[a("strong",[e._v("Seeder")]),e._v(": A function which creates a number of random records in the database.")]),e._v(" "),a("h2",{attrs:{id:"lifecycle"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#lifecycle"}},[e._v("#")]),e._v(" Lifecycle")]),e._v(" "),a("h3",{attrs:{id:"server"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#server"}},[e._v("#")]),e._v(" Server")]),e._v(" "),a("p",[e._v("The very first step of the server lifecycle is the "),a("strong",[e._v("server setup")]),e._v(", taking place when you call "),a("code",[e._v("goyave.Start(route.Register)")]),e._v(" in your application's main function.")]),e._v(" "),a("p",[e._v("Goyave starts by loading the "),a("router-link",{attrs:{to:"/guide/configuration.html"}},[e._v("configuration")]),e._v(" file from the core of the framework. The application's configuration file is then loaded, overriding the default values.")],1),e._v(" "),a("p",[e._v("The second step of the initialization takes a very similar approach to load the "),a("a",{attrs:{href:"./advanced/localization.hmtl"}},[e._v("language")]),e._v(" files. The "),a("code",[e._v("en-US")]),e._v(" language is available by default inside the framework and is used as the default language. When it's loaded, the framework will look for custom language files inside the working directory and will override the "),a("code",[e._v("en-US")]),e._v(" language entries if needed.")]),e._v(" "),a("p",[e._v("Then, if enabled, the automatic migrations are run, thus creating the "),a("router-link",{attrs:{to:"/guide/basics/database.html"}},[e._v("database")]),e._v(" connection pool. If the automatic migrations are not enabled, no connection to the database will be established until the application requires one.")],1),e._v(" "),a("p",[e._v("That is only now that "),a("router-link",{attrs:{to:"/guide/basics/routing.html"}},[e._v("routes")]),e._v(" are registered using the route registrer provided to the "),a("code",[e._v("Start()")]),e._v(" function. That means that at this registrer has already access to all the configuration and language features, which can be handy if you want to generate different routes based on the languages your application supports.")],1),e._v(" "),a("p",[e._v("Finally, the framework starts listening for incoming HTTP requests and serves them. The server also listens for interruption and termination signals so it can finish serving ongoing requests before shutting down gracefully. In the next section, we will get into more details about the lifecycle of each request.")]),e._v(" "),a("h3",{attrs:{id:"requests"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#requests"}},[e._v("#")]),e._v(" Requests")]),e._v(" "),a("p",[e._v("When an incoming request is received, it's first passed through the "),a("a",{attrs:{href:"https://github.com/gorilla/mux",target:"_blank",rel:"noopener noreferrer"}},[e._v("Gorilla Mux"),a("OutboundLink")],1),e._v(" router so your server knows which handler to execute when a user requests a specific URI. Then, the framework's internal handler creates a "),a("code",[e._v("goyave.Request")]),e._v(" object and a "),a("code",[e._v("goyave.Response")]),e._v(" object from the raw request. These two objects are fundamental features of the framework as you are going to use them to retrieve the requests' data and write your responses.")]),e._v(" "),a("p",[e._v("Before executing the handler, the middleware are executed. The framework features a few core middleware, which are executed "),a("strong",[e._v("first")]),e._v(" and for all routes and all requests.")]),e._v(" "),a("h4",{attrs:{id:"_1-recovery"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_1-recovery"}},[e._v("#")]),e._v(" 1. Recovery")]),e._v(" "),a("p",[e._v("The "),a("strong",[e._v("recovery")]),e._v(" middleware is executed. This middleware ensures that any unrecovered panic is handled. Instead of never returning a response in case of a panic, the server will then return an HTTP 500 Error. If debugging is enabled if the configuration, the response will contain the error message and the stacktrace will be printed in the console. It's important to keep this behavior in mind when handling errors in your handlers.")]),e._v(" "),a("h4",{attrs:{id:"_2-parsing"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_2-parsing"}},[e._v("#")]),e._v(" 2. Parsing")]),e._v(" "),a("p",[e._v("The request is "),a("strong",[e._v("parsed")]),e._v(" by a second middleware. This middleware will automatically detect the request's body format based on the headers and attempt to parse it. If the request can't be parsed, the request's data is simply set to "),a("code",[e._v("nil")]),e._v(". This middleware supports JSON requests.")]),e._v(" "),a("h4",{attrs:{id:"_3-language"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_3-language"}},[e._v("#")]),e._v(" 3. Language")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("Accept-Language")]),e._v(" header is checked. If it's there, its value is parsed and the request's language attribute is set accordingly so localization is easy in the following handlers. If the header is missing, invalid, or asks for an unsupported language, the framework falls back to the default language defined in the configuration. Learn more "),a("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h4",{attrs:{id:"_4-application-middlewares"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_4-application-middlewares"}},[e._v("#")]),e._v(" 4. Application middlewares")]),e._v(" "),a("p",[e._v("Application middlewares are executed. These middlewares are implemented and defined by the application developer. Note that some application middleware are already available in the framework. Learn more in the "),a("router-link",{attrs:{to:"/guide/basics/middleware.html"}},[e._v("middlewares")]),e._v(" section. At this stage of the lifecycle, the request is not validated yet, so application middleware can be used for authentication or automatic string trimming for example. Bear in mind that manipulating unvalidated data can be dangerous, especially in form-data where the data types are not converted by the validator yet.")],1),e._v(" "),a("h4",{attrs:{id:"_5-validation"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_5-validation"}},[e._v("#")]),e._v(" 5. Validation")]),e._v(" "),a("p",[e._v("The data is validated last. The validation middleware immediately passes if no rules have been defined for the current route, else, it check if the data parsing was successful. An automatic response is sent if that is not the case. The data is passed through the validator, which converts the data types and validates it. The request is stopped if the validation is not successful, and the validation errors are sent as a response. Be careful when working with unvalidated requests (which you should never do!) because if the request's parsing fails, "),a("code",[e._v("request.Data")]),e._v(" will be "),a("code",[e._v("nil")]),e._v(".")]),e._v(" "),a("h4",{attrs:{id:"_6-controller-handler"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#_6-controller-handler"}},[e._v("#")]),e._v(" 6. Controller handler")]),e._v(" "),a("p",[e._v("Finally, if the request has not been stopped by a middleware, the controller handler is executed.\nIf the controller handler didn't write anything as a response, an empty response with the HTTP status code 204 \"No Content\" is automatically sent, so you don't have to do it yourself.")]),e._v(" "),a("h2",{attrs:{id:"directory-structure"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#directory-structure"}},[e._v("#")]),e._v(" Directory structure")]),e._v(" "),a("p",[e._v('Goyave follows the principle of "'),a("strong",[e._v("Convention is better than configuration")]),e._v('". That means that the framework will attempt to automatically get the resources it needs from predefined directories.\nThe typical and recommended directory structure for Goyave applications is as follows:')]),e._v(" "),a("pre",{staticClass:"vue-container"},[a("code",[a("p",[e._v(".\n├── database\n│   ├── model\n│   | └── "),a("em",[e._v("...")]),e._v("\n│   └── seeder\n│   └── "),a("em",[e._v("...")]),e._v("\n├── http\n│   ├── controller\n│   │ └── "),a("em",[e._v("...")]),e._v("\n│   ├── middleware\n│   │ └── "),a("em",[e._v("...")]),e._v("\n│   ├── request\n│   │   ├── placeholders.go ("),a("em",[e._v("optional")]),e._v(")\n│   │   ├── validation.go ("),a("em",[e._v("optional")]),e._v(")\n│   │ └── "),a("em",[e._v("...")]),e._v("\n│   └── route\n│   └── routes.go\n│\n├── resources\n│   ├── lang\n│   │   └── en-US ("),a("em",[e._v("language name")]),e._v(")\n│   │   ├── fields.json ("),a("em",[e._v("optional")]),e._v(")\n│   │   ├── locale.json ("),a("em",[e._v("optional")]),e._v(")\n│   │   └── rules.json ("),a("em",[e._v("optional")]),e._v(")\n│   └── img ("),a("em",[e._v("optional")]),e._v(")\n│      └── "),a("em",[e._v("...")]),e._v("\n│\n├── test\n| └── "),a("em",[e._v("...")]),e._v("\n|\n├── .gitignore\n├── config.json\n├── go.mod\n└── kernel.go")]),e._v("\n")])]),a("h3",{attrs:{id:"database-directory"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database-directory"}},[e._v("#")]),e._v(" Database directory")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("database")]),e._v(" directory stores source files related to the database. If you don't want to use auto-migrations, you can also store SQL scripts there. This directory can also contain database-related code such as repositories, if you want to use this pattern.")]),e._v(" "),a("p",[e._v("Each model should have its own file in the "),a("code",[e._v("model")]),e._v(" package.")]),e._v(" "),a("p",[e._v("Each seeder should have its own file in the "),a("code",[e._v("seeder")]),e._v(" package.")]),e._v(" "),a("h3",{attrs:{id:"http-directory"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-directory"}},[e._v("#")]),e._v(" HTTP directory")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http")]),e._v(" directory contains all the HTTP-related code. This is where most of your code will be written.")]),e._v(" "),a("h4",{attrs:{id:"http-controllers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-controllers"}},[e._v("#")]),e._v(" HTTP controllers")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http/controller")]),e._v(" directory contains the controller packages. Each feature should have its own package. For example, if you have a controller handling user registration, user profiles, etc, you should create a "),a("code",[e._v("http/controller/user")]),e._v(" 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. Learn more "),a("router-link",{attrs:{to:"/guide/basics/controllers.html"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h4",{attrs:{id:"http-middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-middleware"}},[e._v("#")]),e._v(" HTTP middleware")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http/middleware")]),e._v(" directory contains the application middleware. Each middleware should have its own file. Learn more "),a("router-link",{attrs:{to:"/guide/basics/middleware.html"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h4",{attrs:{id:"http-request"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-request"}},[e._v("#")]),e._v(" HTTP request")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http/request")]),e._v(" directory contains the requests validation rules sets. You should have one package per feature, regrouping all requests handled by the same controller.")]),e._v(" "),a("p",[e._v("This directory can also contain a "),a("code",[e._v("placeholders.go")]),e._v(" file, which will define validation rule messages placeholders. Learn more "),a("router-link",{attrs:{to:"/guide/basics/validation.html#placeholders"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("p",[e._v("This directory can also contain a "),a("code",[e._v("validation.go")]),e._v(" file, which will define custom validation rules. Learn more "),a("router-link",{attrs:{to:"/guide/basics/validation.html#custom-rules"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h4",{attrs:{id:"http-routes"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http-routes"}},[e._v("#")]),e._v(" HTTP Routes")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("http/route")]),e._v(" directory contains the routes définitions. By default, all routes are registered in the "),a("code",[e._v("route.go")]),e._v(" file, but for bigger projects, split the route definitions into multiple files.")]),e._v(" "),a("h3",{attrs:{id:"resources-directory"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#resources-directory"}},[e._v("#")]),e._v(" Resources directory")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("resources")]),e._v(" directory is meant to store static resources such as images, HTML documents and language files. This directory shouldn't be used as a storage for dynamic content such as user profile pictures.")]),e._v(" "),a("h4",{attrs:{id:"language-resources-directory"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#language-resources-directory"}},[e._v("#")]),e._v(" Language resources directory")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("resources/lang")]),e._v(" directory contains your application's supported languages and translations. Each language has its own directory and should be named with an "),a("a",{attrs:{href:"https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes",target:"_blank",rel:"noopener noreferrer"}},[e._v("ISO 639-1"),a("OutboundLink")],1),e._v(" language code. You can also append a variant to your languages: "),a("code",[e._v("en-US")]),e._v(", "),a("code",[e._v("en-UK")]),e._v(", "),a("code",[e._v("fr-FR")]),e._v(", "),a("code",[e._v("fr-CA")]),e._v(", ... "),a("strong",[e._v("Case is important.")])]),e._v(" "),a("p",[e._v("Each language directory contains three files. Each file is "),a("strong",[e._v("optional")]),e._v(".")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("fields.json")]),e._v(": field names translations and field-specific rule messages.")]),e._v(" "),a("li",[a("code",[e._v("locale.json")]),e._v(": all other language lines.")]),e._v(" "),a("li",[a("code",[e._v("rules.json")]),e._v(": validation rules messages.")])]),e._v(" "),a("p",[e._v("Learn more about localization "),a("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("h3",{attrs:{id:"test-directory"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#test-directory"}},[e._v("#")]),e._v(" Test directory")]),e._v(" "),a("p",[e._v("This directory is a package for "),a("strong",[e._v("functional")]),e._v(" tests. Functional tests test your application from an outside perspective. That means that your functional tests will make direct HTTP requests to your application and check the result. Unit tests should be located next to your source files.")]),e._v(" "),a("h3",{attrs:{id:"custom-directories"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#custom-directories"}},[e._v("#")]),e._v(" Custom directories")]),e._v(" "),a("p",[e._v("You may add custom directories for your custom utilities, as they don't belong to any of the above directories. For example, if you develop a service manipulating images, the image processing code shouldn't be written in controller handlers, they are not part of the business logic. You would then create a "),a("code",[e._v("processing")]),e._v(" directory, containing your code in "),a("code",[e._v("images.go")]),e._v(" for example.")]),e._v(" "),a("h2",{attrs:{id:"database"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database"}},[e._v("#")]),e._v(" Database")]),e._v(" "),a("p",[e._v("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.")]),e._v(" "),a("p",[e._v("If automatic migrations are enabled, all registered models at the time of startup will be auto-migrated. They must be registered before the server starts, ideally from an "),a("code",[e._v("init()")]),e._v(" function next to each model definition.")]),e._v(" "),a("p",[e._v("Learn more in the "),a("router-link",{attrs:{to:"/guide/basics/database.html"}},[e._v("database")]),e._v(" section.")],1)])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/15.920a1396.js b/docs/assets/js/15.82da1859.js similarity index 99% rename from docs/assets/js/15.920a1396.js rename to docs/assets/js/15.82da1859.js index 0ee978a2..35de291a 100644 --- a/docs/assets/js/15.920a1396.js +++ b/docs/assets/js/15.82da1859.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{218:function(t,s,a){"use strict";a.r(s);var n=a(0),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"controllers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#controllers"}},[t._v("#")]),t._v(" Controllers")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#defining-controllers"}},[t._v("Defining controllers")])]),a("li",[a("a",{attrs:{href:"#handlers"}},[t._v("Handlers")])]),a("li",[a("a",{attrs:{href:"#naming-conventions"}},[t._v("Naming conventions")])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"defining-controllers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#defining-controllers"}},[t._v("#")]),t._v(" Defining controllers")]),t._v(" "),a("p",[t._v("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 "),a("code",[t._v("http/controller/user")]),t._v(" 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.")]),t._v(" "),a("p",[t._v("Let's take a very simple CRUD as an example for a controller definition:\n"),a("strong",[t._v("http/controllers/product/product.go")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Store")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n product "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" model"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Price"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Numeric")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"price"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusCreated"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Show")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n product "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" model"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ParseUint")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("First")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RecordNotFound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusNotFound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("JSON")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Update")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ParseUint")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n product "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" model"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n db "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" db"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Select")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("First")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RecordNotFound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusNotFound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n db"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Model")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Update")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Destroy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ParseUint")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n product "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" model"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n db "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" db"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Select")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("First")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RecordNotFound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusNotFound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n db"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Delete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("Learn how to handle database errors "),a("a",{attrs:{href:"https://gorm.io/docs/error_handling.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(".")])]),t._v(" "),a("h2",{attrs:{id:"handlers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#handlers"}},[t._v("#")]),t._v(" Handlers")]),t._v(" "),a("p",[t._v("A "),a("code",[t._v("Handler")]),t._v(" is a "),a("code",[t._v("func(*goyave.Response, *goyave.Request)")]),t._v(". The first parameter lets you write a response, and the second contains all the information extracted from the raw incoming request.")]),t._v(" "),a("p",[t._v("Read about the available request information in the "),a("router-link",{attrs:{to:"/guide/basics/requests.html"}},[t._v("Requests")]),t._v(" section.")],1),t._v(" "),a("p",[t._v("Controller handlers contain the business logic of your application. They should be concise and focused on what matters for this particular feature in your application. For example, if you develop a service manipulating images, the image processing code shouldn't be written in controller handlers. In that case, the controller handler would simply pass the correct parameters to your image processor and write a response.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This handler receives an image, optimizes it and sends the result back.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OptimizeImage")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n optimizedImg "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" processing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OptimizeImage")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("File")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" optimizedImg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("Setting the "),a("code",[t._v("Content-Type")]),t._v(" header is not necessary. "),a("code",[t._v("response.Write")]),t._v(" automatically detects the content type and sets the header accordingly, if the latter has not been defined already.")])]),t._v(" "),a("h2",{attrs:{id:"naming-conventions"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#naming-conventions"}},[t._v("#")]),t._v(" Naming conventions")]),t._v(" "),a("ul",[a("li",[t._v("Controller packages are named after the model they are mostly using, in a singular form. For example a controller for a "),a("code",[t._v("Product")]),t._v(" model would be called "),a("code",[t._v("http/controllers/product")]),t._v(". If a controller isn't related to a model, then give it an expressive name.")]),t._v(" "),a("li",[t._v("Controller handlers are always "),a("strong",[t._v("exported")]),t._v(" so they can be used when registering routes. All functions which aren't handlers "),a("strong",[t._v("must be unexported")]),t._v(".")]),t._v(" "),a("li",[t._v("CRUD operations naming and routing:")])]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Method")]),t._v(" "),a("th",[t._v("URI")]),t._v(" "),a("th",[t._v("Handler name")]),t._v(" "),a("th",[t._v("Description")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("GET")])]),t._v(" "),a("td",[a("code",[t._v("/product")])]),t._v(" "),a("td",[a("code",[t._v("Index()")])]),t._v(" "),a("td",[t._v("Get the products list")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("POST")])]),t._v(" "),a("td",[a("code",[t._v("/product")])]),t._v(" "),a("td",[a("code",[t._v("Store()")])]),t._v(" "),a("td",[t._v("Create a product")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("GET")])]),t._v(" "),a("td",[a("code",[t._v("/product/{id}")])]),t._v(" "),a("td",[a("code",[t._v("Show()")])]),t._v(" "),a("td",[t._v("Show a product")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("PUT")]),t._v(" or "),a("code",[t._v("PATCH")])]),t._v(" "),a("td",[a("code",[t._v("/product/{id}")])]),t._v(" "),a("td",[a("code",[t._v("Update()")])]),t._v(" "),a("td",[t._v("Update a product")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("DELETE")])]),t._v(" "),a("td",[a("code",[t._v("/product/{id}")])]),t._v(" "),a("td",[a("code",[t._v("Destroy()")])]),t._v(" "),a("td",[t._v("Delete a product")])])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{217:function(t,s,a){"use strict";a.r(s);var n=a(0),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"controllers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#controllers"}},[t._v("#")]),t._v(" Controllers")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#defining-controllers"}},[t._v("Defining controllers")])]),a("li",[a("a",{attrs:{href:"#handlers"}},[t._v("Handlers")])]),a("li",[a("a",{attrs:{href:"#naming-conventions"}},[t._v("Naming conventions")])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"defining-controllers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#defining-controllers"}},[t._v("#")]),t._v(" Defining controllers")]),t._v(" "),a("p",[t._v("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 "),a("code",[t._v("http/controller/user")]),t._v(" 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.")]),t._v(" "),a("p",[t._v("Let's take a very simple CRUD as an example for a controller definition:\n"),a("strong",[t._v("http/controllers/product/product.go")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Store")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n product "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" model"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Price"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Numeric")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"price"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusCreated"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Show")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n product "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" model"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ParseUint")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("First")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RecordNotFound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusNotFound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("JSON")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Update")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ParseUint")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n product "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" model"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n db "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" db"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Select")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("First")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RecordNotFound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusNotFound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n db"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Model")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Update")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Destroy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ParseUint")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n product "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" model"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n db "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" db"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Select")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("First")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" id"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RecordNotFound")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusNotFound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n db"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Delete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("product"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("Learn how to handle database errors "),a("a",{attrs:{href:"https://gorm.io/docs/error_handling.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(".")])]),t._v(" "),a("h2",{attrs:{id:"handlers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#handlers"}},[t._v("#")]),t._v(" Handlers")]),t._v(" "),a("p",[t._v("A "),a("code",[t._v("Handler")]),t._v(" is a "),a("code",[t._v("func(*goyave.Response, *goyave.Request)")]),t._v(". The first parameter lets you write a response, and the second contains all the information extracted from the raw incoming request.")]),t._v(" "),a("p",[t._v("Read about the available request information in the "),a("router-link",{attrs:{to:"/guide/basics/requests.html"}},[t._v("Requests")]),t._v(" section.")],1),t._v(" "),a("p",[t._v("Controller handlers contain the business logic of your application. They should be concise and focused on what matters for this particular feature in your application. For example, if you develop a service manipulating images, the image processing code shouldn't be written in controller handlers. In that case, the controller handler would simply pass the correct parameters to your image processor and write a response.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This handler receives an image, optimizes it and sends the result back.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OptimizeImage")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n optimizedImg "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" processing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OptimizeImage")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("File")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" optimizedImg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("Setting the "),a("code",[t._v("Content-Type")]),t._v(" header is not necessary. "),a("code",[t._v("response.Write")]),t._v(" automatically detects the content type and sets the header accordingly, if the latter has not been defined already.")])]),t._v(" "),a("h2",{attrs:{id:"naming-conventions"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#naming-conventions"}},[t._v("#")]),t._v(" Naming conventions")]),t._v(" "),a("ul",[a("li",[t._v("Controller packages are named after the model they are mostly using, in a singular form. For example a controller for a "),a("code",[t._v("Product")]),t._v(" model would be called "),a("code",[t._v("http/controllers/product")]),t._v(". If a controller isn't related to a model, then give it an expressive name.")]),t._v(" "),a("li",[t._v("Controller handlers are always "),a("strong",[t._v("exported")]),t._v(" so they can be used when registering routes. All functions which aren't handlers "),a("strong",[t._v("must be unexported")]),t._v(".")]),t._v(" "),a("li",[t._v("CRUD operations naming and routing:")])]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Method")]),t._v(" "),a("th",[t._v("URI")]),t._v(" "),a("th",[t._v("Handler name")]),t._v(" "),a("th",[t._v("Description")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("GET")])]),t._v(" "),a("td",[a("code",[t._v("/product")])]),t._v(" "),a("td",[a("code",[t._v("Index()")])]),t._v(" "),a("td",[t._v("Get the products list")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("POST")])]),t._v(" "),a("td",[a("code",[t._v("/product")])]),t._v(" "),a("td",[a("code",[t._v("Store()")])]),t._v(" "),a("td",[t._v("Create a product")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("GET")])]),t._v(" "),a("td",[a("code",[t._v("/product/{id}")])]),t._v(" "),a("td",[a("code",[t._v("Show()")])]),t._v(" "),a("td",[t._v("Show a product")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("PUT")]),t._v(" or "),a("code",[t._v("PATCH")])]),t._v(" "),a("td",[a("code",[t._v("/product/{id}")])]),t._v(" "),a("td",[a("code",[t._v("Update()")])]),t._v(" "),a("td",[t._v("Update a product")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("DELETE")])]),t._v(" "),a("td",[a("code",[t._v("/product/{id}")])]),t._v(" "),a("td",[a("code",[t._v("Destroy()")])]),t._v(" "),a("td",[t._v("Delete a product")])])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/16.87fac0fb.js b/docs/assets/js/16.9d1b54dc.js similarity index 84% rename from docs/assets/js/16.87fac0fb.js rename to docs/assets/js/16.9d1b54dc.js index eae161bb..95e7785e 100644 --- a/docs/assets/js/16.87fac0fb.js +++ b/docs/assets/js/16.9d1b54dc.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{219:function(t,e,a){"use strict";a.r(e);var s=a(0),n=Object(s.a)({},(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"database"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database"}},[t._v("#")]),t._v(" Database")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#configuration"}},[t._v("Configuration")]),a("ul",[a("li",[a("a",{attrs:{href:"#drivers"}},[t._v("Drivers")])])])]),a("li",[a("a",{attrs:{href:"#getting-a-database-connection"}},[t._v("Getting a database connection")])]),a("li",[a("a",{attrs:{href:"#models"}},[t._v("Models")]),a("ul",[a("li",[a("a",{attrs:{href:"#defining-a-model"}},[t._v("Defining a model")])]),a("li",[a("a",{attrs:{href:"#automatic-migrations"}},[t._v("Automatic migrations")])])])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[t._v("Most web applications use a database. In this section, we are going to see how Goyave applications can query a database, using the awesome "),a("a",{attrs:{href:"https://gorm.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Gorm ORM"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("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.")]),t._v(" "),a("p",[t._v("All functions below require the "),a("code",[t._v("database")]),t._v(" and the "),a("code",[t._v("gorm")]),t._v(" packages to be imported.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/database"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/jinzhu/gorm"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#configuration"}},[t._v("#")]),t._v(" Configuration")]),t._v(" "),a("p",[t._v("Very few code is required to get started with databases. There are some "),a("router-link",{attrs:{to:"/guide/configuration.html#configuration-reference"}},[t._v("configuration")]),t._v(" options that you need to change though:")],1),t._v(" "),a("ul",[a("li",[a("code",[t._v("dbConnection")])]),t._v(" "),a("li",[a("code",[t._v("dbHost")])]),t._v(" "),a("li",[a("code",[t._v("dbPort")])]),t._v(" "),a("li",[a("code",[t._v("dbName")])]),t._v(" "),a("li",[a("code",[t._v("dbUsername")])]),t._v(" "),a("li",[a("code",[t._v("dbPassword")])]),t._v(" "),a("li",[a("code",[t._v("dbOptions")])]),t._v(" "),a("li",[a("code",[t._v("dbMaxOpenConnection")])]),t._v(" "),a("li",[a("code",[t._v("dbMaxIdleConnection")])])]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[a("code",[t._v("dbOptions")]),t._v(" represents the addtional connection options. For example, when using MySQL, you should use the "),a("code",[t._v("parseTime=true")]),t._v(" option so "),a("code",[t._v("time.Time")]),t._v(" can be handled correctly. Available options differ from one driver to another and can be found in their respective documentation.")])]),t._v(" "),a("h3",{attrs:{id:"drivers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#drivers"}},[t._v("#")]),t._v(" Drivers")]),t._v(" "),a("p",[t._v("The framework supports the following sql drivers:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("none")]),t._v(" ("),a("em",[t._v("Disable database features")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("mysql")])]),t._v(" "),a("li",[a("code",[t._v("postgres")])]),t._v(" "),a("li",[a("code",[t._v("sqlite3")])]),t._v(" "),a("li",[a("code",[t._v("mssql")])])]),t._v(" "),a("p",[t._v("Change the "),a("code",[t._v("dbConnection")]),t._v(" config entry to the desired driver.")]),t._v(" "),a("p",[t._v("In order to be able connect to the database, Gorm needs a database driver to be imported. Add the following import to your "),a("code",[t._v("kernel.go")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/jinzhu/gorm/dialects/mysql"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// import _ "github.com/jinzhu/gorm/dialects/postgres"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// import _ "github.com/jinzhu/gorm/dialects/sqlite"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// import _ "github.com/jinzhu/gorm/dialects/mssql"')]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("For SQLite, only the "),a("code",[t._v("dbName")]),t._v(" config entry is required.")])]),t._v(" "),a("h2",{attrs:{id:"getting-a-database-connection"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-a-database-connection"}},[t._v("#")]),t._v(" Getting a database connection")]),t._v(" "),a("h4",{attrs:{id:"database-getconnection"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database-getconnection"}},[t._v("#")]),t._v(" database.GetConnection")]),t._v(" "),a("p",[t._v("Returns the global database connection pool. Creates a new connection pool if no connection is available.")]),t._v(" "),a("p",[t._v("The connections will be closed automatically on server shutdown so you don't need to call "),a("code",[t._v("Close()")]),t._v(" when you're done with the database.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("*gorm.DB")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("db "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\ndb"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("First")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("user"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("Learn how to use the CRUD interface and the query builder in the "),a("a",{attrs:{href:"https://gorm.io/docs/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Gorm documentation"),a("OutboundLink")],1),t._v(".")])]),t._v(" "),a("h4",{attrs:{id:"database-close"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database-close"}},[t._v("#")]),t._v(" database.Close")]),t._v(" "),a("p",[t._v("If you want to manually close the database connection, you can do it using "),a("code",[t._v("Close()")]),t._v(". New connections can be re-opened using "),a("code",[t._v("GetConnection()")]),t._v(" as usual. This function does nothing if the database connection is already closed or has never been created.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("void")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"models"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#models"}},[t._v("#")]),t._v(" Models")]),t._v(" "),a("p",[t._v("A model is a structure reflecting a database table structure. An instance of a model is a single database record. Each model is defined in its own file inside the "),a("code",[t._v("database/model")]),t._v(" directory.")]),t._v(" "),a("h3",{attrs:{id:"defining-a-model"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#defining-a-model"}},[t._v("#")]),t._v(" Defining a model")]),t._v(" "),a("p",[t._v("Models are usually just normal Golang structs, basic Go types, or pointers of them. "),a("code",[t._v("sql.Scanner")]),t._v(" and "),a("code",[t._v("driver.Valuer")]),t._v(" interfaces are also supported.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RegisterModel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" User "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n gorm"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Model\n Name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n Age sql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("NullInt64\n Birthday "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Time\n Email "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"type:varchar(100);unique_index"`')]),t._v("\n Role "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"size:255"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// set field size to 255")]),t._v("\n MemberNumber "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"unique;not null"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// set member number to unique and not null")]),t._v("\n Num "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"AUTO_INCREMENT"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// set num to auto incrementable")]),t._v("\n Address "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"index:addr"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// create index with name `addr` for address")]),t._v("\n IgnoreMe "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"-"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ignore this field")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("All models should be "),a("strong",[t._v("registered")]),t._v(" in an "),a("code",[t._v("init()")]),t._v(" function inside their model file. To ensure the "),a("code",[t._v("init()")]),t._v(" functions are executed before the server starts, import the "),a("code",[t._v("models")]),t._v(" package in your "),a("code",[t._v("kernel.go")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"database/model"')]),t._v("\n")])])])]),t._v(" "),a("p",[t._v("Learn more about model declaration in the "),a("a",{attrs:{href:"https://gorm.io/docs/models.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Gorm documentation"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("h3",{attrs:{id:"automatic-migrations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#automatic-migrations"}},[t._v("#")]),t._v(" Automatic migrations")]),t._v(" "),a("p",[t._v("If the "),a("code",[t._v("dbAutoMigrate")]),t._v(" config option is set to true, all registered models will be automatically migrated when the server starts.")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),a("p",[t._v("Automatic migrations "),a("strong",[t._v("only creates")]),t._v(" tables. Missing columns and indexes won't be created, modified columns won't be changed and unused columns won't be deleted.")])]),t._v(" "),a("p",[t._v("If you would like to know more about migrations using Gorm, read their "),a("a",{attrs:{href:"https://gorm.io/docs/migration.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("documentation"),a("OutboundLink")],1),t._v(".")])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{218:function(t,e,a){"use strict";a.r(e);var s=a(0),n=Object(s.a)({},(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"database"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database"}},[t._v("#")]),t._v(" Database")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#configuration"}},[t._v("Configuration")]),a("ul",[a("li",[a("a",{attrs:{href:"#drivers"}},[t._v("Drivers")])])])]),a("li",[a("a",{attrs:{href:"#getting-a-database-connection"}},[t._v("Getting a database connection")])]),a("li",[a("a",{attrs:{href:"#models"}},[t._v("Models")]),a("ul",[a("li",[a("a",{attrs:{href:"#defining-a-model"}},[t._v("Defining a model")])]),a("li",[a("a",{attrs:{href:"#automatic-migrations"}},[t._v("Automatic migrations")])])])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[t._v("Most web applications use a database. In this section, we are going to see how Goyave applications can query a database, using the awesome "),a("a",{attrs:{href:"https://gorm.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Gorm ORM"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("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.")]),t._v(" "),a("p",[t._v("All functions below require the "),a("code",[t._v("database")]),t._v(" and the "),a("code",[t._v("gorm")]),t._v(" packages to be imported.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/database"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/jinzhu/gorm"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#configuration"}},[t._v("#")]),t._v(" Configuration")]),t._v(" "),a("p",[t._v("Very few code is required to get started with databases. There are some "),a("router-link",{attrs:{to:"/guide/configuration.html#configuration-reference"}},[t._v("configuration")]),t._v(" options that you need to change though:")],1),t._v(" "),a("ul",[a("li",[a("code",[t._v("dbConnection")])]),t._v(" "),a("li",[a("code",[t._v("dbHost")])]),t._v(" "),a("li",[a("code",[t._v("dbPort")])]),t._v(" "),a("li",[a("code",[t._v("dbName")])]),t._v(" "),a("li",[a("code",[t._v("dbUsername")])]),t._v(" "),a("li",[a("code",[t._v("dbPassword")])]),t._v(" "),a("li",[a("code",[t._v("dbOptions")])]),t._v(" "),a("li",[a("code",[t._v("dbMaxOpenConnection")])]),t._v(" "),a("li",[a("code",[t._v("dbMaxIdleConnection")])])]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[a("code",[t._v("dbOptions")]),t._v(" represents the addtional connection options. For example, when using MySQL, you should use the "),a("code",[t._v("parseTime=true")]),t._v(" option so "),a("code",[t._v("time.Time")]),t._v(" can be handled correctly. Available options differ from one driver to another and can be found in their respective documentation.")])]),t._v(" "),a("h3",{attrs:{id:"drivers"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#drivers"}},[t._v("#")]),t._v(" Drivers")]),t._v(" "),a("p",[t._v("The framework supports the following sql drivers:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("none")]),t._v(" ("),a("em",[t._v("Disable database features")]),t._v(")")]),t._v(" "),a("li",[a("code",[t._v("mysql")])]),t._v(" "),a("li",[a("code",[t._v("postgres")])]),t._v(" "),a("li",[a("code",[t._v("sqlite3")])]),t._v(" "),a("li",[a("code",[t._v("mssql")])])]),t._v(" "),a("p",[t._v("Change the "),a("code",[t._v("dbConnection")]),t._v(" config entry to the desired driver.")]),t._v(" "),a("p",[t._v("In order to be able connect to the database, Gorm needs a database driver to be imported. Add the following import to your "),a("code",[t._v("kernel.go")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/jinzhu/gorm/dialects/mysql"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// import _ "github.com/jinzhu/gorm/dialects/postgres"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// import _ "github.com/jinzhu/gorm/dialects/sqlite"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// import _ "github.com/jinzhu/gorm/dialects/mssql"')]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("For SQLite, only the "),a("code",[t._v("dbName")]),t._v(" config entry is required.")])]),t._v(" "),a("h2",{attrs:{id:"getting-a-database-connection"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-a-database-connection"}},[t._v("#")]),t._v(" Getting a database connection")]),t._v(" "),a("h4",{attrs:{id:"database-getconnection"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database-getconnection"}},[t._v("#")]),t._v(" database.GetConnection")]),t._v(" "),a("p",[t._v("Returns the global database connection pool. Creates a new connection pool if no connection is available.")]),t._v(" "),a("p",[t._v("The connections will be closed automatically on server shutdown so you don't need to call "),a("code",[t._v("Close()")]),t._v(" when you're done with the database.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("*gorm.DB")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("db "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetConnection")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\ndb"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("First")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("user"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("Learn how to use the CRUD interface and the query builder in the "),a("a",{attrs:{href:"https://gorm.io/docs/index.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Gorm documentation"),a("OutboundLink")],1),t._v(".")])]),t._v(" "),a("h4",{attrs:{id:"database-close"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database-close"}},[t._v("#")]),t._v(" database.Close")]),t._v(" "),a("p",[t._v("If you want to manually close the database connection, you can do it using "),a("code",[t._v("Close()")]),t._v(". New connections can be re-opened using "),a("code",[t._v("GetConnection()")]),t._v(" as usual. This function does nothing if the database connection is already closed or has never been created.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("void")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"models"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#models"}},[t._v("#")]),t._v(" Models")]),t._v(" "),a("p",[t._v("A model is a structure reflecting a database table structure. An instance of a model is a single database record. Each model is defined in its own file inside the "),a("code",[t._v("database/model")]),t._v(" directory.")]),t._v(" "),a("h3",{attrs:{id:"defining-a-model"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#defining-a-model"}},[t._v("#")]),t._v(" Defining a model")]),t._v(" "),a("p",[t._v("Models are usually just normal Golang structs, basic Go types, or pointers of them. "),a("code",[t._v("sql.Scanner")]),t._v(" and "),a("code",[t._v("driver.Valuer")]),t._v(" interfaces are also supported.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n database"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RegisterModel")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" User "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n gorm"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Model\n Name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n Age sql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("NullInt64\n Birthday "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Time\n Email "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"type:varchar(100);unique_index"`')]),t._v("\n Role "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"size:255"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// set field size to 255")]),t._v("\n MemberNumber "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"unique;not null"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// set member number to unique and not null")]),t._v("\n Num "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"AUTO_INCREMENT"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// set num to auto incrementable")]),t._v("\n Address "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"index:addr"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// create index with name `addr` for address")]),t._v("\n IgnoreMe "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('`gorm:"-"`')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ignore this field")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("All models should be "),a("strong",[t._v("registered")]),t._v(" in an "),a("code",[t._v("init()")]),t._v(" function inside their model file. To ensure the "),a("code",[t._v("init()")]),t._v(" functions are executed before the server starts, import the "),a("code",[t._v("models")]),t._v(" package in your "),a("code",[t._v("kernel.go")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"database/model"')]),t._v("\n")])])])]),t._v(" "),a("p",[t._v("Learn more about model declaration in the "),a("a",{attrs:{href:"https://gorm.io/docs/models.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Gorm documentation"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("h4",{attrs:{id:"database-registermodel"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database-registermodel"}},[t._v("#")]),t._v(" database.RegisterModel")]),t._v(" "),a("p",[t._v("Registers a model for auto-migration.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("model interface{}")])]),t._v(" "),a("td",[a("code",[t._v("void")])])])])]),t._v(" "),a("h4",{attrs:{id:"database-getregisteredmodels"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database-getregisteredmodels"}},[t._v("#")]),t._v(" database.GetRegisteredModels")]),t._v(" "),a("p",[t._v("Get the registered models. The returned slice is a copy of the original, so it cannot be modified.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("[]interface{}")])])])])]),t._v(" "),a("h4",{attrs:{id:"database-clearregisteredmodels"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#database-clearregisteredmodels"}},[t._v("#")]),t._v(" database.ClearRegisteredModels")]),t._v(" "),a("p",[t._v("Unregister all models.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("void")])])])])]),t._v(" "),a("h3",{attrs:{id:"automatic-migrations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#automatic-migrations"}},[t._v("#")]),t._v(" Automatic migrations")]),t._v(" "),a("p",[t._v("If the "),a("code",[t._v("dbAutoMigrate")]),t._v(" config option is set to true, all registered models will be automatically migrated when the server starts.")]),t._v(" "),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),a("p",[t._v("Automatic migrations "),a("strong",[t._v("only create")]),t._v(" tables, missing columns and missing indexes. They "),a("strong",[t._v("wont't change")]),t._v(" existing column’s type or delete unused columns.")])]),t._v(" "),a("p",[t._v("If you would like to know more about migrations using Gorm, read their "),a("a",{attrs:{href:"https://gorm.io/docs/migration.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("documentation"),a("OutboundLink")],1),t._v(".")])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/17.134fa30a.js b/docs/assets/js/17.103ef510.js similarity index 99% rename from docs/assets/js/17.134fa30a.js rename to docs/assets/js/17.103ef510.js index cd9fb239..c3c66672 100644 --- a/docs/assets/js/17.134fa30a.js +++ b/docs/assets/js/17.103ef510.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{220:function(t,e,a){"use strict";a.r(e);var s=a(0),n=Object(s.a)({},(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#writing-middleware"}},[t._v("Writing middleware")])]),a("li",[a("a",{attrs:{href:"#included-middleware"}},[t._v("Included middleware")]),a("ul",[a("li",[a("a",{attrs:{href:"#disallownonvalidatedfields"}},[t._v("DisallowNonValidatedFields")])]),a("li",[a("a",{attrs:{href:"#trim"}},[t._v("Trim")])])])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[t._v("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.")]),t._v(" "),a("p",[t._v("Writing middleware is as easy as writing standard handlers. In fact, middleware are handlers, but they have an additional responsability: when they are done, the may or may not pass to the next handler, which is either another middleware or a controller handler.")]),t._v(" "),a("h2",{attrs:{id:"writing-middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#writing-middleware"}},[t._v("#")]),t._v(" Writing middleware")]),t._v(" "),a("p",[t._v("Each middleware is written in its own file inside the "),a("code",[t._v("http/middleware")]),t._v(" directory. A "),a("code",[t._v("Middleware")]),t._v(" is a function returning a "),a("code",[t._v("Handler")]),t._v(".")]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[a("code",[t._v("goyave.Middleware")]),t._v(" is an alias for "),a("code",[t._v("func(goyave.Handler) goyave.Handler")])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("MyCustomMiddleware")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("next goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Do something")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("next")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Pass to the next handler")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("When implementing middleware, keep in mind that the request "),a("strong",[t._v("has not been validated yet")]),t._v("! Manipulating unvalidated data can be dangerous, especially in form-data where the data types are not converted by the validator yet. In middleware, you should always check if the request has been parsed correctly before trying to access its data:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Parsing OK")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If you want your middleware to stop the request and respond immediately before reaching the controller handler, simply don't call the "),a("code",[t._v("next")]),t._v(" handler. In the following example, consider that you developed a custom authentication system:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("CustomAuthentication")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("next goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("auth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Check")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusUnauthorized"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("next")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("When a middleware stops a request, following middlewares are "),a("strong",[t._v("not")]),t._v(" executed either.")])]),t._v(" "),a("h2",{attrs:{id:"included-middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#included-middleware"}},[t._v("#")]),t._v(" Included middleware")]),t._v(" "),a("p",[t._v("Included middleware are located in the "),a("code",[t._v("middleware")]),t._v(" package.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/middleware"')]),t._v("\n")])])]),a("h3",{attrs:{id:"disallownonvalidatedfields"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#disallownonvalidatedfields"}},[t._v("#")]),t._v(" DisallowNonValidatedFields")]),t._v(" "),a("p",[t._v('DisallowNonValidatedFields validates that all fields in the request are validated by the RuleSet. The middleware stops the request and sends "422 Unprocessable Entity" and an error message if the user has sent non-validated field(s). Fields ending with '),a("code",[t._v("_confirmation")]),t._v(" are ignored.")]),t._v(" "),a("p",[t._v("If the body parsing failed, this middleware immediately passes to the next handler. "),a("strong",[t._v("This middleware shall only be used with requests having a rule set defined.")])]),t._v(" "),a("p",[t._v("The returned error message can be customized using the entry "),a("code",[t._v("disallow-non-validated-fields")]),t._v(" in the "),a("code",[t._v("locale.json")]),t._v(" language file.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("router"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("DisallowNonValidatedFields"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"trim"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#trim"}},[t._v("#")]),t._v(" Trim")]),t._v(" "),a("p",[a("Badge",{attrs:{text:"Since v2.0.0"}})],1),t._v(" "),a("p",[t._v("Trim removes all leading and trailing white space from string fields.")]),t._v(" "),a("p",[t._v("For example, "),a("code",[t._v('" \\t trimmed\\n \\t"')]),t._v(" will be transformed to "),a("code",[t._v('"trimmed"')]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("router"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Trim"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{219:function(t,e,a){"use strict";a.r(e);var s=a(0),n=Object(s.a)({},(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#writing-middleware"}},[t._v("Writing middleware")])]),a("li",[a("a",{attrs:{href:"#included-middleware"}},[t._v("Included middleware")]),a("ul",[a("li",[a("a",{attrs:{href:"#disallownonvalidatedfields"}},[t._v("DisallowNonValidatedFields")])]),a("li",[a("a",{attrs:{href:"#trim"}},[t._v("Trim")])])])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[t._v("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.")]),t._v(" "),a("p",[t._v("Writing middleware is as easy as writing standard handlers. In fact, middleware are handlers, but they have an additional responsability: when they are done, the may or may not pass to the next handler, which is either another middleware or a controller handler.")]),t._v(" "),a("h2",{attrs:{id:"writing-middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#writing-middleware"}},[t._v("#")]),t._v(" Writing middleware")]),t._v(" "),a("p",[t._v("Each middleware is written in its own file inside the "),a("code",[t._v("http/middleware")]),t._v(" directory. A "),a("code",[t._v("Middleware")]),t._v(" is a function returning a "),a("code",[t._v("Handler")]),t._v(".")]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[a("code",[t._v("goyave.Middleware")]),t._v(" is an alias for "),a("code",[t._v("func(goyave.Handler) goyave.Handler")])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("MyCustomMiddleware")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("next goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Do something")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("next")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Pass to the next handler")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("When implementing middleware, keep in mind that the request "),a("strong",[t._v("has not been validated yet")]),t._v("! Manipulating unvalidated data can be dangerous, especially in form-data where the data types are not converted by the validator yet. In middleware, you should always check if the request has been parsed correctly before trying to access its data:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Parsing OK")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("If you want your middleware to stop the request and respond immediately before reaching the controller handler, simply don't call the "),a("code",[t._v("next")]),t._v(" handler. In the following example, consider that you developed a custom authentication system:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("CustomAuthentication")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("next goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("auth"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Check")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusUnauthorized"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("next")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),a("p",[t._v("When a middleware stops a request, following middlewares are "),a("strong",[t._v("not")]),t._v(" executed either.")])]),t._v(" "),a("h2",{attrs:{id:"included-middleware"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#included-middleware"}},[t._v("#")]),t._v(" Included middleware")]),t._v(" "),a("p",[t._v("Included middleware are located in the "),a("code",[t._v("middleware")]),t._v(" package.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/middleware"')]),t._v("\n")])])]),a("h3",{attrs:{id:"disallownonvalidatedfields"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#disallownonvalidatedfields"}},[t._v("#")]),t._v(" DisallowNonValidatedFields")]),t._v(" "),a("p",[t._v('DisallowNonValidatedFields validates that all fields in the request are validated by the RuleSet. The middleware stops the request and sends "422 Unprocessable Entity" and an error message if the user has sent non-validated field(s). Fields ending with '),a("code",[t._v("_confirmation")]),t._v(" are ignored.")]),t._v(" "),a("p",[t._v("If the body parsing failed, this middleware immediately passes to the next handler. "),a("strong",[t._v("This middleware shall only be used with requests having a rule set defined.")])]),t._v(" "),a("p",[t._v("The returned error message can be customized using the entry "),a("code",[t._v("disallow-non-validated-fields")]),t._v(" in the "),a("code",[t._v("locale.json")]),t._v(" language file.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("router"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("DisallowNonValidatedFields"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"trim"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#trim"}},[t._v("#")]),t._v(" Trim")]),t._v(" "),a("p",[a("Badge",{attrs:{text:"Since v2.0.0"}})],1),t._v(" "),a("p",[t._v("Trim removes all leading and trailing white space from string fields.")]),t._v(" "),a("p",[t._v("For example, "),a("code",[t._v('" \\t trimmed\\n \\t"')]),t._v(" will be transformed to "),a("code",[t._v('"trimmed"')]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("router"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Trim"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/18.408c5054.js b/docs/assets/js/18.8a8e742b.js similarity index 99% rename from docs/assets/js/18.408c5054.js rename to docs/assets/js/18.8a8e742b.js index f9ef380e..9da7fc6e 100644 --- a/docs/assets/js/18.408c5054.js +++ b/docs/assets/js/18.8a8e742b.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{229:function(t,s,a){"use strict";a.r(s);var e=a(0),n=Object(e.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"requests"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#requests"}},[t._v("#")]),t._v(" Requests")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#methods"}},[t._v("Methods")]),a("ul",[a("li",[a("a",{attrs:{href:"#accessors"}},[t._v("Accessors")])])])]),a("li",[a("a",{attrs:{href:"#attributes"}},[t._v("Attributes")])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[t._v("Handlers receive a "),a("code",[t._v("goyave.Response")]),t._v(" and a "),a("code",[t._v("goyave.Request")]),t._v(" as parameters. This section is a technical reference of the "),a("code",[t._v("Request")]),t._v(" object. This object can give you a lot of information about the incoming request, such as its headers, cookies, or body.")]),t._v(" "),a("p",[t._v("All functions below require the "),a("code",[t._v("goyave")]),t._v(" package to be imported.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n")])])]),a("h2",{attrs:{id:"methods"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#methods"}},[t._v("#")]),t._v(" Methods")]),t._v(" "),a("div",{staticClass:"table"},[a("p",[a("a",{attrs:{href:"#request-method"}},[t._v("Method")]),t._v(" "),a("a",{attrs:{href:"#request-protocol"}},[t._v("Protocol")]),t._v(" "),a("a",{attrs:{href:"#request-uri"}},[t._v("URI")]),t._v(" "),a("a",{attrs:{href:"#request-header"}},[t._v("Header")]),t._v(" "),a("a",{attrs:{href:"#request-contentlength"}},[t._v("ContentLength")]),t._v(" "),a("a",{attrs:{href:"#request-remoteaddress"}},[t._v("RemoteAddress")]),t._v(" "),a("a",{attrs:{href:"#request-cookies"}},[t._v("Cookies")]),t._v(" "),a("a",{attrs:{href:"#request-referrer"}},[t._v("Referrer")]),t._v(" "),a("a",{attrs:{href:"#request-useragent"}},[t._v("UserAgent")])])]),a("h4",{attrs:{id:"request-method"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-method"}},[t._v("#")]),t._v(" Request.Method")]),t._v(" "),a("p",[t._v("The HTTP method (GET, POST, PUT, etc.).")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// GET")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-protocol"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-protocol"}},[t._v("#")]),t._v(" Request.Protocol")]),t._v(" "),a("p",[t._v('The protocol used by this request, "HTTP/1.1" for example.')]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Protocol")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "HTTP/1.1"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-uri"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-uri"}},[t._v("#")]),t._v(" Request.URI")]),t._v(" "),a("p",[t._v("URI specifies the URI being requested. Use this if you absolutely need the raw query params, url, etc. Otherwise use the provided methods and fields of the "),a("code",[t._v("goyave.Request")]),t._v(".")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("*url.URL")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("URL")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "/foo/bar"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-header"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-header"}},[t._v("#")]),t._v(" Request.Header")]),t._v(" "),a("p",[t._v("Header contains the request header fields either received by the server or to be sent by the client. Header names are case-insensitive.")]),t._v(" "),a("p",[t._v("If the raw request has the following header lines,")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("Host: example.com\naccept-encoding: gzip, deflate\nAccept-Language: en-us\nfOO: Bar\nfoo: two\n")])])]),a("p",[t._v("then the header map will look like this:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("Header "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Accept-Encoding"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"gzip, deflate"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Accept-Language"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"en-us"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Foo"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"two"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("http.Header")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Header")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Content-Type"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "application/json"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-contentlength"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-contentlength"}},[t._v("#")]),t._v(" Request.ContentLength")]),t._v(" "),a("p",[t._v("ContentLength records the length (in bytes) of the associated content. The value -1 indicates that the length is unknown.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("int64")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ContentLength")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 758")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-remoteaddress"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-remoteaddress"}},[t._v("#")]),t._v(" Request.RemoteAddress")]),t._v(" "),a("p",[t._v("RemoteAddress allows to record the network address that sent the request, usually for logging.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RemoteAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 192.168.0.10:1234")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-cookies"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-cookies"}},[t._v("#")]),t._v(" Request.Cookies")]),t._v(" "),a("p",[t._v("Cookies returns the HTTP cookies sent with the request.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("name string")])]),t._v(" "),a("td",[a("code",[t._v("[]*http.Cookie")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("cookie "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cookies")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cookie-name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cookie"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-referrer"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-referrer"}},[t._v("#")]),t._v(" Request.Referrer")]),t._v(" "),a("p",[t._v("Referrer returns the referring URL, if sent in the request.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Referrer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "https://github.com/System-Glitch/goyave/"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-useragent"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-useragent"}},[t._v("#")]),t._v(" Request.UserAgent")]),t._v(" "),a("p",[t._v("UserAgent returns the client's User-Agent, if sent in the request.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("UserAgent")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "Mozilla/5.0 ..."')]),t._v("\n")])])]),a("h3",{attrs:{id:"accessors"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#accessors"}},[t._v("#")]),t._v(" Accessors")]),t._v(" "),a("p",[a("Badge",{attrs:{text:"Since v2.0.0"}})],1),t._v(" "),a("p",[t._v("Accessors are helper functions to retrieve request data without having to write the type assertion. This is helpful to make your controllers cleaner. You shouldn't use these accessors in middlewares because they assume the data has been converted by the validation already. Data can still be accessed through the "),a("code",[t._v("Data")]),t._v(" attribute. There is currently no accessor for slices.")]),t._v(" "),a("div",{staticClass:"table"},[a("p",[a("a",{attrs:{href:"#request-has"}},[t._v("Has")]),t._v(" "),a("a",{attrs:{href:"#request-string"}},[t._v("String")]),t._v(" "),a("a",{attrs:{href:"#request-numeric"}},[t._v("Numeric")]),t._v(" "),a("a",{attrs:{href:"#request-integer"}},[t._v("Integer")]),t._v(" "),a("a",{attrs:{href:"#request-bool"}},[t._v("Bool")]),t._v(" "),a("a",{attrs:{href:"#request-file"}},[t._v("File")]),t._v(" "),a("a",{attrs:{href:"#request-timezone"}},[t._v("Timezone")]),t._v(" "),a("a",{attrs:{href:"#request-ip"}},[t._v("IP")]),t._v(" "),a("a",{attrs:{href:"#request-url"}},[t._v("URL")]),t._v(" "),a("a",{attrs:{href:"#request-uuid"}},[t._v("UUID")]),t._v(" "),a("a",{attrs:{href:"#request-date"}},[t._v("Date")])])]),a("h4",{attrs:{id:"request-has"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-has"}},[t._v("#")]),t._v(" Request.Has")]),t._v(" "),a("p",[t._v("Check if the given field exists in the request data.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("bool")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Has")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-string"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-string"}},[t._v("#")]),t._v(" Request.String")]),t._v(" "),a("p",[t._v("Get a string field from the request data. Panics if the field is not a string or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "JohnDoe"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-numeric"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-numeric"}},[t._v("#")]),t._v(" Request.Numeric")]),t._v(" "),a("p",[t._v("Get a numeric field from the request data. Panics if the field is not numeric or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("float64")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Numeric")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"price"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 42.3")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-integer"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-integer"}},[t._v("#")]),t._v(" Request.Integer")]),t._v(" "),a("p",[t._v("Get an integer field from the request data. Panics if the field is not an integer or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("int")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Integer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 32")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-bool"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-bool"}},[t._v("#")]),t._v(" Request.Bool")]),t._v(" "),a("p",[t._v("Get a bool field from the request data. Panics if the field is not a bool or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("bool")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Bool")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EULA"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-file"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-file"}},[t._v("#")]),t._v(" Request.File")]),t._v(" "),a("p",[t._v("Get a file field from the request data. Panics if the field is not a file or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("[]filesystem.File")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("File")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"images"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Filename"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-timezone"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-timezone"}},[t._v("#")]),t._v(" Request.Timezone")]),t._v(" "),a("p",[t._v("Get a timezone field from the request data. Panics if the field is not a timezone or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("*time.Location")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Timezone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tz"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "America/New_York"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-ip"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-ip"}},[t._v("#")]),t._v(" Request.IP")]),t._v(" "),a("p",[t._v("Get an IP field from the request data. Panics if the field is not an IP or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("net.IP")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("IP")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"host"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "127.0.0.1"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-url"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-url"}},[t._v("#")]),t._v(" Request.URL")]),t._v(" "),a("p",[t._v("Get an URL field from the request data. Panics if the field is not an URL or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("*url.URL")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("URL")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"link"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "https://google.com"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-uuid"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-uuid"}},[t._v("#")]),t._v(" Request.UUID")]),t._v(" "),a("p",[t._v("Get a UUID field from the request data. Panics if the field is not a UUID or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("uuid.UUID")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("UUID")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "3bbcee75-cecc-5b56-8031-b6641c1ed1f1"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-date"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-date"}},[t._v("#")]),t._v(" Request.Date")]),t._v(" "),a("p",[t._v("Get a date field from the request data. Panics if the field is not a date or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("time.Time")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Date")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"birthdate"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "2019-11-21 00:00:00 +0000 UTC"')]),t._v("\n")])])]),a("h2",{attrs:{id:"attributes"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#attributes"}},[t._v("#")]),t._v(" Attributes")]),t._v(" "),a("div",{staticClass:"table"},[a("p",[a("a",{attrs:{href:"#request-rules"}},[t._v("Rules")]),t._v(" "),a("a",{attrs:{href:"#request-data"}},[t._v("Data")]),t._v(" "),a("a",{attrs:{href:"#request-params"}},[t._v("Params")]),t._v(" "),a("a",{attrs:{href:"#request-lang"}},[t._v("Lang")])])]),a("h4",{attrs:{id:"request-rules"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-rules"}},[t._v("#")]),t._v(" Request.Rules")]),t._v(" "),a("p",[t._v("The validation rule set associated with this request. See the "),a("router-link",{attrs:{to:"/guide/basics/validation.html"}},[t._v("validation")]),t._v(" section for more information.")],1),t._v(" "),a("h4",{attrs:{id:"request-data"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-data"}},[t._v("#")]),t._v(" Request.Data")]),t._v(" "),a("p",[t._v("A "),a("code",[t._v("map[string]interface{}")]),t._v(" containing the request's data. The key is the name of the field. This map contains the data from the request's body "),a("strong",[t._v("and")]),t._v(" the URL query string values. The request's body parameters takes precedence over the URL query string values.")]),t._v(" "),a("p",[t._v("For the given JSON request:")]),t._v(" "),a("div",{staticClass:"language-json extra-class"},[a("pre",{pre:!0,attrs:{class:"language-json"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"John Doe"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"tags"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tag1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tag2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "John Doe"')]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tags"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "[tag1 tag2]" ([]string)')]),t._v("\n")])])]),a("p",[t._v("You would obtain the same result for the following url-encoded request:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("name=John%20Doe&tags=tag1&tags=tag2\n")])])]),a("p",[t._v("Because the "),a("code",[t._v("Data")]),t._v(" attribute can hold any type of data, you will likely need type assertion. If you validated your request, checking for type assertion errors is not necessary.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("tags"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tags"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-params"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-params"}},[t._v("#")]),t._v(" Request.Params")]),t._v(" "),a("p",[a("code",[t._v("Params")]),t._v(" is a "),a("code",[t._v("map[string]string")]),t._v(" of the route parameters.")]),t._v(" "),a("p",[t._v("For the given route definition and request:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("/categories/{category}/{product_id}\n")])])]),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("/categories/3/5\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"category"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "3"')]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"product_id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "5"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-lang"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-lang"}},[t._v("#")]),t._v(" Request.Lang")]),t._v(" "),a("p",[a("code",[t._v("Lang")]),t._v(" indicates the language desired by the user. This attribute is automatically set by a core middleware, based on the "),a("code",[t._v("Accept-Language")]),t._v(" header, if present. If the desired language is not available, the default language is used.")]),t._v(" "),a("p",[t._v("Learn more in the "),a("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[t._v("localization")]),t._v(" section.")],1),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "en-US"')]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"validation.rules.required"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "The :field is required."')]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{228:function(t,s,a){"use strict";a.r(s);var e=a(0),n=Object(e.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"requests"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#requests"}},[t._v("#")]),t._v(" Requests")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#methods"}},[t._v("Methods")]),a("ul",[a("li",[a("a",{attrs:{href:"#accessors"}},[t._v("Accessors")])])])]),a("li",[a("a",{attrs:{href:"#attributes"}},[t._v("Attributes")])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[t._v("Handlers receive a "),a("code",[t._v("goyave.Response")]),t._v(" and a "),a("code",[t._v("goyave.Request")]),t._v(" as parameters. This section is a technical reference of the "),a("code",[t._v("Request")]),t._v(" object. This object can give you a lot of information about the incoming request, such as its headers, cookies, or body.")]),t._v(" "),a("p",[t._v("All functions below require the "),a("code",[t._v("goyave")]),t._v(" package to be imported.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n")])])]),a("h2",{attrs:{id:"methods"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#methods"}},[t._v("#")]),t._v(" Methods")]),t._v(" "),a("div",{staticClass:"table"},[a("p",[a("a",{attrs:{href:"#request-method"}},[t._v("Method")]),t._v(" "),a("a",{attrs:{href:"#request-protocol"}},[t._v("Protocol")]),t._v(" "),a("a",{attrs:{href:"#request-uri"}},[t._v("URI")]),t._v(" "),a("a",{attrs:{href:"#request-header"}},[t._v("Header")]),t._v(" "),a("a",{attrs:{href:"#request-contentlength"}},[t._v("ContentLength")]),t._v(" "),a("a",{attrs:{href:"#request-remoteaddress"}},[t._v("RemoteAddress")]),t._v(" "),a("a",{attrs:{href:"#request-cookies"}},[t._v("Cookies")]),t._v(" "),a("a",{attrs:{href:"#request-referrer"}},[t._v("Referrer")]),t._v(" "),a("a",{attrs:{href:"#request-useragent"}},[t._v("UserAgent")])])]),a("h4",{attrs:{id:"request-method"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-method"}},[t._v("#")]),t._v(" Request.Method")]),t._v(" "),a("p",[t._v("The HTTP method (GET, POST, PUT, etc.).")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// GET")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-protocol"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-protocol"}},[t._v("#")]),t._v(" Request.Protocol")]),t._v(" "),a("p",[t._v('The protocol used by this request, "HTTP/1.1" for example.')]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Protocol")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "HTTP/1.1"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-uri"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-uri"}},[t._v("#")]),t._v(" Request.URI")]),t._v(" "),a("p",[t._v("URI specifies the URI being requested. Use this if you absolutely need the raw query params, url, etc. Otherwise use the provided methods and fields of the "),a("code",[t._v("goyave.Request")]),t._v(".")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("*url.URL")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("URL")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "/foo/bar"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-header"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-header"}},[t._v("#")]),t._v(" Request.Header")]),t._v(" "),a("p",[t._v("Header contains the request header fields either received by the server or to be sent by the client. Header names are case-insensitive.")]),t._v(" "),a("p",[t._v("If the raw request has the following header lines,")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("Host: example.com\naccept-encoding: gzip, deflate\nAccept-Language: en-us\nfOO: Bar\nfoo: two\n")])])]),a("p",[t._v("then the header map will look like this:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("Header "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Accept-Encoding"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"gzip, deflate"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Accept-Language"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"en-us"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Foo"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bar"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"two"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("http.Header")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Header")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Content-Type"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "application/json"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-contentlength"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-contentlength"}},[t._v("#")]),t._v(" Request.ContentLength")]),t._v(" "),a("p",[t._v("ContentLength records the length (in bytes) of the associated content. The value -1 indicates that the length is unknown.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("int64")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ContentLength")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 758")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-remoteaddress"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-remoteaddress"}},[t._v("#")]),t._v(" Request.RemoteAddress")]),t._v(" "),a("p",[t._v("RemoteAddress allows to record the network address that sent the request, usually for logging.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RemoteAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 192.168.0.10:1234")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-cookies"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-cookies"}},[t._v("#")]),t._v(" Request.Cookies")]),t._v(" "),a("p",[t._v("Cookies returns the HTTP cookies sent with the request.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("name string")])]),t._v(" "),a("td",[a("code",[t._v("[]*http.Cookie")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("cookie "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cookies")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cookie-name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cookie"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-referrer"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-referrer"}},[t._v("#")]),t._v(" Request.Referrer")]),t._v(" "),a("p",[t._v("Referrer returns the referring URL, if sent in the request.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Referrer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "https://github.com/System-Glitch/goyave/"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-useragent"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-useragent"}},[t._v("#")]),t._v(" Request.UserAgent")]),t._v(" "),a("p",[t._v("UserAgent returns the client's User-Agent, if sent in the request.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("UserAgent")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "Mozilla/5.0 ..."')]),t._v("\n")])])]),a("h3",{attrs:{id:"accessors"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#accessors"}},[t._v("#")]),t._v(" Accessors")]),t._v(" "),a("p",[a("Badge",{attrs:{text:"Since v2.0.0"}})],1),t._v(" "),a("p",[t._v("Accessors are helper functions to retrieve request data without having to write the type assertion. This is helpful to make your controllers cleaner. You shouldn't use these accessors in middlewares because they assume the data has been converted by the validation already. Data can still be accessed through the "),a("code",[t._v("Data")]),t._v(" attribute. There is currently no accessor for slices.")]),t._v(" "),a("div",{staticClass:"table"},[a("p",[a("a",{attrs:{href:"#request-has"}},[t._v("Has")]),t._v(" "),a("a",{attrs:{href:"#request-string"}},[t._v("String")]),t._v(" "),a("a",{attrs:{href:"#request-numeric"}},[t._v("Numeric")]),t._v(" "),a("a",{attrs:{href:"#request-integer"}},[t._v("Integer")]),t._v(" "),a("a",{attrs:{href:"#request-bool"}},[t._v("Bool")]),t._v(" "),a("a",{attrs:{href:"#request-file"}},[t._v("File")]),t._v(" "),a("a",{attrs:{href:"#request-timezone"}},[t._v("Timezone")]),t._v(" "),a("a",{attrs:{href:"#request-ip"}},[t._v("IP")]),t._v(" "),a("a",{attrs:{href:"#request-url"}},[t._v("URL")]),t._v(" "),a("a",{attrs:{href:"#request-uuid"}},[t._v("UUID")]),t._v(" "),a("a",{attrs:{href:"#request-date"}},[t._v("Date")])])]),a("h4",{attrs:{id:"request-has"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-has"}},[t._v("#")]),t._v(" Request.Has")]),t._v(" "),a("p",[t._v("Check if the given field exists in the request data.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("bool")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Has")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-string"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-string"}},[t._v("#")]),t._v(" Request.String")]),t._v(" "),a("p",[t._v("Get a string field from the request data. Panics if the field is not a string or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("string")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "JohnDoe"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-numeric"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-numeric"}},[t._v("#")]),t._v(" Request.Numeric")]),t._v(" "),a("p",[t._v("Get a numeric field from the request data. Panics if the field is not numeric or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("float64")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Numeric")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"price"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 42.3")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-integer"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-integer"}},[t._v("#")]),t._v(" Request.Integer")]),t._v(" "),a("p",[t._v("Get an integer field from the request data. Panics if the field is not an integer or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("int")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Integer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 32")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-bool"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-bool"}},[t._v("#")]),t._v(" Request.Bool")]),t._v(" "),a("p",[t._v("Get a bool field from the request data. Panics if the field is not a bool or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("bool")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Bool")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EULA"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-file"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-file"}},[t._v("#")]),t._v(" Request.File")]),t._v(" "),a("p",[t._v("Get a file field from the request data. Panics if the field is not a file or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("[]filesystem.File")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("File")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"images"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Header"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Filename"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-timezone"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-timezone"}},[t._v("#")]),t._v(" Request.Timezone")]),t._v(" "),a("p",[t._v("Get a timezone field from the request data. Panics if the field is not a timezone or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("*time.Location")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Timezone")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tz"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "America/New_York"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-ip"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-ip"}},[t._v("#")]),t._v(" Request.IP")]),t._v(" "),a("p",[t._v("Get an IP field from the request data. Panics if the field is not an IP or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("net.IP")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("IP")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"host"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "127.0.0.1"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-url"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-url"}},[t._v("#")]),t._v(" Request.URL")]),t._v(" "),a("p",[t._v("Get an URL field from the request data. Panics if the field is not an URL or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("*url.URL")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("URL")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"link"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "https://google.com"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-uuid"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-uuid"}},[t._v("#")]),t._v(" Request.UUID")]),t._v(" "),a("p",[t._v("Get a UUID field from the request data. Panics if the field is not a UUID or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("uuid.UUID")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("UUID")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "3bbcee75-cecc-5b56-8031-b6641c1ed1f1"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-date"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-date"}},[t._v("#")]),t._v(" Request.Date")]),t._v(" "),a("p",[t._v("Get a date field from the request data. Panics if the field is not a date or doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("field string")])]),t._v(" "),a("td",[a("code",[t._v("time.Time")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Date")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"birthdate"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "2019-11-21 00:00:00 +0000 UTC"')]),t._v("\n")])])]),a("h2",{attrs:{id:"attributes"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#attributes"}},[t._v("#")]),t._v(" Attributes")]),t._v(" "),a("div",{staticClass:"table"},[a("p",[a("a",{attrs:{href:"#request-rules"}},[t._v("Rules")]),t._v(" "),a("a",{attrs:{href:"#request-data"}},[t._v("Data")]),t._v(" "),a("a",{attrs:{href:"#request-params"}},[t._v("Params")]),t._v(" "),a("a",{attrs:{href:"#request-lang"}},[t._v("Lang")])])]),a("h4",{attrs:{id:"request-rules"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-rules"}},[t._v("#")]),t._v(" Request.Rules")]),t._v(" "),a("p",[t._v("The validation rule set associated with this request. See the "),a("router-link",{attrs:{to:"/guide/basics/validation.html"}},[t._v("validation")]),t._v(" section for more information.")],1),t._v(" "),a("h4",{attrs:{id:"request-data"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-data"}},[t._v("#")]),t._v(" Request.Data")]),t._v(" "),a("p",[t._v("A "),a("code",[t._v("map[string]interface{}")]),t._v(" containing the request's data. The key is the name of the field. This map contains the data from the request's body "),a("strong",[t._v("and")]),t._v(" the URL query string values. The request's body parameters takes precedence over the URL query string values.")]),t._v(" "),a("p",[t._v("For the given JSON request:")]),t._v(" "),a("div",{staticClass:"language-json extra-class"},[a("pre",{pre:!0,attrs:{class:"language-json"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"John Doe"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"tags"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tag1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tag2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "John Doe"')]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tags"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "[tag1 tag2]" ([]string)')]),t._v("\n")])])]),a("p",[t._v("You would obtain the same result for the following url-encoded request:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("name=John%20Doe&tags=tag1&tags=tag2\n")])])]),a("p",[t._v("Because the "),a("code",[t._v("Data")]),t._v(" attribute can hold any type of data, you will likely need type assertion. If you validated your request, checking for type assertion errors is not necessary.")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("tags"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tags"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h4",{attrs:{id:"request-params"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-params"}},[t._v("#")]),t._v(" Request.Params")]),t._v(" "),a("p",[a("code",[t._v("Params")]),t._v(" is a "),a("code",[t._v("map[string]string")]),t._v(" of the route parameters.")]),t._v(" "),a("p",[t._v("For the given route definition and request:")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("/categories/{category}/{product_id}\n")])])]),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("/categories/3/5\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"category"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "3"')]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"product_id"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "5"')]),t._v("\n")])])]),a("h4",{attrs:{id:"request-lang"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#request-lang"}},[t._v("#")]),t._v(" Request.Lang")]),t._v(" "),a("p",[a("code",[t._v("Lang")]),t._v(" indicates the language desired by the user. This attribute is automatically set by a core middleware, based on the "),a("code",[t._v("Accept-Language")]),t._v(" header, if present. If the desired language is not available, the default language is used.")]),t._v(" "),a("p",[t._v("Learn more in the "),a("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[t._v("localization")]),t._v(" section.")],1),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "en-US"')]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("lang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"validation.rules.required"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "The :field is required."')]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/19.157c7dbe.js b/docs/assets/js/19.157c7dbe.js deleted file mode 100644 index a726a8be..00000000 --- a/docs/assets/js/19.157c7dbe.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{221:function(t,s,e){"use strict";e.r(s);var a=e(0),n=Object(a.a)({},(function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"responses"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#responses"}},[t._v("#")]),t._v(" Responses")]),t._v(" "),e("p",[t._v("Handlers receive a "),e("code",[t._v("goyave.Response")]),t._v(" and a "),e("code",[t._v("goyave.Request")]),t._v(" as parameters. This section is a technical reference of the "),e("code",[t._v("Response")]),t._v(" object.")]),t._v(" "),e("p",[e("code",[t._v("goyave.Response")]),t._v(" implements "),e("code",[t._v("http.ResponseWriter")]),t._v(". This object brings a number of convenient methods to write HTTP responses.")]),t._v(" "),e("p",[t._v("If you didn't write anything before the request lifecycle ends, "),e("code",[t._v("204 No Content")]),t._v(" is automatically written.")]),t._v(" "),e("p",[t._v("All functions below require the "),e("code",[t._v("goyave")]),t._v(" package to be imported.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n")])])]),e("p",[e("strong",[t._v("List of response methods")]),t._v(":")]),t._v(" "),e("div",{staticClass:"table"},[e("p",[e("a",{attrs:{href:"#response-header"}},[t._v("Header")]),t._v(" "),e("a",{attrs:{href:"#response-status"}},[t._v("Status")]),t._v(" "),e("a",{attrs:{href:"#response-json"}},[t._v("JSON")]),t._v(" "),e("a",{attrs:{href:"#response-string"}},[t._v("String")]),t._v(" "),e("a",{attrs:{href:"#response-write"}},[t._v("Write")]),t._v(" "),e("a",{attrs:{href:"#response-file"}},[t._v("File")]),t._v(" "),e("a",{attrs:{href:"#response-download"}},[t._v("Download")]),t._v(" "),e("a",{attrs:{href:"#response-error"}},[t._v("Error")]),t._v(" "),e("a",{attrs:{href:"#response-cookie"}},[t._v("Cookie")]),t._v(" "),e("a",{attrs:{href:"#response-redirect"}},[t._v("Redirect")]),t._v(" "),e("a",{attrs:{href:"#response-temporaryredirect"}},[t._v("TemporaryRedirect")]),t._v(" "),e("a",{attrs:{href:"#response-createtestresponse"}},[t._v("CreateTestResponse")])])]),e("h4",{attrs:{id:"response-header"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-header"}},[t._v("#")]),t._v(" Response.Header")]),t._v(" "),e("p",[t._v("Returns the Header map that will be sent.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td"),t._v(" "),e("td",[e("code",[t._v("http.Header")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("header "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Header")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nheader"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Set")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Content-Type"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"application/json"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-status"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-status"}},[t._v("#")]),t._v(" Response.Status")]),t._v(" "),e("p",[t._v("Write the given status code.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("status int")])]),t._v(" "),e("td",[e("code",[t._v("void")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-json"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-json"}},[t._v("#")]),t._v(" Response.JSON")]),t._v(" "),e("p",[t._v("Write JSON data as a response. This method automatically sets the "),e("code",[t._v("Content-Type")]),t._v(" header.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("responseCode int")])]),t._v(" "),e("td",[e("code",[t._v("error")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("data interface{}")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("JSON")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"John Doe"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tags"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tag1"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tag2"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-string"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-string"}},[t._v("#")]),t._v(" Response.String")]),t._v(" "),e("p",[t._v("Write a string as a response.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("responseCode int")])]),t._v(" "),e("td",[e("code",[t._v("error")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("message string")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello there!"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-write"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-write"}},[t._v("#")]),t._v(" Response.Write")]),t._v(" "),e("p",[t._v("Write the data as a response. Can be used to write in-memory files. This method can be called successively.")]),t._v(" "),e("p",[t._v("Returns the number of bytes written.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("data []byte")])]),t._v(" "),e("td",[e("code",[t._v("int")])])]),t._v(" "),e("tr",[e("td"),t._v(" "),e("td",[e("code",[t._v("error")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello there!"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-file"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-file"}},[t._v("#")]),t._v(" Response.File")]),t._v(" "),e("p",[t._v("Write a file as an inline element.")]),t._v(" "),e("p",[t._v('Automatically detects the file MIME type and sets the "Content-Type" header accordingly. It is advised to call '),e("code",[t._v("filesystem.FileExists()")]),t._v(" before sending a file to avoid a panic and return a 404 error. The given path can be relative or absolute.")]),t._v(" "),e("p",[t._v('If you want the file to be sent as a download ("Content-Disposition: attachment"), use the "Download" function instead.')]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("file string")])]),t._v(" "),e("td",[e("code",[t._v("error")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("File")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/path/to/file"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-download"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-download"}},[t._v("#")]),t._v(" Response.Download")]),t._v(" "),e("p",[t._v("Write a file as an attachment element.")]),t._v(" "),e("p",[t._v('Automatically detects the file MIME type and sets the "Content-Type" header accordingly. It is advised to call '),e("code",[t._v("filesystem.FileExists()")]),t._v(" before sending a file to avoid a panic and return a 404 error if the file doesn't exist. The given path can be relative or absolute.")]),t._v(" "),e("p",[t._v('If you want the file to be sent as a download ("Content-Disposition: attachment"), use the "Download" function instead.')]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("file string")])]),t._v(" "),e("td",[e("code",[t._v("error")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("fileName string")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Download")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/path/to/file"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"awesome.txt"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-error"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-error"}},[t._v("#")]),t._v(" Response.Error")]),t._v(" "),e("p",[t._v("Print the error in the console and return it with an error code 500. If debugging is enabled in the config, the error is also written in the response using the JSON format, and the stacktrace is printed in the console.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("err interface{}")])]),t._v(" "),e("td",[e("code",[t._v("error")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("v"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Atoi")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"-42"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nresponse"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Error")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-cookie"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-cookie"}},[t._v("#")]),t._v(" Response.Cookie")]),t._v(" "),e("p",[t._v("Add a Set-Cookie header to the response. The provided cookie must have a valid Name. Invalid cookies may be silently dropped.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("cookie *http.Cookie*")])]),t._v(" "),e("td",[e("code",[t._v("void")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("cookie "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Cookie"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Name"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cookie-name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Value"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nresponse"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cookie")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cookie"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-redirect"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-redirect"}},[t._v("#")]),t._v(" Response.Redirect")]),t._v(" "),e("p",[t._v("Send a permanent redirect response. (HTTP 308)")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("url string")])]),t._v(" "),e("td",[e("code",[t._v("void")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Redirect")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/login"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-temporaryredirect"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-temporaryredirect"}},[t._v("#")]),t._v(" Response.TemporaryRedirect")]),t._v(" "),e("p",[t._v("Send a temporary redirect response. (HTTP 307)")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("url string")])]),t._v(" "),e("td",[e("code",[t._v("void")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("TemporaryRedirect")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/maintenance"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"response-createtestresponse"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#response-createtestresponse"}},[t._v("#")]),t._v(" Response.CreateTestResponse")]),t._v(" "),e("p",[t._v("Create an empty response with the given response writer. This function is aimed at making it easier to unit test Responses.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("recorder http.ResponseWriter")])]),t._v(" "),e("td",[e("code",[t._v("void")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("writer "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" httptest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewRecorder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nresponse "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("CreateTestResponse")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("writer"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nresponse"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusNoContent"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nresult "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" writer"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Result")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nfmt"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusCode"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 204")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/19.56b0038a.js b/docs/assets/js/19.56b0038a.js new file mode 100644 index 00000000..8142e762 --- /dev/null +++ b/docs/assets/js/19.56b0038a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{220:function(t,e,s){"use strict";s.r(e);var a=s(0),n=Object(a.a)({},(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"responses"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#responses"}},[t._v("#")]),t._v(" Responses")]),t._v(" "),s("p",[t._v("Handlers receive a "),s("code",[t._v("goyave.Response")]),t._v(" and a "),s("code",[t._v("goyave.Request")]),t._v(" as parameters. This section is a technical reference of the "),s("code",[t._v("Response")]),t._v(" object.")]),t._v(" "),s("p",[s("code",[t._v("goyave.Response")]),t._v(" implements "),s("code",[t._v("http.ResponseWriter")]),t._v(". This object brings a number of convenient methods to write HTTP responses.")]),t._v(" "),s("p",[t._v("If you didn't write anything before the request lifecycle ends, "),s("code",[t._v("204 No Content")]),t._v(" is automatically written.")]),t._v(" "),s("p",[t._v("All functions below require the "),s("code",[t._v("goyave")]),t._v(" package to be imported.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n")])])]),s("p",[s("strong",[t._v("List of response methods")]),t._v(":")]),t._v(" "),s("div",{staticClass:"table"},[s("p",[s("a",{attrs:{href:"#response-header"}},[t._v("Header")]),t._v(" "),s("a",{attrs:{href:"#response-status"}},[t._v("Status")]),t._v(" "),s("a",{attrs:{href:"#response-json"}},[t._v("JSON")]),t._v(" "),s("a",{attrs:{href:"#response-string"}},[t._v("String")]),t._v(" "),s("a",{attrs:{href:"#response-write"}},[t._v("Write")]),t._v(" "),s("a",{attrs:{href:"#response-file"}},[t._v("File")]),t._v(" "),s("a",{attrs:{href:"#response-download"}},[t._v("Download")]),t._v(" "),s("a",{attrs:{href:"#response-error"}},[t._v("Error")]),t._v(" "),s("a",{attrs:{href:"#response-cookie"}},[t._v("Cookie")]),t._v(" "),s("a",{attrs:{href:"#response-redirect"}},[t._v("Redirect")]),t._v(" "),s("a",{attrs:{href:"#response-temporaryredirect"}},[t._v("TemporaryRedirect")])])]),s("h4",{attrs:{id:"response-header"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-header"}},[t._v("#")]),t._v(" Response.Header")]),t._v(" "),s("p",[t._v("Returns the Header map that will be sent.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td"),t._v(" "),s("td",[s("code",[t._v("http.Header")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("header "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Header")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nheader"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Set")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Content-Type"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"application/json"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-status"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-status"}},[t._v("#")]),t._v(" Response.Status")]),t._v(" "),s("p",[t._v("Write the given status code.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("status int")])]),t._v(" "),s("td",[s("code",[t._v("void")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Status")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-json"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-json"}},[t._v("#")]),t._v(" Response.JSON")]),t._v(" "),s("p",[t._v("Write JSON data as a response. This method automatically sets the "),s("code",[t._v("Content-Type")]),t._v(" header.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("responseCode int")])]),t._v(" "),s("td",[s("code",[t._v("error")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("data interface{}")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("JSON")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"John Doe"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tags"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tag1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tag2"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-string"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-string"}},[t._v("#")]),t._v(" Response.String")]),t._v(" "),s("p",[t._v("Write a string as a response.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("responseCode int")])]),t._v(" "),s("td",[s("code",[t._v("error")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("message string")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello there!"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-write"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-write"}},[t._v("#")]),t._v(" Response.Write")]),t._v(" "),s("p",[t._v("Write the data as a response. Can be used to write in-memory files. This method can be called successively.")]),t._v(" "),s("p",[t._v("Returns the number of bytes written.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("data []byte")])]),t._v(" "),s("td",[s("code",[t._v("int")])])]),t._v(" "),s("tr",[s("td"),t._v(" "),s("td",[s("code",[t._v("error")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello there!"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-file"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-file"}},[t._v("#")]),t._v(" Response.File")]),t._v(" "),s("p",[t._v("Write a file as an inline element.")]),t._v(" "),s("p",[t._v('Automatically detects the file MIME type and sets the "Content-Type" header accordingly. It is advised to call '),s("code",[t._v("filesystem.FileExists()")]),t._v(" before sending a file to avoid a panic and return a 404 error. The given path can be relative or absolute.")]),t._v(" "),s("p",[t._v('If you want the file to be sent as a download ("Content-Disposition: attachment"), use the "Download" function instead.')]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("file string")])]),t._v(" "),s("td",[s("code",[t._v("error")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("File")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/path/to/file"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-download"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-download"}},[t._v("#")]),t._v(" Response.Download")]),t._v(" "),s("p",[t._v("Write a file as an attachment element.")]),t._v(" "),s("p",[t._v('Automatically detects the file MIME type and sets the "Content-Type" header accordingly. It is advised to call '),s("code",[t._v("filesystem.FileExists()")]),t._v(" before sending a file to avoid a panic and return a 404 error if the file doesn't exist. The given path can be relative or absolute.")]),t._v(" "),s("p",[t._v('If you want the file to be sent as a download ("Content-Disposition: attachment"), use the "Download" function instead.')]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("file string")])]),t._v(" "),s("td",[s("code",[t._v("error")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("fileName string")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Download")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/path/to/file"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"awesome.txt"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-error"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-error"}},[t._v("#")]),t._v(" Response.Error")]),t._v(" "),s("p",[t._v("Print the error in the console and return it with an error code 500. If debugging is enabled in the config, the error is also written in the response using the JSON format, and the stacktrace is printed in the console.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("err interface{}")])]),t._v(" "),s("td",[s("code",[t._v("error")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("v"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Atoi")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"-42"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nresponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Error")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-cookie"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-cookie"}},[t._v("#")]),t._v(" Response.Cookie")]),t._v(" "),s("p",[t._v("Add a Set-Cookie header to the response. The provided cookie must have a valid Name. Invalid cookies may be silently dropped.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("cookie *http.Cookie*")])]),t._v(" "),s("td",[s("code",[t._v("void")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("cookie "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Cookie"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cookie-name"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"value"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nresponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cookie")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cookie"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-redirect"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-redirect"}},[t._v("#")]),t._v(" Response.Redirect")]),t._v(" "),s("p",[t._v("Send a permanent redirect response. (HTTP 308)")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("url string")])]),t._v(" "),s("td",[s("code",[t._v("void")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Redirect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/login"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"response-temporaryredirect"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#response-temporaryredirect"}},[t._v("#")]),t._v(" Response.TemporaryRedirect")]),t._v(" "),s("p",[t._v("Send a temporary redirect response. (HTTP 307)")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("url string")])]),t._v(" "),s("td",[s("code",[t._v("void")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("TemporaryRedirect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/maintenance"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/2.906a9991.js b/docs/assets/js/2.6673aca7.js similarity index 100% rename from docs/assets/js/2.906a9991.js rename to docs/assets/js/2.6673aca7.js diff --git a/docs/assets/js/20.bee2c95f.js b/docs/assets/js/20.7f3d43e8.js similarity index 99% rename from docs/assets/js/20.bee2c95f.js rename to docs/assets/js/20.7f3d43e8.js index fffea8d3..796c8cb3 100644 --- a/docs/assets/js/20.bee2c95f.js +++ b/docs/assets/js/20.7f3d43e8.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{230:function(t,a,s){"use strict";s.r(a);var e=s(0),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"routing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#routing"}},[t._v("#")]),t._v(" Routing")]),t._v(" "),s("p"),s("div",{staticClass:"table-of-contents"},[s("ul",[s("li",[s("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),s("li",[s("a",{attrs:{href:"#basic-routing"}},[t._v("Basic routing")])]),s("li",[s("a",{attrs:{href:"#route-parameters"}},[t._v("Route parameters")])]),s("li",[s("a",{attrs:{href:"#validation"}},[t._v("Validation")])]),s("li",[s("a",{attrs:{href:"#groups-and-sub-routers"}},[t._v("Groups and sub-routers")])]),s("li",[s("a",{attrs:{href:"#middleware"}},[t._v("Middleware")])]),s("li",[s("a",{attrs:{href:"#serve-static-resources"}},[t._v("Serve static resources")])]),s("li",[s("a",{attrs:{href:"#native-handlers"}},[t._v("Native handlers")])])])]),s("p"),t._v(" "),s("h2",{attrs:{id:"introduction"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),s("p",[t._v("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.")]),t._v(" "),s("p",[t._v("All features below require the "),s("code",[t._v("goyave")]),t._v(" package to be imported.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n")])])]),s("p",[t._v("Routes are defined in "),s("strong",[t._v("routes registrer functions")]),t._v(". The main route registrer is passed to "),s("code",[t._v("goyave.Start()")]),t._v(" and is executed automatically with a newly created root-level "),s("strong",[t._v("router")]),t._v(".")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Register your routes here")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"basic-routing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#basic-routing"}},[t._v("#")]),t._v(" Basic routing")]),t._v(" "),s("p",[t._v("Although it's not recommended, routes can be defined using "),s("strong",[t._v("closures")]),t._v(". This is a very simple way of defining routes that can be used for scaffolding or quick testing.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/hello"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hi!"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"router-route"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#router-route"}},[t._v("#")]),t._v(" Router.Route")]),t._v(" "),s("p",[t._v("Register a new route."),s("br"),t._v("\nMultiple methods can be passed using a pipe-separated string.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("methods string")])]),t._v(" "),s("td",[s("code",[t._v("void")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("uri string")])]),t._v(" "),s("td")]),t._v(" "),s("tr",[s("td",[s("code",[t._v("handler goyave.Handler")])]),t._v(" "),s("td")]),t._v(" "),s("tr",[s("td",[s("code",[t._v("validationRules validation.RuleSet")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Examples:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/hello"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" myHandlerFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/user"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userrequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PUT|PATCH"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/user"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userrequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("goyave.Handler")]),t._v(" is an alias for "),s("code",[t._v("func(*goyave.Response, *goyave.Request)")]),t._v(".")]),t._v(" "),s("li",[t._v("Learn more about validation and rules sets "),s("router-link",{attrs:{to:"/guide/basics/validation.html"}},[t._v("here")]),t._v(".")],1)])]),t._v(" "),s("h2",{attrs:{id:"route-parameters"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#route-parameters"}},[t._v("#")]),t._v(" Route parameters")]),t._v(" "),s("p",[t._v("URIs can have parameters, defined using the format "),s("code",[t._v("{name}")]),t._v(" or "),s("code",[t._v("{name:pattern}")]),t._v(". If a regular expression pattern is not defined, the matched variable will be anything until the next slash.")]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/products/{key}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Show"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/products/{id:[0-9]+}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ShowById"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/categories/{category}/{id:[0-9]+}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" category"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Show"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Regex groups can be used inside patterns, as long as they are non-capturing ("),s("code",[t._v("(?:re)")]),t._v("). For example:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/categories/{category}/{sort:(?:asc|desc|new)}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" category"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ShowSorted"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Route parameters can be retrieved as a "),s("code",[t._v("map[string]string")]),t._v(" in handlers using the request's "),s("code",[t._v("Params")]),t._v(" attribute.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("myHandlerFunction")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n category "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"category"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Atoi")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"validation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#validation"}},[t._v("#")]),t._v(" Validation")]),t._v(" "),s("p",[t._v("You can assign a validation rules set to each route. Learn more in the dedicated "),s("router-link",{attrs:{to:"/guide/basics/validation.html"}},[t._v("section")]),t._v(". You should always validate incoming requests.")],1),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/products"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Create"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" validation"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Name"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"min:4"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Price"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"numeric"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("It's not recommended to define rules set directly in the route definition. You should define rules sets in the "),s("code",[t._v("http/requests")]),t._v(" directory and have one file per feature, regrouping all requests handled by the same controller. You can also create one package per feature, just like controllers, if you so desire.")])]),t._v(" "),s("p",[t._v("If you don't want your route to be validated, or if validation is not necessary, just pass "),s("code",[t._v("nil")]),t._v(" as the last parameter.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/products/{id}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Show"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"groups-and-sub-routers"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#groups-and-sub-routers"}},[t._v("#")]),t._v(" Groups and sub-routers")]),t._v(" "),s("p",[t._v("Grouping routes makes it easier to define multiple routes having the same prefix and/or middlewares.")]),t._v(" "),s("p",[t._v("Let's take a simple scenario where we want to implement a user CRUD. All our routes will start with "),s("code",[t._v("/user")]),t._v(", so we are going to create a sub-router for it:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("userRouter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Subrouter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/user"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("In our application, user profiles are public: anyone can see the user profiles without being authenticated. However, only authenticated users can modify their information and delete their account. We don't want to add some redundancy and apply the authentication middleware for each route needing it, so we are going to create another sub-router.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("userRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/{username}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Show"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nuserRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userrequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nauthUserRouter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" userRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Subrouter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Don't add a prefix")]),t._v("\nauthUserRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authenticationMiddleware"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nauthUserRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PUT"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userrequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nauthUserRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"DELETE"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Delete"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("To improve your routes definition readability, you should create a new route registrer for each feature. In our example, our definitions would look like this:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("registerUserRoutes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Register is the main route registrer.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("registerUserRoutes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("registerProductsRoutes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"middleware"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),s("p",[t._v("Middleware are handlers executed before the controller handler. Learn more in the dedicated "),s("router-link",{attrs:{to:"/guide/basics/middleware.html"}},[t._v("section")]),t._v(".")],1),t._v(" "),s("p",[t._v("Middleware are applied to a router or a sub-router "),s("strong",[t._v("before the routes definition")]),t._v(". Therefore, all routes in that router and its sub-routers will execute them before executing their associated handler.")]),t._v(" "),s("p",[t._v("To assign a middleware to a router, use the "),s("code",[t._v("router.Middleware()")]),t._v(" function. Many middleware can be assigned at once. The assignment order is important as middleware will be "),s("strong",[t._v("executed in order")]),t._v(".")]),t._v(" "),s("h4",{attrs:{id:"router-middleware"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#router-middleware"}},[t._v("#")]),t._v(" Router.Middleware")]),t._v(" "),s("p",[t._v("Middleware apply one or more middleware(s) to the route group.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("middleware ...Middleware")])]),t._v(" "),s("td",[s("code",[t._v("void")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("DisallowNonValidatedFields"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"serve-static-resources"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#serve-static-resources"}},[t._v("#")]),t._v(" Serve static resources")]),t._v(" "),s("p",[t._v("The Goyave router provides a way to serve a directory of static resources, including its sub-directories.")]),t._v(" "),s("p",[t._v("Let's say you have the following directory structure:")]),t._v(" "),s("pre",{staticClass:"vue-container"},[s("code",[s("p",[t._v(".\n└── static\n   ├── js\n   │ └── index.js\n   ├── img\n   │   ├── favicon.ico\n   │   └── logo.png\n   ├── css\n   │ └── styles.css\n   └── index.html")]),t._v("\n")])]),s("p",[t._v("If you want to serve the "),s("code",[t._v("static")]),t._v(" directory, register the following route:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Static")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"static"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("If a user requests "),s("code",[t._v("http://yourdomain.com/js/index.js")]),t._v(", the corresponding file will be sent as a response.")]),t._v(" "),s("p",[t._v("If no file is given ("),s("code",[t._v("http://yourdomain.com/")]),t._v("), or if the request URI is a directory ("),s("code",[t._v("http://yourdomain.com/img")]),t._v("), Goyave will look for a "),s("code",[t._v("index.html")]),t._v(" file and send it if it exists. An error 404 Not Found is otherwise returned.")]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("This method is especially useful to serve Single Page Applications from your API. (Angular, Vue.js, React applications)")])]),t._v(" "),s("h4",{attrs:{id:"router-static"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#router-static"}},[t._v("#")]),t._v(" Router.Static")]),t._v(" "),s("p",[t._v("Static serve a directory and its sub-directories of static resources.\nSet the "),s("code",[t._v("download")]),t._v(" parameter to true if you want the files to be sent as an attachment instead of an inline element.")]),t._v(" "),s("p",[t._v("The "),s("code",[t._v("directory")]),t._v(" parameter can be a relative or an absolute path.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("uri string")])]),t._v(" "),s("td",[s("code",[t._v("void")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("directory string")])]),t._v(" "),s("td")]),t._v(" "),s("tr",[s("td",[s("code",[t._v("download bool")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Static")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/public"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/path/to/static/dir"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"native-handlers"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#native-handlers"}},[t._v("#")]),t._v(" Native handlers")]),t._v(" "),s("p",[s("Badge",{attrs:{text:"Since v2.0.0"}})],1),t._v(" "),s("h4",{attrs:{id:"goyave-nativehandler"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#goyave-nativehandler"}},[t._v("#")]),t._v(" goyave.NativeHandler")]),t._v(" "),s("p",[t._v("NativeHandler is an adapter function for "),s("code",[t._v("http.Handler")]),t._v(". With this adapter, you can plug non-Goyave handlers to your application.")]),t._v(" "),s("p",[t._v("If the request is a JSON request, the native handler will not be able to read the body, as it has already been parsed by the framework and is stored in the "),s("code",[t._v("goyave.Request")]),t._v(" object. However, form data can be accessed as usual. Just remember that it contains the raw data, which haven't been validated nor converted. This means that "),s("strong",[t._v("native handlers are not guaranteed to work")]),t._v(".")]),t._v(" "),s("p",[t._v("The actual response writer passed to the native handler is a "),s("code",[t._v("goyave.Response")]),t._v(".")]),t._v(" "),s("div",{staticClass:"custom-block warning"},[s("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),s("p",[t._v("This feature is a compatibility layer with the rest of the Golang web ecosystem. Prefer using Goyave handlers if possible.")])]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("handler http.Handler")])]),t._v(" "),s("td",[s("code",[t._v("goyave.Handler")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("httpHandler "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandlerFunc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ResponseWriter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n w"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello world"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/user"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NativeHandler")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("httpHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"goyave-nativemiddleware"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#goyave-nativemiddleware"}},[t._v("#")]),t._v(" goyave.NativeMiddleware")]),t._v(" "),s("p",[t._v("NativeMiddleware is an adapter function "),s("code",[t._v("mux.MiddlewareFunc")]),t._v(". With this adapter, you can plug "),s("a",{attrs:{href:"https://github.com/gorilla/mux#middleware",target:"_blank",rel:"noopener noreferrer"}},[t._v("Gorilla Mux middleware"),s("OutboundLink")],1),t._v(" to your application.")]),t._v(" "),s("p",[t._v("Native middleware work like native handlers. See "),s("a",{attrs:{href:"#goyave-nativehandler"}},[s("code",[t._v("NativeHandler")])]),t._v(" for more details.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("middleware mux.MiddlewareFunc")])]),t._v(" "),s("td",[s("code",[t._v("goyave.Middelware")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("middleware "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NativeMiddleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("next http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandlerFunc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ResponseWriter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n w"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello world"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n next"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ServeHTTP")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Don\'t call "next" if your middleware is blocking.')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{229:function(t,a,s){"use strict";s.r(a);var e=s(0),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"routing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#routing"}},[t._v("#")]),t._v(" Routing")]),t._v(" "),s("p"),s("div",{staticClass:"table-of-contents"},[s("ul",[s("li",[s("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),s("li",[s("a",{attrs:{href:"#basic-routing"}},[t._v("Basic routing")])]),s("li",[s("a",{attrs:{href:"#route-parameters"}},[t._v("Route parameters")])]),s("li",[s("a",{attrs:{href:"#validation"}},[t._v("Validation")])]),s("li",[s("a",{attrs:{href:"#groups-and-sub-routers"}},[t._v("Groups and sub-routers")])]),s("li",[s("a",{attrs:{href:"#middleware"}},[t._v("Middleware")])]),s("li",[s("a",{attrs:{href:"#serve-static-resources"}},[t._v("Serve static resources")])]),s("li",[s("a",{attrs:{href:"#native-handlers"}},[t._v("Native handlers")])])])]),s("p"),t._v(" "),s("h2",{attrs:{id:"introduction"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),s("p",[t._v("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.")]),t._v(" "),s("p",[t._v("All features below require the "),s("code",[t._v("goyave")]),t._v(" package to be imported.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n")])])]),s("p",[t._v("Routes are defined in "),s("strong",[t._v("routes registrer functions")]),t._v(". The main route registrer is passed to "),s("code",[t._v("goyave.Start()")]),t._v(" and is executed automatically with a newly created root-level "),s("strong",[t._v("router")]),t._v(".")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Register your routes here")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"basic-routing"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#basic-routing"}},[t._v("#")]),t._v(" Basic routing")]),t._v(" "),s("p",[t._v("Although it's not recommended, routes can be defined using "),s("strong",[t._v("closures")]),t._v(". This is a very simple way of defining routes that can be used for scaffolding or quick testing.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/hello"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hi!"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"router-route"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#router-route"}},[t._v("#")]),t._v(" Router.Route")]),t._v(" "),s("p",[t._v("Register a new route."),s("br"),t._v("\nMultiple methods can be passed using a pipe-separated string.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("methods string")])]),t._v(" "),s("td",[s("code",[t._v("void")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("uri string")])]),t._v(" "),s("td")]),t._v(" "),s("tr",[s("td",[s("code",[t._v("handler goyave.Handler")])]),t._v(" "),s("td")]),t._v(" "),s("tr",[s("td",[s("code",[t._v("validationRules validation.RuleSet")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Examples:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/hello"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" myHandlerFunction"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/user"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userrequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PUT|PATCH"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/user"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userrequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("goyave.Handler")]),t._v(" is an alias for "),s("code",[t._v("func(*goyave.Response, *goyave.Request)")]),t._v(".")]),t._v(" "),s("li",[t._v("Learn more about validation and rules sets "),s("router-link",{attrs:{to:"/guide/basics/validation.html"}},[t._v("here")]),t._v(".")],1)])]),t._v(" "),s("h2",{attrs:{id:"route-parameters"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#route-parameters"}},[t._v("#")]),t._v(" Route parameters")]),t._v(" "),s("p",[t._v("URIs can have parameters, defined using the format "),s("code",[t._v("{name}")]),t._v(" or "),s("code",[t._v("{name:pattern}")]),t._v(". If a regular expression pattern is not defined, the matched variable will be anything until the next slash.")]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/products/{key}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Show"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/products/{id:[0-9]+}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ShowById"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/categories/{category}/{id:[0-9]+}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" category"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Show"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Regex groups can be used inside patterns, as long as they are non-capturing ("),s("code",[t._v("(?:re)")]),t._v("). For example:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/categories/{category}/{sort:(?:asc|desc|new)}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" category"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ShowSorted"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Route parameters can be retrieved as a "),s("code",[t._v("map[string]string")]),t._v(" in handlers using the request's "),s("code",[t._v("Params")]),t._v(" attribute.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("myHandlerFunction")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n category "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"category"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n id"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" strconv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Atoi")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Params"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"validation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#validation"}},[t._v("#")]),t._v(" Validation")]),t._v(" "),s("p",[t._v("You can assign a validation rules set to each route. Learn more in the dedicated "),s("router-link",{attrs:{to:"/guide/basics/validation.html"}},[t._v("section")]),t._v(". You should always validate incoming requests.")],1),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/products"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Create"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" validation"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Name"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"min:4"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Price"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"numeric"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("It's not recommended to define rules set directly in the route definition. You should define rules sets in the "),s("code",[t._v("http/requests")]),t._v(" directory and have one file per feature, regrouping all requests handled by the same controller. You can also create one package per feature, just like controllers, if you so desire.")])]),t._v(" "),s("p",[t._v("If you don't want your route to be validated, or if validation is not necessary, just pass "),s("code",[t._v("nil")]),t._v(" as the last parameter.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/products/{id}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Show"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"groups-and-sub-routers"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#groups-and-sub-routers"}},[t._v("#")]),t._v(" Groups and sub-routers")]),t._v(" "),s("p",[t._v("Grouping routes makes it easier to define multiple routes having the same prefix and/or middlewares.")]),t._v(" "),s("p",[t._v("Let's take a simple scenario where we want to implement a user CRUD. All our routes will start with "),s("code",[t._v("/user")]),t._v(", so we are going to create a sub-router for it:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("userRouter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Subrouter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/user"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("In our application, user profiles are public: anyone can see the user profiles without being authenticated. However, only authenticated users can modify their information and delete their account. We don't want to add some redundancy and apply the authentication middleware for each route needing it, so we are going to create another sub-router.")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("userRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/{username}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Show"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nuserRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"POST"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userrequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nauthUserRouter "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" userRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Subrouter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Don't add a prefix")]),t._v("\nauthUserRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("authenticationMiddleware"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nauthUserRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PUT"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" userrequest"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Update"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nauthUserRouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"DELETE"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" user"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Delete"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("To improve your routes definition readability, you should create a new route registrer for each feature. In our example, our definitions would look like this:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("registerUserRoutes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Register is the main route registrer.")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("registerUserRoutes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("registerProductsRoutes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"middleware"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#middleware"}},[t._v("#")]),t._v(" Middleware")]),t._v(" "),s("p",[t._v("Middleware are handlers executed before the controller handler. Learn more in the dedicated "),s("router-link",{attrs:{to:"/guide/basics/middleware.html"}},[t._v("section")]),t._v(".")],1),t._v(" "),s("p",[t._v("Middleware are applied to a router or a sub-router "),s("strong",[t._v("before the routes definition")]),t._v(". Therefore, all routes in that router and its sub-routers will execute them before executing their associated handler.")]),t._v(" "),s("p",[t._v("To assign a middleware to a router, use the "),s("code",[t._v("router.Middleware()")]),t._v(" function. Many middleware can be assigned at once. The assignment order is important as middleware will be "),s("strong",[t._v("executed in order")]),t._v(".")]),t._v(" "),s("h4",{attrs:{id:"router-middleware"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#router-middleware"}},[t._v("#")]),t._v(" Router.Middleware")]),t._v(" "),s("p",[t._v("Middleware apply one or more middleware(s) to the route group.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("middleware ...Middleware")])]),t._v(" "),s("td",[s("code",[t._v("void")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("DisallowNonValidatedFields"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"serve-static-resources"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#serve-static-resources"}},[t._v("#")]),t._v(" Serve static resources")]),t._v(" "),s("p",[t._v("The Goyave router provides a way to serve a directory of static resources, including its sub-directories.")]),t._v(" "),s("p",[t._v("Let's say you have the following directory structure:")]),t._v(" "),s("pre",{staticClass:"vue-container"},[s("code",[s("p",[t._v(".\n└── static\n   ├── js\n   │ └── index.js\n   ├── img\n   │   ├── favicon.ico\n   │   └── logo.png\n   ├── css\n   │ └── styles.css\n   └── index.html")]),t._v("\n")])]),s("p",[t._v("If you want to serve the "),s("code",[t._v("static")]),t._v(" directory, register the following route:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Static")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"static"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("If a user requests "),s("code",[t._v("http://yourdomain.com/js/index.js")]),t._v(", the corresponding file will be sent as a response.")]),t._v(" "),s("p",[t._v("If no file is given ("),s("code",[t._v("http://yourdomain.com/")]),t._v("), or if the request URI is a directory ("),s("code",[t._v("http://yourdomain.com/img")]),t._v("), Goyave will look for a "),s("code",[t._v("index.html")]),t._v(" file and send it if it exists. An error 404 Not Found is otherwise returned.")]),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("This method is especially useful to serve Single Page Applications from your API. (Angular, Vue.js, React applications)")])]),t._v(" "),s("h4",{attrs:{id:"router-static"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#router-static"}},[t._v("#")]),t._v(" Router.Static")]),t._v(" "),s("p",[t._v("Static serve a directory and its sub-directories of static resources.\nSet the "),s("code",[t._v("download")]),t._v(" parameter to true if you want the files to be sent as an attachment instead of an inline element.")]),t._v(" "),s("p",[t._v("The "),s("code",[t._v("directory")]),t._v(" parameter can be a relative or an absolute path.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("uri string")])]),t._v(" "),s("td",[s("code",[t._v("void")])])]),t._v(" "),s("tr",[s("td",[s("code",[t._v("directory string")])]),t._v(" "),s("td")]),t._v(" "),s("tr",[s("td",[s("code",[t._v("download bool")])]),t._v(" "),s("td")])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Static")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/public"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/path/to/static/dir"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"native-handlers"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#native-handlers"}},[t._v("#")]),t._v(" Native handlers")]),t._v(" "),s("p",[s("Badge",{attrs:{text:"Since v2.0.0"}})],1),t._v(" "),s("h4",{attrs:{id:"goyave-nativehandler"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#goyave-nativehandler"}},[t._v("#")]),t._v(" goyave.NativeHandler")]),t._v(" "),s("p",[t._v("NativeHandler is an adapter function for "),s("code",[t._v("http.Handler")]),t._v(". With this adapter, you can plug non-Goyave handlers to your application.")]),t._v(" "),s("p",[t._v("If the request is a JSON request, the native handler will not be able to read the body, as it has already been parsed by the framework and is stored in the "),s("code",[t._v("goyave.Request")]),t._v(" object. However, form data can be accessed as usual. Just remember that it contains the raw data, which haven't been validated nor converted. This means that "),s("strong",[t._v("native handlers are not guaranteed to work")]),t._v(".")]),t._v(" "),s("p",[t._v("The actual response writer passed to the native handler is a "),s("code",[t._v("goyave.Response")]),t._v(".")]),t._v(" "),s("div",{staticClass:"custom-block warning"},[s("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),s("p",[t._v("This feature is a compatibility layer with the rest of the Golang web ecosystem. Prefer using Goyave handlers if possible.")])]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("handler http.Handler")])]),t._v(" "),s("td",[s("code",[t._v("goyave.Handler")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("httpHandler "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandlerFunc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ResponseWriter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n w"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello world"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/user"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NativeHandler")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("httpHandler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h4",{attrs:{id:"goyave-nativemiddleware"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#goyave-nativemiddleware"}},[t._v("#")]),t._v(" goyave.NativeMiddleware")]),t._v(" "),s("p",[t._v("NativeMiddleware is an adapter function "),s("code",[t._v("mux.MiddlewareFunc")]),t._v(". With this adapter, you can plug "),s("a",{attrs:{href:"https://github.com/gorilla/mux#middleware",target:"_blank",rel:"noopener noreferrer"}},[t._v("Gorilla Mux middleware"),s("OutboundLink")],1),t._v(" to your application.")]),t._v(" "),s("p",[t._v("Native middleware work like native handlers. See "),s("a",{attrs:{href:"#goyave-nativehandler"}},[s("code",[t._v("NativeHandler")])]),t._v(" for more details.")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",[t._v("Parameters")]),t._v(" "),s("th",[t._v("Return")])])]),t._v(" "),s("tbody",[s("tr",[s("td",[s("code",[t._v("middleware mux.MiddlewareFunc")])]),t._v(" "),s("td",[s("code",[t._v("goyave.Middelware")])])])])]),t._v(" "),s("p",[s("strong",[t._v("Example:")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("middleware "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NativeMiddleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("next http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Handler "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandlerFunc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ResponseWriter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n w"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello world"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n next"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ServeHTTP")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Don\'t call "next" if your middleware is blocking.')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nrouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Middleware")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("middleware"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/21.83573c32.js b/docs/assets/js/21.f4152867.js similarity index 73% rename from docs/assets/js/21.83573c32.js rename to docs/assets/js/21.f4152867.js index 114b17c3..8a455077 100644 --- a/docs/assets/js/21.83573c32.js +++ b/docs/assets/js/21.f4152867.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[21],{232:function(t,a,e){"use strict";e.r(a);var s=e(0),n=Object(s.a)({},(function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"validation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation"}},[t._v("#")]),t._v(" Validation")]),t._v(" "),e("p"),e("div",{staticClass:"table-of-contents"},[e("ul",[e("li",[e("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),e("li",[e("a",{attrs:{href:"#rules-sets"}},[t._v("Rules sets")])]),e("li",[e("a",{attrs:{href:"#available-validation-rules"}},[t._v("Available validation rules")])]),e("li",[e("a",{attrs:{href:"#custom-rules"}},[t._v("Custom rules")])]),e("li",[e("a",{attrs:{href:"#validating-arrays"}},[t._v("Validating arrays")]),e("ul",[e("li",[e("a",{attrs:{href:"#n-dimensional-arrays"}},[t._v("N-dimensional arrays")])])])]),e("li",[e("a",{attrs:{href:"#placeholders"}},[t._v("Placeholders")]),e("ul",[e("li",[e("a",{attrs:{href:"#available-placeholders"}},[t._v("Available placeholders")])])])]),e("li",[e("a",{attrs:{href:"#manual-validation"}},[t._v("Manual validation")])])])]),e("p"),t._v(" "),e("h2",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),e("p",[t._v("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.")]),t._v(" "),e("p",[t._v("Incoming requests are validated using "),e("strong",[t._v("rules set")]),t._v(", which associate rules with each expected field in the request.")]),t._v(" "),e("p",[t._v("Validation rules can "),e("strong",[t._v("alter the raw data")]),t._v(". 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 "),e("code",[t._v("float64")]),t._v(". Or if you're validating an IP, you get a "),e("code",[t._v("net.IP")]),t._v(" object.")]),t._v(" "),e("p",[t._v("If a request contains a field with a "),e("code",[t._v("nil")]),t._v("/"),e("code",[t._v("null")]),t._v(" value, and that this field doesn't have the "),e("code",[t._v("nullable")]),t._v(" rule, the field is "),e("strong",[t._v("removed")]),t._v(" entirely from the request.")]),t._v(" "),e("p",[t._v("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, using the correct "),e("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[t._v("language")]),t._v(". The HTTP response code of failed validation is "),e("strong",[t._v('422 "Unprocessable Entity"')]),t._v(", or "),e("strong",[t._v('400 "Bad Request"')]),t._v(" if the body could not be parsed.")],1),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("You can customize the validation error messages by editing "),e("code",[t._v("resources/lang//rules.json")]),t._v(". Learn more in the "),e("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[t._v("localization")]),t._v(" section.")],1)]),t._v(" "),e("p",[t._v("The following features require the "),e("code",[t._v("validation")]),t._v(" package to be imported.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/validation"')]),t._v("\n")])])]),e("h2",{attrs:{id:"rules-sets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rules-sets"}},[t._v("#")]),t._v(" Rules sets")]),t._v(" "),e("p",[t._v("The "),e("code",[t._v("http/request")]),t._v(" directory contains the requests validation rules sets. You should have one package per feature, regrouping all requests handled by the same controller. The package should be named "),e("code",[t._v("request")]),t._v(".")]),t._v(" "),e("p",[e("strong",[t._v("Example:")]),t._v(" ("),e("code",[t._v("http/request/productrequest/product.go")]),t._v(")")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tStore validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"between:3,50"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"price"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"numeric"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"min:0.01"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nullable"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"file"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"max:2048"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"count:1"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),e("p",[e("strong",[t._v("The order in which you assign rules is important")]),t._v(", as rules are executed in this order. The rules checking for the type of the data should "),e("strong",[t._v("always be first")]),t._v(", or after "),e("code",[t._v("required")]),t._v(" and "),e("code",[t._v("nullable")]),t._v(".")]),t._v(" "),e("p",[t._v("If a field is not "),e("strong",[t._v("required")]),t._v(" and is missing from the request, "),e("strong",[t._v("no rules are checked")]),t._v("!")])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[e("code",[t._v("validation.RuleSet")]),t._v(" is an alias for "),e("code",[t._v("map[string][]string")])])]),t._v(" "),e("hr"),t._v(" "),e("p",[t._v("Once your rules sets are defined, you need to assign them to your routes. The rule set for a route is the last parameter of the route definition. Learn more about routing in the "),e("router-link",{attrs:{to:"/guide/basics/routing.html"}},[t._v("dedicated section")]),t._v(".")],1),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("router"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"POST"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/product"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Store"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" productrequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Store"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h2",{attrs:{id:"available-validation-rules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#available-validation-rules"}},[t._v("#")]),t._v(" Available validation rules")]),t._v(" "),e("div",{staticClass:"table"},[e("p",[e("a",{attrs:{href:"#required"}},[t._v("Required")]),t._v(" "),e("a",{attrs:{href:"#nullable"}},[t._v("Nullable")]),t._v(" "),e("a",{attrs:{href:"#numeric"}},[t._v("Numeric")]),t._v(" "),e("a",{attrs:{href:"#integer"}},[t._v("Integer")]),t._v(" "),e("a",{attrs:{href:"#min-value"}},[t._v("Min")]),t._v(" "),e("a",{attrs:{href:"#max-value"}},[t._v("Max")]),t._v(" "),e("a",{attrs:{href:"#between-min-max"}},[t._v("Between")]),t._v(" "),e("a",{attrs:{href:"#greater-than-field"}},[t._v("Greater than")]),t._v(" "),e("a",{attrs:{href:"#greater-than-equal-field"}},[t._v("Greater than or equal")]),t._v(" "),e("a",{attrs:{href:"#lower-than-field"}},[t._v("Lower than")]),t._v(" "),e("a",{attrs:{href:"#lower-than-equal-field"}},[t._v("Lower than or equal")]),t._v(" "),e("a",{attrs:{href:"#string"}},[t._v("String")]),t._v(" "),e("a",{attrs:{href:"#array-type"}},[t._v("Array")]),t._v(" "),e("a",{attrs:{href:"#distinct"}},[t._v("Distinct")]),t._v(" "),e("a",{attrs:{href:"#digits"}},[t._v("Digits")]),t._v(" "),e("a",{attrs:{href:"#regex-pattern"}},[t._v("Regex")]),t._v(" "),e("a",{attrs:{href:"#email"}},[t._v("Email")]),t._v(" "),e("a",{attrs:{href:"#size-value"}},[t._v("Size")]),t._v(" "),e("a",{attrs:{href:"#alpha"}},[t._v("Alpha")]),t._v(" "),e("a",{attrs:{href:"#alpha-dash"}},[t._v("Alpha dash")]),t._v(" "),e("a",{attrs:{href:"#alpha-num"}},[t._v("Alpha numeric")]),t._v(" "),e("a",{attrs:{href:"#starts-with-value1"}},[t._v("Starts with")]),t._v(" "),e("a",{attrs:{href:"#ends-with-value1"}},[t._v("Ends with")]),t._v(" "),e("a",{attrs:{href:"#in-value1-value2"}},[t._v("In")]),t._v(" "),e("a",{attrs:{href:"#not-in-value1-value2"}},[t._v("Not in")]),t._v(" "),e("a",{attrs:{href:"#in-array-field"}},[t._v("In array")]),t._v(" "),e("a",{attrs:{href:"#not-in-array-field"}},[t._v("Not in array")]),t._v(" "),e("a",{attrs:{href:"#timezone"}},[t._v("Timezone")]),t._v(" "),e("a",{attrs:{href:"#ip"}},[t._v("IP")]),t._v(" "),e("a",{attrs:{href:"#ipv4"}},[t._v("IPv4")]),t._v(" "),e("a",{attrs:{href:"#ipv6"}},[t._v("IPv6")]),t._v(" "),e("a",{attrs:{href:"#json"}},[t._v("JSON")]),t._v(" "),e("a",{attrs:{href:"#url"}},[t._v("URL")]),t._v(" "),e("a",{attrs:{href:"#uuid-version"}},[t._v("UUID")]),t._v(" "),e("a",{attrs:{href:"#bool"}},[t._v("Bool")]),t._v(" "),e("a",{attrs:{href:"#same-field"}},[t._v("Same")]),t._v(" "),e("a",{attrs:{href:"#different-field"}},[t._v("Different")]),t._v(" "),e("a",{attrs:{href:"#confirmed"}},[t._v("Confirmed")]),t._v(" "),e("a",{attrs:{href:"#file"}},[t._v("File")]),t._v(" "),e("a",{attrs:{href:"#mime-foo"}},[t._v("MIME")]),t._v(" "),e("a",{attrs:{href:"#image"}},[t._v("Image")]),t._v(" "),e("a",{attrs:{href:"#extension-foo"}},[t._v("Extension")]),t._v(" "),e("a",{attrs:{href:"#count-value"}},[t._v("Count")]),t._v(" "),e("a",{attrs:{href:"#count-min-value"}},[t._v("Count min")]),t._v(" "),e("a",{attrs:{href:"#count-max-value"}},[t._v("Count max")]),t._v(" "),e("a",{attrs:{href:"#count-between-min-max"}},[t._v("Count between")]),t._v(" "),e("a",{attrs:{href:"#date-format"}},[t._v("Date")]),t._v(" "),e("a",{attrs:{href:"#before-date"}},[t._v("Before")]),t._v(" "),e("a",{attrs:{href:"#before-equal-date"}},[t._v("Before or equal")]),t._v(" "),e("a",{attrs:{href:"#after-date"}},[t._v("After")]),t._v(" "),e("a",{attrs:{href:"#after-equal-date"}},[t._v("After or equal")]),t._v(" "),e("a",{attrs:{href:"#date-equals-date"}},[t._v("Date equals")]),t._v(" "),e("a",{attrs:{href:"#date-between-date1-date2"}},[t._v("Date between")])])]),e("h4",{attrs:{id:"required"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#required"}},[t._v("#")]),t._v(" required")]),t._v(" "),e("p",[t._v("The field under validation must be present.")]),t._v(" "),e("p",[t._v("If the field is a string, the string must not be empty. If a field is "),e("code",[t._v("null")]),t._v(" and has the "),e("code",[t._v("nullable")]),t._v(" rule, the "),e("code",[t._v("required")]),t._v(" rules passes. As non-nullable fields are removed if they have a "),e("code",[t._v("null")]),t._v(" value, the "),e("code",[t._v("required")]),t._v(" rule doesn't pass if a field is "),e("code",[t._v("null")]),t._v(" and doesn't have the "),e("code",[t._v("nullable")]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"nullable"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#nullable"}},[t._v("#")]),t._v(" nullable")]),t._v(" "),e("p",[t._v("The field under validation can have a "),e("code",[t._v("nil")]),t._v("/"),e("code",[t._v("null")]),t._v(" value. If this rule is missing from the rules set, the field will be "),e("strong",[t._v("removed")]),t._v(" if it is "),e("code",[t._v("null")]),t._v(". This rule is especially useful when working with JSON requests or with primitives that can contain null values.")]),t._v(" "),e("p",[t._v("Be sure to check if your field is not null before using it in your handlers.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In this example, field is numeric")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" val"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" exists "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" exists "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" val "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h4",{attrs:{id:"numeric"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#numeric"}},[t._v("#")]),t._v(" numeric")]),t._v(" "),e("p",[t._v("The field under validation must be numeric. Strings that can be converted to numbers are accepted.\nThis rule converts the field to "),e("code",[t._v("float64")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"integer"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#integer"}},[t._v("#")]),t._v(" integer")]),t._v(" "),e("p",[t._v("The field under validation must be an integer. Strings that can be converted to an integer are accepted.\nThis rule converts the field to "),e("code",[t._v("int")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"min-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#min-value"}},[t._v("#")]),t._v(" min:value")]),t._v(" "),e("p",[t._v("Depending on its type, the field under validation must be at least "),e("code",[t._v("min")]),t._v(".\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"max-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#max-value"}},[t._v("#")]),t._v(" max:value")]),t._v(" "),e("p",[t._v("Depending on its type, the field under validation must not be superior to "),e("code",[t._v("value")]),t._v(".\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"between-min-max"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#between-min-max"}},[t._v("#")]),t._v(" between:min,max")]),t._v(" "),e("p",[t._v("Depending on its type, the field under validation must be between "),e("code",[t._v("min")]),t._v(" and "),e("code",[t._v("max")]),t._v(".\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"greater-than-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#greater-than-field"}},[t._v("#")]),t._v(" greater_than:field")]),t._v(" "),e("p",[t._v("The field under validation must be greater than the given "),e("code",[t._v("field")]),t._v(". The two fields must have the same type.\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"greater-than-equal-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#greater-than-equal-field"}},[t._v("#")]),t._v(" greater_than_equal:field")]),t._v(" "),e("p",[t._v("The field under validation must be greater or equal to the given "),e("code",[t._v("field")]),t._v(". The two fields must have the same type.\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"lower-than-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lower-than-field"}},[t._v("#")]),t._v(" lower_than:field")]),t._v(" "),e("p",[t._v("The field under validation must be lower than the given "),e("code",[t._v("field")]),t._v(". The two fields must have the same type.\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"lower-than-equal-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lower-than-equal-field"}},[t._v("#")]),t._v(" lower_than_equal:field")]),t._v(" "),e("p",[t._v("The field under validation must be lower or equal to the given "),e("code",[t._v("field")]),t._v(". The two fields must have the same type.\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"string"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#string"}},[t._v("#")]),t._v(" string")]),t._v(" "),e("p",[t._v("The field under validation must be a string.")]),t._v(" "),e("h4",{attrs:{id:"array-type"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#array-type"}},[t._v("#")]),t._v(" array:type")]),t._v(" "),e("p",[t._v("The field under validation must be an array. The "),e("code",[t._v("type")]),t._v(" parameter is "),e("strong",[t._v("optional")]),t._v(".")]),t._v(" "),e("p",[t._v("If no type is provided, the field has the type "),e("code",[t._v("[]interface{}")]),t._v(" after validation. If a type is provided, the array is converted to a slice of the correct type, and all values in the array are validated in the same way as standard fields.")]),t._v(" "),e("p",[t._v("For example, with the rule "),e("code",[t._v("array:url")]),t._v(", all values must be valid URLs and the field will be converted to "),e("code",[t._v("[]*url.URL")]),t._v(".")]),t._v(" "),e("p",[e("strong",[t._v("Available types:")])]),t._v(" "),e("ul",[e("li",[e("code",[t._v("string")])]),t._v(" "),e("li",[e("code",[t._v("numeric")])]),t._v(" "),e("li",[e("code",[t._v("integer")])]),t._v(" "),e("li",[e("code",[t._v("timezone")])]),t._v(" "),e("li",[e("code",[t._v("ip")]),t._v(", "),e("code",[t._v("ipv4")]),t._v(", "),e("code",[t._v("ipv6")])]),t._v(" "),e("li",[e("code",[t._v("url")])]),t._v(" "),e("li",[e("code",[t._v("uuid")])]),t._v(" "),e("li",[e("code",[t._v("bool")])]),t._v(" "),e("li",[e("code",[t._v("date")])])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("For the "),e("code",[t._v("uuid")]),t._v(" and "),e("code",[t._v("date")]),t._v(" types, you can pass a second parameter: "),e("code",[t._v("array:date,02-01-2006")])])]),t._v(" "),e("h4",{attrs:{id:"distinct"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#distinct"}},[t._v("#")]),t._v(" distinct")]),t._v(" "),e("p",[t._v("The field under validation must be an array and have distinct values.")]),t._v(" "),e("h4",{attrs:{id:"digits"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#digits"}},[t._v("#")]),t._v(" digits")]),t._v(" "),e("p",[t._v("The field under validation must be a string and contain only digits.")]),t._v(" "),e("h4",{attrs:{id:"regex-pattern"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#regex-pattern"}},[t._v("#")]),t._v(" regex:pattern")]),t._v(" "),e("p",[t._v("The field under validation must be a string and match the given "),e("code",[t._v("pattern")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"email"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#email"}},[t._v("#")]),t._v(" email")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be an email address.")]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),e("p",[t._v("This rule is not enough to properly validate email addresses. The only way to ensure an email address is valid is by sending a confirmation email.")])]),t._v(" "),e("h4",{attrs:{id:"size-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#size-value"}},[t._v("#")]),t._v(" size:value")]),t._v(" "),e("p",[t._v("Depending on its type, the field under validation must:")]),t._v(" "),e("ul",[e("li",[t._v("Strings: have a length of "),e("code",[t._v("value")]),t._v(" characters.")]),t._v(" "),e("li",[t._v("Numerics: be equal to "),e("code",[t._v("value")]),t._v(".")]),t._v(" "),e("li",[t._v("Arrays: exactly have "),e("code",[t._v("value")]),t._v(" items.")]),t._v(" "),e("li",[t._v("Files: weight exactly "),e("code",[t._v("value")]),t._v(" KiB.\n"),e("ul",[e("li",[e("em",[t._v("Note: for this rule only (not for "),e("code",[t._v("min")]),t._v(", "),e("code",[t._v("max")]),t._v(", etc), the size of the file under validation is "),e("strong",[t._v("rounded")]),t._v(" to the closest KiB.")])]),t._v(" "),e("li",[t._v("When the field is a multi-files upload, the size of "),e("strong",[t._v("all files")]),t._v(" is checked.")])])])]),t._v(" "),e("h4",{attrs:{id:"alpha"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#alpha"}},[t._v("#")]),t._v(" alpha")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be entirely alphabetic characters.")]),t._v(" "),e("h4",{attrs:{id:"alpha-dash"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#alpha-dash"}},[t._v("#")]),t._v(" alpha_dash")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be entirely alphabetic-numeric characters, dashes or underscores.")]),t._v(" "),e("h4",{attrs:{id:"alpha-num"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#alpha-num"}},[t._v("#")]),t._v(" alpha_num")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be entirely alphabetic-numeric characters.")]),t._v(" "),e("h4",{attrs:{id:"starts-with-value1"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#starts-with-value1"}},[t._v("#")]),t._v(" starts_with:value1,...")]),t._v(" "),e("p",[t._v("The field under validation must be a string and start with of the given values.")]),t._v(" "),e("h4",{attrs:{id:"ends-with-value1"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#ends-with-value1"}},[t._v("#")]),t._v(" ends_with:value1,...")]),t._v(" "),e("p",[t._v("The field under validation must be a string and end with one of the given values.")]),t._v(" "),e("h4",{attrs:{id:"in-value1-value2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#in-value1-value2"}},[t._v("#")]),t._v(" in:value1,value2,...")]),t._v(" "),e("p",[t._v("The field under validation must be a one of the given values. Only numerics and strings are checked.")]),t._v(" "),e("h4",{attrs:{id:"not-in-value1-value2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#not-in-value1-value2"}},[t._v("#")]),t._v(" not_in:value1,value2,...")]),t._v(" "),e("p",[t._v("The field under validation must not be a one of the given values. Only numerics and strings are checked.")]),t._v(" "),e("h4",{attrs:{id:"in-array-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#in-array-field"}},[t._v("#")]),t._v(" in_array:field")]),t._v(" "),e("p",[t._v("The field under validation must be a one of the values in the given "),e("code",[t._v("field")]),t._v(". Only numerics and strings are checked, and the given "),e("code",[t._v("field")]),t._v(" must be an array.")]),t._v(" "),e("h4",{attrs:{id:"not-in-array-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#not-in-array-field"}},[t._v("#")]),t._v(" not_in_array:field")]),t._v(" "),e("p",[t._v("The field under validation must not be a one of the values in the given "),e("code",[t._v("field")]),t._v(". Only numerics and strings are checked, and the given "),e("code",[t._v("field")]),t._v(" must be an array.")]),t._v(" "),e("h4",{attrs:{id:"timezone"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#timezone"}},[t._v("#")]),t._v(" timezone")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be a valid timezone. This rule converts the field to "),e("code",[t._v("*time.Location")]),t._v(" if it passes.")]),t._v(" "),e("p",[t._v("Valid timezones are:")]),t._v(" "),e("ul",[e("li",[t._v("UTC")]),t._v(" "),e("li",[t._v("Timezones from the IANA Time Zone database, such as "),e("code",[t._v("America/New_York")])])]),t._v(" "),e("p",[t._v("The time zone database needed by LoadLocation may not be present on all systems, especially non-Unix systems. The rules looks in the directory or uncompressed zip file\nnamed by the "),e("code",[t._v("ZONEINFO")]),t._v(" environment variable, if any, then looks in known installation locations on Unix systems, and finally looks in "),e("code",[t._v("$GOROOT/lib/time/zoneinfo.zip")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"ip"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#ip"}},[t._v("#")]),t._v(" ip")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be either an IPv4 address or an IPv6 address.\nThis rule converts the field to "),e("code",[t._v("net.IP")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"ipv4"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#ipv4"}},[t._v("#")]),t._v(" ipv4")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be an IPv4 address.\nThis rule converts the field to "),e("code",[t._v("net.IP")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"ipv6"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#ipv6"}},[t._v("#")]),t._v(" ipv6")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be an IPv6 address.\nThis rule converts the field to "),e("code",[t._v("net.IP")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"json"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#json"}},[t._v("#")]),t._v(" json")]),t._v(" "),e("p",[t._v("The field under validation must be a valid JSON string. This rule unmarshals the string and sets the field value to the unmarshalled result.")]),t._v(" "),e("h4",{attrs:{id:"url"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#url"}},[t._v("#")]),t._v(" url")]),t._v(" "),e("p",[t._v("The field under validation must be a valid URL.\nThis rule converts the field to "),e("code",[t._v("*url.URL")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"uuid-version"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#uuid-version"}},[t._v("#")]),t._v(" uuid:version")]),t._v(" "),e("p",[t._v("The field under validation must be a string and a valid UUID.")]),t._v(" "),e("p",[t._v("The "),e("code",[t._v("version")]),t._v(" parameter is "),e("strong",[t._v("optional")]),t._v(".")]),t._v(" "),e("ul",[e("li",[t._v("If a "),e("code",[t._v("version")]),t._v(" is given ("),e("code",[t._v("uuid:3")]),t._v(","),e("code",[t._v("uuid:4")]),t._v(","),e("code",[t._v("uuid:5")]),t._v("), the rule will pass only if the version of the UUID matches.")]),t._v(" "),e("li",[t._v("If no "),e("code",[t._v("version")]),t._v(" is given, any UUID version is accepted.")])]),t._v(" "),e("p",[t._v("This rule converts the field to "),e("code",[t._v("uuid.UUID")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"bool"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#bool"}},[t._v("#")]),t._v(" bool")]),t._v(" "),e("p",[t._v("The field under validation must be a boolean or one of the following values:")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("1")]),t._v("/"),e("code",[t._v("0")])]),t._v(" "),e("li",[e("code",[t._v('"1"')]),t._v("/"),e("code",[t._v('"0"')])]),t._v(" "),e("li",[e("code",[t._v('"on"')]),t._v("/"),e("code",[t._v('"off"')])]),t._v(" "),e("li",[e("code",[t._v('"true"')]),t._v("/"),e("code",[t._v('"false"')])]),t._v(" "),e("li",[e("code",[t._v('"yes"')]),t._v("/"),e("code",[t._v('"no"')])])]),t._v(" "),e("p",[t._v("This rule converts the field to "),e("code",[t._v("bool")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"same-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#same-field"}},[t._v("#")]),t._v(" same:field")]),t._v(" "),e("p",[t._v("The field under validation must have the same value as the given "),e("code",[t._v("field")]),t._v(". For arrays, the two fields must have the same values in the same order.")]),t._v(" "),e("p",[t._v("The two fields must have the same type. Files are not checked.")]),t._v(" "),e("h4",{attrs:{id:"different-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#different-field"}},[t._v("#")]),t._v(" different:field")]),t._v(" "),e("p",[t._v("The field under validation must have a different value from the given "),e("code",[t._v("field")]),t._v(". For arrays, the two fields must have different values or not be in the same order.")]),t._v(" "),e("p",[t._v("The two fields must have the same type. Files are not checked.")]),t._v(" "),e("h4",{attrs:{id:"confirmed"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#confirmed"}},[t._v("#")]),t._v(" confirmed")]),t._v(" "),e("p",[t._v("The field under validation must have a matching "),e("code",[t._v("foo_confirmation")]),t._v(". This rule validate equality in the same way as the "),e("a",{attrs:{href:"#same-field"}},[e("code",[t._v("same")])]),t._v(" rule.")]),t._v(" "),e("p",[t._v("For example, if the field under validation is "),e("code",[t._v("password")]),t._v(", a matching "),e("code",[t._v("password_confirmation")]),t._v(" field must be present in the input.")]),t._v(" "),e("h4",{attrs:{id:"file"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#file"}},[t._v("#")]),t._v(" file")]),t._v(" "),e("p",[t._v("The field under validation must be a file. Multi-files are supported.\nThis rule converts the field to "),e("code",[t._v("[]filesystem.File")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"mime-foo"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#mime-foo"}},[t._v("#")]),t._v(" mime:foo,...")]),t._v(" "),e("p",[t._v("The field under validation must be a file and match one of the given MIME types. If the field is a multi-files, all files must satisfy this rule.")]),t._v(" "),e("h4",{attrs:{id:"image"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#image"}},[t._v("#")]),t._v(" image")]),t._v(" "),e("p",[t._v("The field under validation must be a file and match one of the following MIME types:")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("image/jpeg")])]),t._v(" "),e("li",[e("code",[t._v("image/png")])]),t._v(" "),e("li",[e("code",[t._v("image/gif")])]),t._v(" "),e("li",[e("code",[t._v("image/bmp")])]),t._v(" "),e("li",[e("code",[t._v("image/svg+xml")])]),t._v(" "),e("li",[e("code",[t._v("image/webp")])])]),t._v(" "),e("p",[t._v("If the field is a multi-files, all files must satisfy this rule.")]),t._v(" "),e("h4",{attrs:{id:"extension-foo"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#extension-foo"}},[t._v("#")]),t._v(" extension:foo,...")]),t._v(" "),e("p",[t._v("The field under validation must be a file and match one of the given extensions. If the field is a multi-files, all files must satisfy this rule.")]),t._v(" "),e("h4",{attrs:{id:"count-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#count-value"}},[t._v("#")]),t._v(" count:value")]),t._v(" "),e("p",[t._v("The field under validation must be a multi-file and contain "),e("code",[t._v("value")]),t._v(" files.")]),t._v(" "),e("h4",{attrs:{id:"count-min-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#count-min-value"}},[t._v("#")]),t._v(" count_min:value")]),t._v(" "),e("p",[t._v("The field under validation must be a multi-file and contain at least "),e("code",[t._v("value")]),t._v(" files.")]),t._v(" "),e("h4",{attrs:{id:"count-max-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#count-max-value"}},[t._v("#")]),t._v(" count_max:value")]),t._v(" "),e("p",[t._v("The field under validation must be a multi-file and may not contain more than "),e("code",[t._v("value")]),t._v(" files.")]),t._v(" "),e("h4",{attrs:{id:"count-between-min-max"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#count-between-min-max"}},[t._v("#")]),t._v(" count_between:min,max")]),t._v(" "),e("p",[t._v("The field under validation must be a multi-file and contain between "),e("code",[t._v("min")]),t._v(" and "),e("code",[t._v("max")]),t._v(" files.")]),t._v(" "),e("h4",{attrs:{id:"date-format"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#date-format"}},[t._v("#")]),t._v(" date:format")]),t._v(" "),e("p",[t._v("The field under validation must be a string representing a date. The "),e("code",[t._v("format")]),t._v(" is optional. If no format is given, the "),e("code",[t._v("2006-01-02")]),t._v(" format is used.")]),t._v(" "),e("p",[t._v("This rule converts the field to "),e("code",[t._v("time.Time")]),t._v(" if it passes.")]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("See the "),e("a",{attrs:{href:"https://golang.org/src/time/format.go",target:"_blank",rel:"noopener noreferrer"}},[t._v("Golang datetime format"),e("OutboundLink")],1),t._v(".")])]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),e("p",[t._v("When validating dates by comparing them together, the order of the declaration of the fields in the request is important. For example, if you want to validate that an end date is after a start date, the start date should be decalred "),e("strong",[t._v("before")]),t._v(" the end date in the rules set.")]),t._v(" "),e("p",[t._v("If a date has not been validated and converted yet, the date comparison rules will attempt to parse the dates using the following format: "),e("code",[t._v("2006-01-02")]),t._v(".")])]),t._v(" "),e("h4",{attrs:{id:"before-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#before-date"}},[t._v("#")]),t._v(" before:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value preceding the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be preceding the given field.")]),t._v(" "),e("h4",{attrs:{id:"before-equal-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#before-equal-date"}},[t._v("#")]),t._v(" before_equal:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value preceding or equal to the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be preceding or equal to given field.")]),t._v(" "),e("h4",{attrs:{id:"after-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#after-date"}},[t._v("#")]),t._v(" after:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value after the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be preceding the given field.")]),t._v(" "),e("h4",{attrs:{id:"after-equal-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#after-equal-date"}},[t._v("#")]),t._v(" after_equal:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value after or equal to the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be after or equal to given field.")]),t._v(" "),e("h4",{attrs:{id:"date-equals-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#date-equals-date"}},[t._v("#")]),t._v(" date_equals:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value equal to the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be equal to given field.")]),t._v(" "),e("h4",{attrs:{id:"date-between-date1-date2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#date-between-date1-date2"}},[t._v("#")]),t._v(" date_between:date1,date2")]),t._v(" "),e("p",[t._v("The field under validation must be a value between or equal to the given dates. The given dates must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a date, then all the fields must be a date and the field under validation must be between or equal to given fields.")]),t._v(" "),e("h2",{attrs:{id:"custom-rules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#custom-rules"}},[t._v("#")]),t._v(" Custom rules")]),t._v(" "),e("p",[t._v("If none of the available validation rules satisfy your needs, you can implement custom validation rules. To do so, create a new file "),e("code",[t._v("http/requests/validation.go")]),t._v(" in which you are going to define your custom rules.")]),t._v(" "),e("p",[t._v("Rules definition shouldn't be exported, and start with "),e("code",[t._v("validate")]),t._v(". A rule returns a "),e("code",[t._v("bool")]),t._v(", indicating if the validation passed or not.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("validateCustomFormat")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" value "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" form "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Ensure the rule has at least one parameter")]),t._v("\n validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("RequireParametersCount")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"custom_format"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n str"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" value"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" ok "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The data under validation is a string")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" regexp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("MustCompile")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("MatchString")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("str"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Cannot validate this field")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("validation.Rule")]),t._v(" is an alias for "),e("code",[t._v("func(string, interface{}, []string, map[string]interface{}) bool")])]),t._v(" "),e("li",[t._v("The "),e("code",[t._v("form")]),t._v(" parameter lets you access the whole form data, and modify it if needed.")]),t._v(" "),e("li",[t._v("The custom rule in the example above validates a string using a regex. If you need this kind of validation, prefer the included "),e("code",[t._v("regex")]),t._v(" validation rule.")])])]),t._v(" "),e("p",[t._v("Now that your rule behavior is defined, you need to "),e("strong",[t._v("register")]),t._v(" your rule. Do this in an "),e("code",[t._v("init()")]),t._v(" function in your "),e("code",[t._v("validation.go")]),t._v(" file.")]),t._v(" "),e("h4",{attrs:{id:"validation-addrule"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-addrule"}},[t._v("#")]),t._v(" validation.AddRule")]),t._v(" "),e("p",[t._v("Register a validation rule.")]),t._v(" "),e("p",[t._v("The rule will be usable in request validation by using the given rule name.")]),t._v(" "),e("p",[t._v('Type-dependent messages let you define a different message for numeric, string, arrays and files. The language entry used will be "validation.rules.rulename.type"')]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("name string")])]),t._v(" "),e("td",[e("code",[t._v("void")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("typeDependentMessage bool")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("rule validation.Rule")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddRule")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"custom_format"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" validateCustomFormat"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h4",{attrs:{id:"validation-requireparameterscount"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-requireparameterscount"}},[t._v("#")]),t._v(" validation.RequireParametersCount")]),t._v(" "),e("p",[t._v("Checks if the given parameters slice has at least "),e("code",[t._v("count")]),t._v(" elements. If this criteria is not met, the function triggers a panic.")]),t._v(" "),e("p",[t._v("Use this to make sure your validation rules are correctly used.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("rule string")])]),t._v(" "),e("td",[e("code",[t._v("void")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("params []string")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("count int")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("RequireParametersCount")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"custom_format"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"validation-getfieldtype"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-getfieldtype"}},[t._v("#")]),t._v(" validation.GetFieldType")]),t._v(" "),e("p",[e("Badge",{attrs:{text:"Since v2.0.0"}})],1),t._v(" "),e("p",[t._v("returns the non-technical type of the given "),e("code",[t._v("value")]),t._v(" interface.\nThis is used by validation rules to know if the input data is a candidate\nfor validation or not and is especially useful for type-dependent rules.")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("numeric")]),t._v(" if the value is an int, uint or a float")]),t._v(" "),e("li",[e("code",[t._v("string")]),t._v(" if the value is a string")]),t._v(" "),e("li",[e("code",[t._v("array")]),t._v(" if the value is a slice")]),t._v(" "),e("li",[e("code",[t._v("file")]),t._v(" if the value is a slice of "),e("code",[t._v("filesystem.File")])]),t._v(" "),e("li",[e("code",[t._v("unsupported")]),t._v(" otherwise")])]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("value interface{}")])]),t._v(" "),e("td",[e("code",[t._v("string")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetFieldType")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"foo"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "string"')]),t._v("\nvalidation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetFieldType")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "numeric"')]),t._v("\nvalidation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetFieldType")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2.4")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "numeric"')]),t._v("\nvalidation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetFieldType")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "array"')]),t._v("\n")])])]),e("h2",{attrs:{id:"validating-arrays"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validating-arrays"}},[t._v("#")]),t._v(" Validating arrays")]),t._v(" "),e("p",[e("Badge",{attrs:{text:"Since v2.1.0"}}),e("Badge",{attrs:{text:"BETA",type:"warn"}})],1),t._v(" "),e("p",[t._v("Validating arrays is easy. All the validation rules, "),e("strong",[t._v("except the file-related rules and the "),e("code",[t._v("confirmed")]),t._v(" rule")]),t._v(", can be applied to array values using the prefix "),e("code",[t._v(">")]),t._v(". When array values are validated, "),e("strong",[t._v("all of them")]),t._v(" must pass the validation.")]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" arrayValidation "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"array"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"array:string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"between:1,5"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">email"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">max:128"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("In this example, we are validating an array of one to five email addresses, which can't be longer than 128 characters.")]),t._v(" "),e("h3",{attrs:{id:"n-dimensional-arrays"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#n-dimensional-arrays"}},[t._v("#")]),t._v(" N-dimensional arrays")]),t._v(" "),e("p",[t._v("You can validate n-dimensional arrays.")]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" arrayValidation "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" RuleSet"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"array"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"array"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">array"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">>array:numeric"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">max:3"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">>>max:4"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("In this example, we are validating a three-dimensional array of numeric values. The second dimension must be made of arrays with a size of 3 or less. The third dimensions must contain numbers inferior to 4. The following JSON input passes the validation:")]),t._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[t._v('"array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.5")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.42")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.6")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.6")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.43")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h2",{attrs:{id:"placeholders"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#placeholders"}},[t._v("#")]),t._v(" Placeholders")]),t._v(" "),e("p",[t._v("Validation messages can use placeholders to inject dynamic values in the validation error message. For example, in the "),e("code",[t._v("rules.json")]),t._v(" language file:")]),t._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token property"}},[t._v('"between.string"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"The :field must be between :min and :max characters."')]),t._v("\n")])])]),e("p",[t._v("Here, the "),e("code",[t._v(":field")]),t._v(" placeholder will be replaced by the field name, "),e("code",[t._v(":min")]),t._v(" with the first parameter and "),e("code",[t._v(":max")]),t._v(" with the second parameter, effectively giving the following result:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("The password must be between 6 and 32 characters. \n")])])]),e("p",[t._v("Placeholders are "),e("strong",[t._v("replacer functions")]),t._v(". In fact, "),e("code",[t._v("validation.Placeholder")]),t._v(" is an alias for "),e("code",[t._v("func(string, string, []string, string) string")]),t._v(". These functions should return the value to replace the placeholder with.")]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("simpleParameterPlaceholder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rule "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" language "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("hr"),t._v(" "),e("p",[t._v("Placeholders are implemented in the "),e("code",[t._v("http/requests/placeholders.go")]),t._v(". To register a custom placeholder, use the "),e("code",[t._v("validation.SetPlaceholder()")]),t._v(" function, preferably in the "),e("code",[t._v("init()")]),t._v(" function of your "),e("code",[t._v("placeholders.go")]),t._v(" file.")]),t._v(" "),e("h4",{attrs:{id:"validation-setplaceholder"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-setplaceholder"}},[t._v("#")]),t._v(" validation.SetPlaceholder")]),t._v(" "),e("p",[t._v("Sets the replacer function for the given placeholder. Don't include the colon prefix in the placeholder name.")]),t._v(" "),e("p",[t._v("If a placeholder with this name already exists, the latter will be overridden.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("placeholderName string")])]),t._v(" "),e("td",[e("code",[t._v("void")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("replacer validation.Placeholder")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetPlaceholder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"min"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rule "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" language "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Replace ":min" by the first parameter in the rule definition')]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h3",{attrs:{id:"available-placeholders"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#available-placeholders"}},[t._v("#")]),t._v(" Available placeholders")]),t._v(" "),e("h4",{attrs:{id:"field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#field"}},[t._v("#")]),t._v(" :field")]),t._v(" "),e("p",[e("code",[t._v(":field")]),t._v(" is replaced by the name of the field. If it exists, the replacer with favor the language lines in "),e("code",[t._v("fields.json")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"other"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#other"}},[t._v("#")]),t._v(" :other")]),t._v(" "),e("p",[e("code",[t._v(":other")]),t._v(" is replaced by the name of the field given as first parameter in the rule definition. If it exists, the replacer with favor the language lines in "),e("code",[t._v("fields.json")]),t._v(".")]),t._v(" "),e("p",[t._v("For example, the "),e("code",[t._v("same:password_confirmation")]),t._v(" rule compares two fields together and returns the following message if the validation fails:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("The :field and the :other must match.\n\nThe password and the password confirmation must match.\n")])])]),e("h4",{attrs:{id:"value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#value"}},[t._v("#")]),t._v(" :value")]),t._v(" "),e("p",[e("code",[t._v(":value")]),t._v(" is replaced by the first parameter of the rule definition.")]),t._v(" "),e("h4",{attrs:{id:"values"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#values"}},[t._v("#")]),t._v(" :values")]),t._v(" "),e("p",[e("code",[t._v(":values")]),t._v(" is replaced by a concatenation of all rule parameters, joined by a comma.")]),t._v(" "),e("h4",{attrs:{id:"min"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#min"}},[t._v("#")]),t._v(" :min")]),t._v(" "),e("p",[e("code",[t._v(":min")]),t._v(" is replaced by the first parameter of the rule definition.")]),t._v(" "),e("h4",{attrs:{id:"max"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#max"}},[t._v("#")]),t._v(" :max")]),t._v(" "),e("p",[e("code",[t._v(":max")]),t._v(" is replaced by the first parameter of the rule definition, or the second if the rule name contains "),e("code",[t._v("between")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"version"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#version"}},[t._v("#")]),t._v(" :version")]),t._v(" "),e("p",[e("code",[t._v(":version")]),t._v(" is replaced by a concatenation of "),e("code",[t._v("v")]),t._v(" and the first parameter of the rule definition, or by an empty string if the rule doesn't have any parameter.")]),t._v(" "),e("p",[t._v("For example, for the "),e("code",[t._v("UUID:4")]),t._v(" rule, the result would be "),e("code",[t._v("v4")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#date"}},[t._v("#")]),t._v(" :date")]),t._v(" "),e("p",[e("code",[t._v(":date")]),t._v(" is replaced by the first parameter of the rule definition. If the first parameter is a field name, "),e("code",[t._v(":date")]),t._v(" will be replaced with the name of the field in the same way as the "),e("code",[t._v(":other")]),t._v(" placeholder.")]),t._v(" "),e("h4",{attrs:{id:"max-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#max-date"}},[t._v("#")]),t._v(" :max_date")]),t._v(" "),e("p",[e("code",[t._v(":max_date")]),t._v(" is replaced by the second parameter of the rule definition. If the second parameter is a field name, "),e("code",[t._v(":max_date")]),t._v(" will be replaced with the name of the field in the same way as the "),e("code",[t._v(":other")]),t._v(" placeholder.")]),t._v(" "),e("h2",{attrs:{id:"manual-validation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#manual-validation"}},[t._v("#")]),t._v(" Manual validation")]),t._v(" "),e("p",[e("Badge",{attrs:{text:"Since v2.1.0"}})],1),t._v(" "),e("p",[t._v("You may need to validate some data manually as part of your business logic. You can use the Goyave validator to do so.")]),t._v(" "),e("h4",{attrs:{id:"validation-validate"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-validate"}},[t._v("#")]),t._v(" validation.Validate")]),t._v(" "),e("p",[t._v("Validate the given data with the given rule set. If all validation rules pass, returns an empty "),e("code",[t._v("validation.Errors")]),t._v(".")]),t._v(" "),e("p",[t._v("The third parameter ("),e("code",[t._v("isJSON")]),t._v(") tells the function if the data comes from a JSON request. This is used to return the correct message if the given data is "),e("code",[t._v("nil")]),t._v(" and to correctly handle arrays in url-encoded requests.")]),t._v(" "),e("p",[t._v("The last parameter ("),e("code",[t._v("language")]),t._v(") sets the language of the validation error messages.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("data map[string]interface{}")])]),t._v(" "),e("td",[e("code",[t._v("validation.Errors")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("rules RuleSet")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("isJSON bool")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("language string")])]),t._v(" "),e("td")])])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[e("code",[t._v("validation.Errors")]),t._v(" is an alias for "),e("code",[t._v("map[string][]string")]),t._v(". The key represents the field name and the associated slice contains all already translated validation error messages for this field.")])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Store")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n data "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello world"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"number"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("42")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\terrors "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Validate")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("data"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"number"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"numeric"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"min:10"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("errors"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tresponse"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("JSON")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusUnprocessableEntity"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Errors"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"validationError"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" errors"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// data can be safely used from here")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[21],{232:function(t,a,e){"use strict";e.r(a);var s=e(0),n=Object(s.a)({},(function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"validation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation"}},[t._v("#")]),t._v(" Validation")]),t._v(" "),e("p"),e("div",{staticClass:"table-of-contents"},[e("ul",[e("li",[e("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),e("li",[e("a",{attrs:{href:"#rules-sets"}},[t._v("Rules sets")])]),e("li",[e("a",{attrs:{href:"#available-validation-rules"}},[t._v("Available validation rules")])]),e("li",[e("a",{attrs:{href:"#custom-rules"}},[t._v("Custom rules")])]),e("li",[e("a",{attrs:{href:"#validating-arrays"}},[t._v("Validating arrays")]),e("ul",[e("li",[e("a",{attrs:{href:"#n-dimensional-arrays"}},[t._v("N-dimensional arrays")])])])]),e("li",[e("a",{attrs:{href:"#placeholders"}},[t._v("Placeholders")]),e("ul",[e("li",[e("a",{attrs:{href:"#available-placeholders"}},[t._v("Available placeholders")])])])]),e("li",[e("a",{attrs:{href:"#manual-validation"}},[t._v("Manual validation")])])])]),e("p"),t._v(" "),e("h2",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),e("p",[t._v("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.")]),t._v(" "),e("p",[t._v("Incoming requests are validated using "),e("strong",[t._v("rules set")]),t._v(", which associate rules with each expected field in the request.")]),t._v(" "),e("p",[t._v("Validation rules can "),e("strong",[t._v("alter the raw data")]),t._v(". 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 "),e("code",[t._v("float64")]),t._v(". Or if you're validating an IP, you get a "),e("code",[t._v("net.IP")]),t._v(" object.")]),t._v(" "),e("p",[t._v("If a request contains a field with a "),e("code",[t._v("nil")]),t._v("/"),e("code",[t._v("null")]),t._v(" value, and that this field doesn't have the "),e("code",[t._v("nullable")]),t._v(" rule, the field is "),e("strong",[t._v("removed")]),t._v(" entirely from the request.")]),t._v(" "),e("p",[t._v("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, using the correct "),e("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[t._v("language")]),t._v(". The HTTP response code of failed validation is "),e("strong",[t._v('422 "Unprocessable Entity"')]),t._v(", or "),e("strong",[t._v('400 "Bad Request"')]),t._v(" if the body could not be parsed.")],1),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("You can customize the validation error messages by editing "),e("code",[t._v("resources/lang//rules.json")]),t._v(". Learn more in the "),e("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[t._v("localization")]),t._v(" section.")],1)]),t._v(" "),e("p",[t._v("The following features require the "),e("code",[t._v("validation")]),t._v(" package to be imported.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/validation"')]),t._v("\n")])])]),e("h2",{attrs:{id:"rules-sets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rules-sets"}},[t._v("#")]),t._v(" Rules sets")]),t._v(" "),e("p",[t._v("The "),e("code",[t._v("http/request")]),t._v(" directory contains the requests validation rules sets. You should have one package per feature, regrouping all requests handled by the same controller. The package should be named "),e("code",[t._v("request")]),t._v(".")]),t._v(" "),e("p",[e("strong",[t._v("Example:")]),t._v(" ("),e("code",[t._v("http/request/productrequest/product.go")]),t._v(")")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tStore validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"between:3,50"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"price"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"numeric"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"min:0.01"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nullable"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"file"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"max:2048"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"count:1"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),e("p",[e("strong",[t._v("The order in which you assign rules is important")]),t._v(", as rules are executed in this order. The rules checking for the type of the data should "),e("strong",[t._v("always be first")]),t._v(", or after "),e("code",[t._v("required")]),t._v(" and "),e("code",[t._v("nullable")]),t._v(".")]),t._v(" "),e("p",[t._v("If a field is not "),e("strong",[t._v("required")]),t._v(" and is missing from the request, "),e("strong",[t._v("no rules are checked")]),t._v("!")])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[e("code",[t._v("validation.RuleSet")]),t._v(" is an alias for "),e("code",[t._v("map[string][]string")])])]),t._v(" "),e("hr"),t._v(" "),e("p",[t._v("Once your rules sets are defined, you need to assign them to your routes. The rule set for a route is the last parameter of the route definition. Learn more about routing in the "),e("router-link",{attrs:{to:"/guide/basics/routing.html"}},[t._v("dedicated section")]),t._v(".")],1),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("router"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"POST"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/product"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" product"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Store"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" productrequest"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Store"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h2",{attrs:{id:"available-validation-rules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#available-validation-rules"}},[t._v("#")]),t._v(" Available validation rules")]),t._v(" "),e("div",{staticClass:"table"},[e("p",[e("a",{attrs:{href:"#required"}},[t._v("Required")]),t._v(" "),e("a",{attrs:{href:"#nullable"}},[t._v("Nullable")]),t._v(" "),e("a",{attrs:{href:"#numeric"}},[t._v("Numeric")]),t._v(" "),e("a",{attrs:{href:"#integer"}},[t._v("Integer")]),t._v(" "),e("a",{attrs:{href:"#min-value"}},[t._v("Min")]),t._v(" "),e("a",{attrs:{href:"#max-value"}},[t._v("Max")]),t._v(" "),e("a",{attrs:{href:"#between-min-max"}},[t._v("Between")]),t._v(" "),e("a",{attrs:{href:"#greater-than-field"}},[t._v("Greater than")]),t._v(" "),e("a",{attrs:{href:"#greater-than-equal-field"}},[t._v("Greater than or equal")]),t._v(" "),e("a",{attrs:{href:"#lower-than-field"}},[t._v("Lower than")]),t._v(" "),e("a",{attrs:{href:"#lower-than-equal-field"}},[t._v("Lower than or equal")]),t._v(" "),e("a",{attrs:{href:"#string"}},[t._v("String")]),t._v(" "),e("a",{attrs:{href:"#array-type"}},[t._v("Array")]),t._v(" "),e("a",{attrs:{href:"#distinct"}},[t._v("Distinct")]),t._v(" "),e("a",{attrs:{href:"#digits"}},[t._v("Digits")]),t._v(" "),e("a",{attrs:{href:"#regex-pattern"}},[t._v("Regex")]),t._v(" "),e("a",{attrs:{href:"#email"}},[t._v("Email")]),t._v(" "),e("a",{attrs:{href:"#size-value"}},[t._v("Size")]),t._v(" "),e("a",{attrs:{href:"#alpha"}},[t._v("Alpha")]),t._v(" "),e("a",{attrs:{href:"#alpha-dash"}},[t._v("Alpha dash")]),t._v(" "),e("a",{attrs:{href:"#alpha-num"}},[t._v("Alpha numeric")]),t._v(" "),e("a",{attrs:{href:"#starts-with-value1"}},[t._v("Starts with")]),t._v(" "),e("a",{attrs:{href:"#ends-with-value1"}},[t._v("Ends with")]),t._v(" "),e("a",{attrs:{href:"#in-value1-value2"}},[t._v("In")]),t._v(" "),e("a",{attrs:{href:"#not-in-value1-value2"}},[t._v("Not in")]),t._v(" "),e("a",{attrs:{href:"#in-array-field"}},[t._v("In array")]),t._v(" "),e("a",{attrs:{href:"#not-in-array-field"}},[t._v("Not in array")]),t._v(" "),e("a",{attrs:{href:"#timezone"}},[t._v("Timezone")]),t._v(" "),e("a",{attrs:{href:"#ip"}},[t._v("IP")]),t._v(" "),e("a",{attrs:{href:"#ipv4"}},[t._v("IPv4")]),t._v(" "),e("a",{attrs:{href:"#ipv6"}},[t._v("IPv6")]),t._v(" "),e("a",{attrs:{href:"#json"}},[t._v("JSON")]),t._v(" "),e("a",{attrs:{href:"#url"}},[t._v("URL")]),t._v(" "),e("a",{attrs:{href:"#uuid-version"}},[t._v("UUID")]),t._v(" "),e("a",{attrs:{href:"#bool"}},[t._v("Bool")]),t._v(" "),e("a",{attrs:{href:"#same-field"}},[t._v("Same")]),t._v(" "),e("a",{attrs:{href:"#different-field"}},[t._v("Different")]),t._v(" "),e("a",{attrs:{href:"#confirmed"}},[t._v("Confirmed")]),t._v(" "),e("a",{attrs:{href:"#file"}},[t._v("File")]),t._v(" "),e("a",{attrs:{href:"#mime-foo"}},[t._v("MIME")]),t._v(" "),e("a",{attrs:{href:"#image"}},[t._v("Image")]),t._v(" "),e("a",{attrs:{href:"#extension-foo"}},[t._v("Extension")]),t._v(" "),e("a",{attrs:{href:"#count-value"}},[t._v("Count")]),t._v(" "),e("a",{attrs:{href:"#count-min-value"}},[t._v("Count min")]),t._v(" "),e("a",{attrs:{href:"#count-max-value"}},[t._v("Count max")]),t._v(" "),e("a",{attrs:{href:"#count-between-min-max"}},[t._v("Count between")]),t._v(" "),e("a",{attrs:{href:"#date-format"}},[t._v("Date")]),t._v(" "),e("a",{attrs:{href:"#before-date"}},[t._v("Before")]),t._v(" "),e("a",{attrs:{href:"#before-equal-date"}},[t._v("Before or equal")]),t._v(" "),e("a",{attrs:{href:"#after-date"}},[t._v("After")]),t._v(" "),e("a",{attrs:{href:"#after-equal-date"}},[t._v("After or equal")]),t._v(" "),e("a",{attrs:{href:"#date-equals-date"}},[t._v("Date equals")]),t._v(" "),e("a",{attrs:{href:"#date-between-date1-date2"}},[t._v("Date between")])])]),e("h4",{attrs:{id:"required"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#required"}},[t._v("#")]),t._v(" required")]),t._v(" "),e("p",[t._v("The field under validation must be present.")]),t._v(" "),e("p",[t._v("If the field is a string, the string must not be empty. If a field is "),e("code",[t._v("null")]),t._v(" and has the "),e("code",[t._v("nullable")]),t._v(" rule, the "),e("code",[t._v("required")]),t._v(" rules passes. As non-nullable fields are removed if they have a "),e("code",[t._v("null")]),t._v(" value, the "),e("code",[t._v("required")]),t._v(" rule doesn't pass if a field is "),e("code",[t._v("null")]),t._v(" and doesn't have the "),e("code",[t._v("nullable")]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"nullable"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#nullable"}},[t._v("#")]),t._v(" nullable")]),t._v(" "),e("p",[t._v("The field under validation can have a "),e("code",[t._v("nil")]),t._v("/"),e("code",[t._v("null")]),t._v(" value. If this rule is missing from the rules set, the field will be "),e("strong",[t._v("removed")]),t._v(" if it is "),e("code",[t._v("null")]),t._v(". This rule is especially useful when working with JSON requests or with primitives that can contain null values.")]),t._v(" "),e("p",[t._v("Be sure to check if your field is not null before using it in your handlers.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// In this example, field is numeric")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" val"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" exists "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" exists "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" val "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n field"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Data"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"field"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h4",{attrs:{id:"numeric"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#numeric"}},[t._v("#")]),t._v(" numeric")]),t._v(" "),e("p",[t._v("The field under validation must be numeric. Strings that can be converted to numbers are accepted.\nThis rule converts the field to "),e("code",[t._v("float64")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"integer"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#integer"}},[t._v("#")]),t._v(" integer")]),t._v(" "),e("p",[t._v("The field under validation must be an integer. Strings that can be converted to an integer are accepted.\nThis rule converts the field to "),e("code",[t._v("int")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"min-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#min-value"}},[t._v("#")]),t._v(" min:value")]),t._v(" "),e("p",[t._v("Depending on its type, the field under validation must be at least "),e("code",[t._v("min")]),t._v(".\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"max-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#max-value"}},[t._v("#")]),t._v(" max:value")]),t._v(" "),e("p",[t._v("Depending on its type, the field under validation must not be superior to "),e("code",[t._v("value")]),t._v(".\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"between-min-max"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#between-min-max"}},[t._v("#")]),t._v(" between:min,max")]),t._v(" "),e("p",[t._v("Depending on its type, the field under validation must be between "),e("code",[t._v("min")]),t._v(" and "),e("code",[t._v("max")]),t._v(".\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"greater-than-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#greater-than-field"}},[t._v("#")]),t._v(" greater_than:field")]),t._v(" "),e("p",[t._v("The field under validation must be greater than the given "),e("code",[t._v("field")]),t._v(". The two fields must have the same type.\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"greater-than-equal-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#greater-than-equal-field"}},[t._v("#")]),t._v(" greater_than_equal:field")]),t._v(" "),e("p",[t._v("The field under validation must be greater or equal to the given "),e("code",[t._v("field")]),t._v(". The two fields must have the same type.\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"lower-than-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lower-than-field"}},[t._v("#")]),t._v(" lower_than:field")]),t._v(" "),e("p",[t._v("The field under validation must be lower than the given "),e("code",[t._v("field")]),t._v(". The two fields must have the same type.\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"lower-than-equal-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#lower-than-equal-field"}},[t._v("#")]),t._v(" lower_than_equal:field")]),t._v(" "),e("p",[t._v("The field under validation must be lower or equal to the given "),e("code",[t._v("field")]),t._v(". The two fields must have the same type.\nStrings, numerics, array, and files are evaluated using the same method as the "),e("a",{attrs:{href:"#size-value"}},[e("code",[t._v("size")])]),t._v(" rule.")]),t._v(" "),e("h4",{attrs:{id:"string"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#string"}},[t._v("#")]),t._v(" string")]),t._v(" "),e("p",[t._v("The field under validation must be a string.")]),t._v(" "),e("h4",{attrs:{id:"array-type"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#array-type"}},[t._v("#")]),t._v(" array:type")]),t._v(" "),e("p",[t._v("The field under validation must be an array. The "),e("code",[t._v("type")]),t._v(" parameter is "),e("strong",[t._v("optional")]),t._v(".")]),t._v(" "),e("p",[t._v("If no type is provided, the field has the type "),e("code",[t._v("[]interface{}")]),t._v(" after validation. If a type is provided, the array is converted to a slice of the correct type, and all values in the array are validated in the same way as standard fields.")]),t._v(" "),e("p",[t._v("For example, with the rule "),e("code",[t._v("array:url")]),t._v(", all values must be valid URLs and the field will be converted to "),e("code",[t._v("[]*url.URL")]),t._v(".")]),t._v(" "),e("p",[e("strong",[t._v("Available types:")])]),t._v(" "),e("ul",[e("li",[e("code",[t._v("string")])]),t._v(" "),e("li",[e("code",[t._v("numeric")])]),t._v(" "),e("li",[e("code",[t._v("integer")])]),t._v(" "),e("li",[e("code",[t._v("timezone")])]),t._v(" "),e("li",[e("code",[t._v("ip")]),t._v(", "),e("code",[t._v("ipv4")]),t._v(", "),e("code",[t._v("ipv6")])]),t._v(" "),e("li",[e("code",[t._v("url")])]),t._v(" "),e("li",[e("code",[t._v("uuid")])]),t._v(" "),e("li",[e("code",[t._v("bool")])]),t._v(" "),e("li",[e("code",[t._v("date")])])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("For the "),e("code",[t._v("uuid")]),t._v(" and "),e("code",[t._v("date")]),t._v(" types, you can pass a second parameter: "),e("code",[t._v("array:date,02-01-2006")])])]),t._v(" "),e("h4",{attrs:{id:"distinct"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#distinct"}},[t._v("#")]),t._v(" distinct")]),t._v(" "),e("p",[t._v("The field under validation must be an array and have distinct values.")]),t._v(" "),e("h4",{attrs:{id:"digits"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#digits"}},[t._v("#")]),t._v(" digits")]),t._v(" "),e("p",[t._v("The field under validation must be a string and contain only digits.")]),t._v(" "),e("h4",{attrs:{id:"regex-pattern"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#regex-pattern"}},[t._v("#")]),t._v(" regex:pattern")]),t._v(" "),e("p",[t._v("The field under validation must be a string and match the given "),e("code",[t._v("pattern")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"email"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#email"}},[t._v("#")]),t._v(" email")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be an email address.")]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),e("p",[t._v("This rule is not enough to properly validate email addresses. The only way to ensure an email address is valid is by sending a confirmation email.")])]),t._v(" "),e("h4",{attrs:{id:"size-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#size-value"}},[t._v("#")]),t._v(" size:value")]),t._v(" "),e("p",[t._v("Depending on its type, the field under validation must:")]),t._v(" "),e("ul",[e("li",[t._v("Strings: have a length of "),e("code",[t._v("value")]),t._v(" characters.")]),t._v(" "),e("li",[t._v("Numerics: be equal to "),e("code",[t._v("value")]),t._v(".")]),t._v(" "),e("li",[t._v("Arrays: exactly have "),e("code",[t._v("value")]),t._v(" items.")]),t._v(" "),e("li",[t._v("Files: weight exactly "),e("code",[t._v("value")]),t._v(" KiB.\n"),e("ul",[e("li",[e("em",[t._v("Note: for this rule only (not for "),e("code",[t._v("min")]),t._v(", "),e("code",[t._v("max")]),t._v(", etc), the size of the file under validation is "),e("strong",[t._v("rounded")]),t._v(" to the closest KiB.")])]),t._v(" "),e("li",[t._v("When the field is a multi-files upload, the size of "),e("strong",[t._v("all files")]),t._v(" is checked.")])])])]),t._v(" "),e("h4",{attrs:{id:"alpha"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#alpha"}},[t._v("#")]),t._v(" alpha")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be entirely alphabetic characters.")]),t._v(" "),e("h4",{attrs:{id:"alpha-dash"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#alpha-dash"}},[t._v("#")]),t._v(" alpha_dash")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be entirely alphabetic-numeric characters, dashes or underscores.")]),t._v(" "),e("h4",{attrs:{id:"alpha-num"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#alpha-num"}},[t._v("#")]),t._v(" alpha_num")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be entirely alphabetic-numeric characters.")]),t._v(" "),e("h4",{attrs:{id:"starts-with-value1"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#starts-with-value1"}},[t._v("#")]),t._v(" starts_with:value1,...")]),t._v(" "),e("p",[t._v("The field under validation must be a string and start with of the given values.")]),t._v(" "),e("h4",{attrs:{id:"ends-with-value1"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#ends-with-value1"}},[t._v("#")]),t._v(" ends_with:value1,...")]),t._v(" "),e("p",[t._v("The field under validation must be a string and end with one of the given values.")]),t._v(" "),e("h4",{attrs:{id:"in-value1-value2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#in-value1-value2"}},[t._v("#")]),t._v(" in:value1,value2,...")]),t._v(" "),e("p",[t._v("The field under validation must be a one of the given values. Only numerics and strings are checked.")]),t._v(" "),e("h4",{attrs:{id:"not-in-value1-value2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#not-in-value1-value2"}},[t._v("#")]),t._v(" not_in:value1,value2,...")]),t._v(" "),e("p",[t._v("The field under validation must not be a one of the given values. Only numerics and strings are checked.")]),t._v(" "),e("h4",{attrs:{id:"in-array-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#in-array-field"}},[t._v("#")]),t._v(" in_array:field")]),t._v(" "),e("p",[t._v("The field under validation must be a one of the values in the given "),e("code",[t._v("field")]),t._v(". Only numerics and strings are checked, and the given "),e("code",[t._v("field")]),t._v(" must be an array.")]),t._v(" "),e("h4",{attrs:{id:"not-in-array-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#not-in-array-field"}},[t._v("#")]),t._v(" not_in_array:field")]),t._v(" "),e("p",[t._v("The field under validation must not be a one of the values in the given "),e("code",[t._v("field")]),t._v(". Only numerics and strings are checked, and the given "),e("code",[t._v("field")]),t._v(" must be an array.")]),t._v(" "),e("h4",{attrs:{id:"timezone"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#timezone"}},[t._v("#")]),t._v(" timezone")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be a valid timezone. This rule converts the field to "),e("code",[t._v("*time.Location")]),t._v(" if it passes.")]),t._v(" "),e("p",[t._v("Valid timezones are:")]),t._v(" "),e("ul",[e("li",[t._v("UTC")]),t._v(" "),e("li",[t._v("Timezones from the IANA Time Zone database, such as "),e("code",[t._v("America/New_York")])])]),t._v(" "),e("p",[t._v("The time zone database needed by LoadLocation may not be present on all systems, especially non-Unix systems. The rules looks in the directory or uncompressed zip file\nnamed by the "),e("code",[t._v("ZONEINFO")]),t._v(" environment variable, if any, then looks in known installation locations on Unix systems, and finally looks in "),e("code",[t._v("$GOROOT/lib/time/zoneinfo.zip")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"ip"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#ip"}},[t._v("#")]),t._v(" ip")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be either an IPv4 address or an IPv6 address.\nThis rule converts the field to "),e("code",[t._v("net.IP")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"ipv4"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#ipv4"}},[t._v("#")]),t._v(" ipv4")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be an IPv4 address.\nThis rule converts the field to "),e("code",[t._v("net.IP")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"ipv6"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#ipv6"}},[t._v("#")]),t._v(" ipv6")]),t._v(" "),e("p",[t._v("The field under validation must be a string and be an IPv6 address.\nThis rule converts the field to "),e("code",[t._v("net.IP")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"json"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#json"}},[t._v("#")]),t._v(" json")]),t._v(" "),e("p",[t._v("The field under validation must be a valid JSON string. This rule unmarshals the string and sets the field value to the unmarshalled result.")]),t._v(" "),e("h4",{attrs:{id:"url"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#url"}},[t._v("#")]),t._v(" url")]),t._v(" "),e("p",[t._v("The field under validation must be a valid URL.\nThis rule converts the field to "),e("code",[t._v("*url.URL")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"uuid-version"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#uuid-version"}},[t._v("#")]),t._v(" uuid:version")]),t._v(" "),e("p",[t._v("The field under validation must be a string and a valid UUID.")]),t._v(" "),e("p",[t._v("The "),e("code",[t._v("version")]),t._v(" parameter is "),e("strong",[t._v("optional")]),t._v(".")]),t._v(" "),e("ul",[e("li",[t._v("If a "),e("code",[t._v("version")]),t._v(" is given ("),e("code",[t._v("uuid:3")]),t._v(","),e("code",[t._v("uuid:4")]),t._v(","),e("code",[t._v("uuid:5")]),t._v("), the rule will pass only if the version of the UUID matches.")]),t._v(" "),e("li",[t._v("If no "),e("code",[t._v("version")]),t._v(" is given, any UUID version is accepted.")])]),t._v(" "),e("p",[t._v("This rule converts the field to "),e("code",[t._v("uuid.UUID")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"bool"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#bool"}},[t._v("#")]),t._v(" bool")]),t._v(" "),e("p",[t._v("The field under validation must be a boolean or one of the following values:")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("1")]),t._v("/"),e("code",[t._v("0")])]),t._v(" "),e("li",[e("code",[t._v('"1"')]),t._v("/"),e("code",[t._v('"0"')])]),t._v(" "),e("li",[e("code",[t._v('"on"')]),t._v("/"),e("code",[t._v('"off"')])]),t._v(" "),e("li",[e("code",[t._v('"true"')]),t._v("/"),e("code",[t._v('"false"')])]),t._v(" "),e("li",[e("code",[t._v('"yes"')]),t._v("/"),e("code",[t._v('"no"')])])]),t._v(" "),e("p",[t._v("This rule converts the field to "),e("code",[t._v("bool")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"same-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#same-field"}},[t._v("#")]),t._v(" same:field")]),t._v(" "),e("p",[t._v("The field under validation must have the same value as the given "),e("code",[t._v("field")]),t._v(". For arrays, the two fields must have the same values in the same order.")]),t._v(" "),e("p",[t._v("The two fields must have the same type. Files are not checked.")]),t._v(" "),e("h4",{attrs:{id:"different-field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#different-field"}},[t._v("#")]),t._v(" different:field")]),t._v(" "),e("p",[t._v("The field under validation must have a different value from the given "),e("code",[t._v("field")]),t._v(". For arrays, the two fields must have different values or not be in the same order.")]),t._v(" "),e("p",[t._v("The two fields must have the same type. Files are not checked.")]),t._v(" "),e("h4",{attrs:{id:"confirmed"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#confirmed"}},[t._v("#")]),t._v(" confirmed")]),t._v(" "),e("p",[t._v("The field under validation must have a matching "),e("code",[t._v("foo_confirmation")]),t._v(". This rule validate equality in the same way as the "),e("a",{attrs:{href:"#same-field"}},[e("code",[t._v("same")])]),t._v(" rule.")]),t._v(" "),e("p",[t._v("For example, if the field under validation is "),e("code",[t._v("password")]),t._v(", a matching "),e("code",[t._v("password_confirmation")]),t._v(" field must be present in the input.")]),t._v(" "),e("h4",{attrs:{id:"file"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#file"}},[t._v("#")]),t._v(" file")]),t._v(" "),e("p",[t._v("The field under validation must be a file. Multi-files are supported.\nThis rule converts the field to "),e("code",[t._v("[]filesystem.File")]),t._v(" if it passes.")]),t._v(" "),e("h4",{attrs:{id:"mime-foo"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#mime-foo"}},[t._v("#")]),t._v(" mime:foo,...")]),t._v(" "),e("p",[t._v("The field under validation must be a file and match one of the given MIME types. If the field is a multi-files, all files must satisfy this rule.")]),t._v(" "),e("h4",{attrs:{id:"image"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#image"}},[t._v("#")]),t._v(" image")]),t._v(" "),e("p",[t._v("The field under validation must be a file and match one of the following MIME types:")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("image/jpeg")])]),t._v(" "),e("li",[e("code",[t._v("image/png")])]),t._v(" "),e("li",[e("code",[t._v("image/gif")])]),t._v(" "),e("li",[e("code",[t._v("image/bmp")])]),t._v(" "),e("li",[e("code",[t._v("image/svg+xml")])]),t._v(" "),e("li",[e("code",[t._v("image/webp")])])]),t._v(" "),e("p",[t._v("If the field is a multi-files, all files must satisfy this rule.")]),t._v(" "),e("h4",{attrs:{id:"extension-foo"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#extension-foo"}},[t._v("#")]),t._v(" extension:foo,...")]),t._v(" "),e("p",[t._v("The field under validation must be a file and match one of the given extensions. If the field is a multi-files, all files must satisfy this rule.")]),t._v(" "),e("h4",{attrs:{id:"count-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#count-value"}},[t._v("#")]),t._v(" count:value")]),t._v(" "),e("p",[t._v("The field under validation must be a multi-file and contain "),e("code",[t._v("value")]),t._v(" files.")]),t._v(" "),e("h4",{attrs:{id:"count-min-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#count-min-value"}},[t._v("#")]),t._v(" count_min:value")]),t._v(" "),e("p",[t._v("The field under validation must be a multi-file and contain at least "),e("code",[t._v("value")]),t._v(" files.")]),t._v(" "),e("h4",{attrs:{id:"count-max-value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#count-max-value"}},[t._v("#")]),t._v(" count_max:value")]),t._v(" "),e("p",[t._v("The field under validation must be a multi-file and may not contain more than "),e("code",[t._v("value")]),t._v(" files.")]),t._v(" "),e("h4",{attrs:{id:"count-between-min-max"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#count-between-min-max"}},[t._v("#")]),t._v(" count_between:min,max")]),t._v(" "),e("p",[t._v("The field under validation must be a multi-file and contain between "),e("code",[t._v("min")]),t._v(" and "),e("code",[t._v("max")]),t._v(" files.")]),t._v(" "),e("h4",{attrs:{id:"date-format"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#date-format"}},[t._v("#")]),t._v(" date:format")]),t._v(" "),e("p",[t._v("The field under validation must be a string representing a date. The "),e("code",[t._v("format")]),t._v(" is optional. If no format is given, the "),e("code",[t._v("2006-01-02")]),t._v(" format is used.")]),t._v(" "),e("p",[t._v("This rule converts the field to "),e("code",[t._v("time.Time")]),t._v(" if it passes.")]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("See the "),e("a",{attrs:{href:"https://golang.org/src/time/format.go",target:"_blank",rel:"noopener noreferrer"}},[t._v("Golang datetime format"),e("OutboundLink")],1),t._v(".")])]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),e("p",[t._v("When validating dates by comparing them together, the order of the declaration of the fields in the request is important. For example, if you want to validate that an end date is after a start date, the start date should be decalred "),e("strong",[t._v("before")]),t._v(" the end date in the rules set.")]),t._v(" "),e("p",[t._v("If a date has not been validated and converted yet, the date comparison rules will attempt to parse the dates using the following format: "),e("code",[t._v("2006-01-02")]),t._v(".")])]),t._v(" "),e("h4",{attrs:{id:"before-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#before-date"}},[t._v("#")]),t._v(" before:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value preceding the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be preceding the given field.")]),t._v(" "),e("h4",{attrs:{id:"before-equal-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#before-equal-date"}},[t._v("#")]),t._v(" before_equal:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value preceding or equal to the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be preceding or equal to given field.")]),t._v(" "),e("h4",{attrs:{id:"after-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#after-date"}},[t._v("#")]),t._v(" after:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value after the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be preceding the given field.")]),t._v(" "),e("h4",{attrs:{id:"after-equal-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#after-equal-date"}},[t._v("#")]),t._v(" after_equal:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value after or equal to the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be after or equal to given field.")]),t._v(" "),e("h4",{attrs:{id:"date-equals-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#date-equals-date"}},[t._v("#")]),t._v(" date_equals:date")]),t._v(" "),e("p",[t._v("The field under validation must be a value equal to the given date. The "),e("code",[t._v("date")]),t._v(" must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a "),e("code",[t._v("date")]),t._v(", then the two fields must be a date and the field under validation must be equal to given field.")]),t._v(" "),e("h4",{attrs:{id:"date-between-date1-date2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#date-between-date1-date2"}},[t._v("#")]),t._v(" date_between:date1,date2")]),t._v(" "),e("p",[t._v("The field under validation must be a value between or equal to the given dates. The given dates must be written using following format: "),e("code",[t._v("2006-01-02T15:04:05")]),t._v(".")]),t._v(" "),e("p",[t._v("If the name of another field is given as a date, then all the fields must be a date and the field under validation must be between or equal to given fields.")]),t._v(" "),e("h2",{attrs:{id:"custom-rules"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#custom-rules"}},[t._v("#")]),t._v(" Custom rules")]),t._v(" "),e("p",[t._v("If none of the available validation rules satisfy your needs, you can implement custom validation rules. To do so, create a new file "),e("code",[t._v("http/requests/validation.go")]),t._v(" in which you are going to define your custom rules.")]),t._v(" "),e("p",[t._v("Rules definition shouldn't be exported, and start with "),e("code",[t._v("validate")]),t._v(". A rule returns a "),e("code",[t._v("bool")]),t._v(", indicating if the validation passed or not.")]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("validateCustomFormat")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" value "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" form "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Ensure the rule has at least one parameter")]),t._v("\n validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("RequireParametersCount")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"custom_format"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n str"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" value"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" ok "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The data under validation is a string")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" regexp"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("MustCompile")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("MatchString")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("str"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Cannot validate this field")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("validation.Rule")]),t._v(" is an alias for "),e("code",[t._v("func(string, interface{}, []string, map[string]interface{}) bool")])]),t._v(" "),e("li",[t._v("The "),e("code",[t._v("form")]),t._v(" parameter lets you access the whole form data, and modify it if needed.")]),t._v(" "),e("li",[t._v("The custom rule in the example above validates a string using a regex. If you need this kind of validation, prefer the included "),e("code",[t._v("regex")]),t._v(" validation rule.")])])]),t._v(" "),e("p",[t._v("Now that your rule behavior is defined, you need to "),e("strong",[t._v("register")]),t._v(" your rule. Do this in an "),e("code",[t._v("init()")]),t._v(" function in your "),e("code",[t._v("validation.go")]),t._v(" file.")]),t._v(" "),e("h4",{attrs:{id:"validation-addrule"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-addrule"}},[t._v("#")]),t._v(" validation.AddRule")]),t._v(" "),e("p",[t._v("Register a validation rule.")]),t._v(" "),e("p",[t._v("The rule will be usable in request validation by using the given rule name.")]),t._v(" "),e("p",[t._v('Type-dependent messages let you define a different message for numeric, string, arrays and files. The language entry used will be "validation.rules.rulename.type"')]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("name string")])]),t._v(" "),e("td",[e("code",[t._v("void")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("typeDependentMessage bool")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("rule validation.Rule")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddRule")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"custom_format"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" validateCustomFormat"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h4",{attrs:{id:"validation-requireparameterscount"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-requireparameterscount"}},[t._v("#")]),t._v(" validation.RequireParametersCount")]),t._v(" "),e("p",[t._v("Checks if the given parameters slice has at least "),e("code",[t._v("count")]),t._v(" elements. If this criteria is not met, the function triggers a panic.")]),t._v(" "),e("p",[t._v("Use this to make sure your validation rules are correctly used.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("rule string")])]),t._v(" "),e("td",[e("code",[t._v("void")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("params []string")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("count int")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("RequireParametersCount")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"custom_format"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h4",{attrs:{id:"validation-getfieldtype"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-getfieldtype"}},[t._v("#")]),t._v(" validation.GetFieldType")]),t._v(" "),e("p",[e("Badge",{attrs:{text:"Since v2.0.0"}})],1),t._v(" "),e("p",[t._v("returns the non-technical type of the given "),e("code",[t._v("value")]),t._v(" interface.\nThis is used by validation rules to know if the input data is a candidate\nfor validation or not and is especially useful for type-dependent rules.")]),t._v(" "),e("ul",[e("li",[e("code",[t._v("numeric")]),t._v(" if the value is an int, uint or a float")]),t._v(" "),e("li",[e("code",[t._v("string")]),t._v(" if the value is a string")]),t._v(" "),e("li",[e("code",[t._v("array")]),t._v(" if the value is a slice")]),t._v(" "),e("li",[e("code",[t._v("file")]),t._v(" if the value is a slice of "),e("code",[t._v("filesystem.File")])]),t._v(" "),e("li",[e("code",[t._v("unsupported")]),t._v(" otherwise")])]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("value interface{}")])]),t._v(" "),e("td",[e("code",[t._v("string")])])])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetFieldType")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"foo"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "string"')]),t._v("\nvalidation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetFieldType")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "numeric"')]),t._v("\nvalidation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetFieldType")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2.4")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "numeric"')]),t._v("\nvalidation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetFieldType")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "array"')]),t._v("\n")])])]),e("h2",{attrs:{id:"validating-arrays"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validating-arrays"}},[t._v("#")]),t._v(" Validating arrays")]),t._v(" "),e("p",[e("Badge",{attrs:{text:"Since v2.1.0"}}),e("Badge",{attrs:{text:"BETA",type:"warn"}})],1),t._v(" "),e("p",[t._v("Validating arrays is easy. All the validation rules, "),e("strong",[t._v("except the file-related rules and the "),e("code",[t._v("confirmed")]),t._v(" rule")]),t._v(", can be applied to array values using the prefix "),e("code",[t._v(">")]),t._v(". When array values are validated, "),e("strong",[t._v("all of them")]),t._v(" must pass the validation.")]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" arrayValidation "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"array"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"array:string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"between:1,5"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">email"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">max:128"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("In this example, we are validating an array of one to five email addresses, which can't be longer than 128 characters.")]),t._v(" "),e("h3",{attrs:{id:"n-dimensional-arrays"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#n-dimensional-arrays"}},[t._v("#")]),t._v(" N-dimensional arrays")]),t._v(" "),e("p",[t._v("You can validate n-dimensional arrays.")]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" arrayValidation "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" RuleSet"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"array"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"array"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">array"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">>array:numeric"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">max:3"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('">>>max:4"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("p",[t._v("In this example, we are validating a three-dimensional array of numeric values. The second dimension must be made of arrays with a size of 3 or less. The third dimension must contain numbers inferior or equal to 4. The following JSON input passes the validation:")]),t._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token property"}},[t._v('"array"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.5")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.42")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.6")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.6")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.43")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("h2",{attrs:{id:"placeholders"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#placeholders"}},[t._v("#")]),t._v(" Placeholders")]),t._v(" "),e("p",[t._v("Validation messages can use placeholders to inject dynamic values in the validation error message. For example, in the "),e("code",[t._v("rules.json")]),t._v(" language file:")]),t._v(" "),e("div",{staticClass:"language-json extra-class"},[e("pre",{pre:!0,attrs:{class:"language-json"}},[e("code",[e("span",{pre:!0,attrs:{class:"token property"}},[t._v('"between.string"')]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"The :field must be between :min and :max characters."')]),t._v("\n")])])]),e("p",[t._v("Here, the "),e("code",[t._v(":field")]),t._v(" placeholder will be replaced by the field name, "),e("code",[t._v(":min")]),t._v(" with the first parameter and "),e("code",[t._v(":max")]),t._v(" with the second parameter, effectively giving the following result:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("The password must be between 6 and 32 characters. \n")])])]),e("p",[t._v("Placeholders are "),e("strong",[t._v("replacer functions")]),t._v(". In fact, "),e("code",[t._v("validation.Placeholder")]),t._v(" is an alias for "),e("code",[t._v("func(string, string, []string, string) string")]),t._v(". These functions should return the value to replace the placeholder with.")]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("simpleParameterPlaceholder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rule "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" language "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),e("hr"),t._v(" "),e("p",[t._v("Placeholders are implemented in the "),e("code",[t._v("http/requests/placeholders.go")]),t._v(". To register a custom placeholder, use the "),e("code",[t._v("validation.SetPlaceholder()")]),t._v(" function, preferably in the "),e("code",[t._v("init()")]),t._v(" function of your "),e("code",[t._v("placeholders.go")]),t._v(" file.")]),t._v(" "),e("h4",{attrs:{id:"validation-setplaceholder"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-setplaceholder"}},[t._v("#")]),t._v(" validation.SetPlaceholder")]),t._v(" "),e("p",[t._v("Sets the replacer function for the given placeholder. Don't include the colon prefix in the placeholder name.")]),t._v(" "),e("p",[t._v("If a placeholder with this name already exists, the latter will be overridden.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("placeholderName string")])]),t._v(" "),e("td",[e("code",[t._v("void")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("replacer validation.Placeholder")])]),t._v(" "),e("td")])])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[t._v("validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetPlaceholder")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"min"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("field "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rule "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parameters "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" language "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" parameters"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Replace ":min" by the first parameter in the rule definition')]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h3",{attrs:{id:"available-placeholders"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#available-placeholders"}},[t._v("#")]),t._v(" Available placeholders")]),t._v(" "),e("h4",{attrs:{id:"field"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#field"}},[t._v("#")]),t._v(" :field")]),t._v(" "),e("p",[e("code",[t._v(":field")]),t._v(" is replaced by the name of the field. If it exists, the replacer with favor the language lines in "),e("code",[t._v("fields.json")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"other"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#other"}},[t._v("#")]),t._v(" :other")]),t._v(" "),e("p",[e("code",[t._v(":other")]),t._v(" is replaced by the name of the field given as first parameter in the rule definition. If it exists, the replacer with favor the language lines in "),e("code",[t._v("fields.json")]),t._v(".")]),t._v(" "),e("p",[t._v("For example, the "),e("code",[t._v("same:password_confirmation")]),t._v(" rule compares two fields together and returns the following message if the validation fails:")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("The :field and the :other must match.\n\nThe password and the password confirmation must match.\n")])])]),e("h4",{attrs:{id:"value"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#value"}},[t._v("#")]),t._v(" :value")]),t._v(" "),e("p",[e("code",[t._v(":value")]),t._v(" is replaced by the first parameter of the rule definition.")]),t._v(" "),e("h4",{attrs:{id:"values"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#values"}},[t._v("#")]),t._v(" :values")]),t._v(" "),e("p",[e("code",[t._v(":values")]),t._v(" is replaced by a concatenation of all rule parameters, joined by a comma.")]),t._v(" "),e("h4",{attrs:{id:"min"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#min"}},[t._v("#")]),t._v(" :min")]),t._v(" "),e("p",[e("code",[t._v(":min")]),t._v(" is replaced by the first parameter of the rule definition.")]),t._v(" "),e("h4",{attrs:{id:"max"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#max"}},[t._v("#")]),t._v(" :max")]),t._v(" "),e("p",[e("code",[t._v(":max")]),t._v(" is replaced by the first parameter of the rule definition, or the second if the rule name contains "),e("code",[t._v("between")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"version"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#version"}},[t._v("#")]),t._v(" :version")]),t._v(" "),e("p",[e("code",[t._v(":version")]),t._v(" is replaced by a concatenation of "),e("code",[t._v("v")]),t._v(" and the first parameter of the rule definition, or by an empty string if the rule doesn't have any parameter.")]),t._v(" "),e("p",[t._v("For example, for the "),e("code",[t._v("UUID:4")]),t._v(" rule, the result would be "),e("code",[t._v("v4")]),t._v(".")]),t._v(" "),e("h4",{attrs:{id:"date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#date"}},[t._v("#")]),t._v(" :date")]),t._v(" "),e("p",[e("code",[t._v(":date")]),t._v(" is replaced by the first parameter of the rule definition. If the first parameter is a field name, "),e("code",[t._v(":date")]),t._v(" will be replaced with the name of the field in the same way as the "),e("code",[t._v(":other")]),t._v(" placeholder.")]),t._v(" "),e("h4",{attrs:{id:"max-date"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#max-date"}},[t._v("#")]),t._v(" :max_date")]),t._v(" "),e("p",[e("code",[t._v(":max_date")]),t._v(" is replaced by the second parameter of the rule definition. If the second parameter is a field name, "),e("code",[t._v(":max_date")]),t._v(" will be replaced with the name of the field in the same way as the "),e("code",[t._v(":other")]),t._v(" placeholder.")]),t._v(" "),e("h2",{attrs:{id:"manual-validation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#manual-validation"}},[t._v("#")]),t._v(" Manual validation")]),t._v(" "),e("p",[e("Badge",{attrs:{text:"Since v2.1.0"}})],1),t._v(" "),e("p",[t._v("You may need to validate some data manually as part of your business logic. You can use the Goyave validator to do so.")]),t._v(" "),e("h4",{attrs:{id:"validation-validate"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#validation-validate"}},[t._v("#")]),t._v(" validation.Validate")]),t._v(" "),e("p",[t._v("Validate the given data with the given rule set. If all validation rules pass, returns an empty "),e("code",[t._v("validation.Errors")]),t._v(".")]),t._v(" "),e("p",[t._v("The third parameter ("),e("code",[t._v("isJSON")]),t._v(") tells the function if the data comes from a JSON request. This is used to return the correct message if the given data is "),e("code",[t._v("nil")]),t._v(" and to correctly handle arrays in url-encoded requests.")]),t._v(" "),e("p",[t._v("The last parameter ("),e("code",[t._v("language")]),t._v(") sets the language of the validation error messages.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Parameters")]),t._v(" "),e("th",[t._v("Return")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[e("code",[t._v("data map[string]interface{}")])]),t._v(" "),e("td",[e("code",[t._v("validation.Errors")])])]),t._v(" "),e("tr",[e("td",[e("code",[t._v("rules RuleSet")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("isJSON bool")])]),t._v(" "),e("td")]),t._v(" "),e("tr",[e("td",[e("code",[t._v("language string")])]),t._v(" "),e("td")])])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[e("code",[t._v("validation.Errors")]),t._v(" is an alias for "),e("code",[t._v("map[string][]string")]),t._v(". The key represents the field name and the associated slice contains all already translated validation error messages for this field.")])]),t._v(" "),e("p",[e("strong",[t._v("Example:")])]),t._v(" "),e("div",{staticClass:"language-go extra-class"},[e("pre",{pre:!0,attrs:{class:"language-go"}},[e("code",[e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Store")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n data "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello world"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"number"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("42")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\terrors "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("Validate")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("data"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RuleSet"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"number"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"required"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"numeric"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"min:10"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lang"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("errors"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tresponse"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("JSON")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusUnprocessableEntity"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("validation"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Errors"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"validationError"')]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" errors"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),e("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// data can be safely used from here")]),t._v("\n\t"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/22.57006fdb.js b/docs/assets/js/22.57006fdb.js new file mode 100644 index 00000000..e90d004a --- /dev/null +++ b/docs/assets/js/22.57006fdb.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{221:function(e,t,a){"use strict";a.r(t);var i=a(0),v=Object(i.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"changelog"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#changelog"}},[e._v("#")]),e._v(" Changelog")]),e._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#v2-2-0"}},[e._v("v2.2.0")])]),a("li",[a("a",{attrs:{href:"#v2-1-0"}},[e._v("v2.1.0")])]),a("li",[a("a",{attrs:{href:"#v2-0-0"}},[e._v("v2.0.0")])])])]),a("p"),e._v(" "),a("h2",{attrs:{id:"v2-2-0"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#v2-2-0"}},[e._v("#")]),e._v(" v2.2.0")]),e._v(" "),a("ul",[a("li",[e._v("Added "),a("router-link",{attrs:{to:"/guide/advanced/testing.html"}},[e._v("testing API")]),e._v(".")],1),e._v(" "),a("li",[e._v("Fixed links in documentation.")]),e._v(" "),a("li",[e._v("Fixed "),a("code",[e._v("models")]),e._v(" package in template project. (Changed to "),a("code",[e._v("model")]),e._v(")")]),e._v(" "),a("li",[e._v("Added "),a("router-link",{attrs:{to:"/guide/basics/database.html#database-clearregisteredmodels"}},[a("code",[e._v("database.ClearRegisteredModels")])])],1)]),e._v(" "),a("h2",{attrs:{id:"v2-1-0"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#v2-1-0"}},[e._v("#")]),e._v(" v2.1.0")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("filesystem.GetMIMEType")]),e._v(" now detects "),a("code",[e._v("css")]),e._v(", "),a("code",[e._v("js")]),e._v(", "),a("code",[e._v("json")]),e._v(" and "),a("code",[e._v("jsonld")]),e._v(" files based on their extension.")]),e._v(" "),a("li",[e._v("Added maintenance mode.\n"),a("ul",[a("li",[e._v("Can be "),a("router-link",{attrs:{to:"/guide/advanced/multi-services.html#maintenance-mode"}},[e._v("toggled at runtime")]),e._v(".")],1),e._v(" "),a("li",[e._v("The server can be started in maintenance mode using the "),a("code",[e._v("maintenance")]),e._v(" config option. (Defaults to "),a("code",[e._v("false")]),e._v(")")])])]),e._v(" "),a("li",[e._v("Added "),a("router-link",{attrs:{to:"/guide/basics/validation.html#validating-arrays"}},[e._v("advanced array validation")]),e._v(", with support for n-dimensional arrays."),a("Badge",{attrs:{text:"BETA",type:"warn"}})],1),e._v(" "),a("li",[e._v("Malformed request messages can now be localized. ("),a("code",[e._v("malformed-request")]),e._v(" and "),a("code",[e._v("malformed-json")]),e._v(" entries in "),a("code",[e._v("locale.json")]),e._v(")")]),e._v(" "),a("li",[e._v("Modified the validator to allow "),a("router-link",{attrs:{to:"/guide/basics/validation.html#manual-validation"}},[e._v("manual validation")]),e._v(".")],1)]),e._v(" "),a("h2",{attrs:{id:"v2-0-0"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#v2-0-0"}},[e._v("#")]),e._v(" v2.0.0")]),e._v(" "),a("ul",[a("li",[e._v("Documentation and README improvements.")]),e._v(" "),a("li",[e._v("In the configuration:\n"),a("ul",[a("li",[e._v("The default value of "),a("code",[e._v("dbConnection")]),e._v(" has been changed to "),a("code",[e._v("none")]),e._v(".")]),e._v(" "),a("li",[e._v("The default value of "),a("code",[e._v("dbAutoMigrate")]),e._v(" has been changed to "),a("code",[e._v("false")]),e._v(".")])])]),e._v(" "),a("li",[e._v("Added "),a("router-link",{attrs:{to:"/guide/basics/requests.html#accessors"}},[e._v("request data accessors")]),e._v(".")],1),e._v(" "),a("li",[e._v("Some refactoring and package renaming have been done to better respect the Go conventions.\n"),a("ul",[a("li",[e._v("The "),a("code",[e._v("helpers")]),e._v(" package have been renamed to "),a("code",[e._v("helper")])])])]),e._v(" "),a("li",[e._v("The server now shuts down when it encounters an error during startup.")]),e._v(" "),a("li",[e._v("New "),a("router-link",{attrs:{to:"/guide/basics/validation.html#validation-getfieldtype"}},[a("code",[e._v("validation.GetFieldType")])]),e._v(" function.")],1),e._v(" "),a("li",[e._v("Config and Lang are now protected with a "),a("code",[e._v("sync.RWMutex")]),e._v(" to avoid data races in multi-threaded environments.")]),e._v(" "),a("li",[e._v("Greatly improve concurrency.")]),e._v(" "),a("li",[e._v("Config can now be reloaded manually.")]),e._v(" "),a("li",[e._v("Added the "),a("router-link",{attrs:{to:"/guide/basics/middleware.html#trim"}},[a("code",[e._v("Trim")])]),e._v(" middleware.")],1),e._v(" "),a("li",[a("code",[e._v("goyave.Response")]),e._v(" now implements "),a("code",[e._v("http.ResponseWriter")]),e._v(".\n"),a("ul",[a("li",[e._v("All writing functions can now return an error.")])])]),e._v(" "),a("li",[e._v("Added the "),a("router-link",{attrs:{to:"/guide/basics/routing.html#native-handlers"}},[a("code",[e._v("NativeHandler")])]),e._v(" compatibility layer.")],1),e._v(" "),a("li",[e._v("Fixed a bug preventing the static resources handler to find "),a("code",[e._v("index.html")]),e._v(" if a directory with a depth of one was requested without a trailing slash.")]),e._v(" "),a("li",[e._v("Now panics when calling "),a("code",[e._v("Start()")]),e._v(" while the server is already running.")])])])}),[],!1,null,null,null);t.default=v.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/22.d93658d2.js b/docs/assets/js/22.d93658d2.js deleted file mode 100644 index 5339c9f8..00000000 --- a/docs/assets/js/22.d93658d2.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{222:function(e,t,a){"use strict";a.r(t);var n=a(0),i=Object(n.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"changelog"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#changelog"}},[e._v("#")]),e._v(" Changelog")]),e._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#v2-1-0"}},[e._v("v2.1.0")])]),a("li",[a("a",{attrs:{href:"#v2-0-0"}},[e._v("v2.0.0")])])])]),a("p"),e._v(" "),a("h2",{attrs:{id:"v2-1-0"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#v2-1-0"}},[e._v("#")]),e._v(" v2.1.0")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("filesystem.GetMIMEType")]),e._v(" now detects "),a("code",[e._v("css")]),e._v(", "),a("code",[e._v("js")]),e._v(", "),a("code",[e._v("json")]),e._v(" and "),a("code",[e._v("jsonld")]),e._v(" files based on their extension.")]),e._v(" "),a("li",[e._v("Added maintenance mode.\n"),a("ul",[a("li",[e._v("Can be "),a("router-link",{attrs:{to:"/guide/advanced/multi-services.html#maintenance-mode"}},[e._v("toggled at runtime")]),e._v(".")],1),e._v(" "),a("li",[e._v("The server can be started in maintenance mode using the "),a("code",[e._v("maintenance")]),e._v(" config option. (Defaults to "),a("code",[e._v("false")]),e._v(")")])])]),e._v(" "),a("li",[e._v("Added "),a("router-link",{attrs:{to:"/guide/basics/validation.html#validating-arrays"}},[e._v("advanced array validation")]),e._v(", with support for n-dimensional arrays."),a("Badge",{attrs:{text:"BETA",type:"warn"}})],1),e._v(" "),a("li",[e._v("Malformed request messages can now be localized. ("),a("code",[e._v("malformed-request")]),e._v(" and "),a("code",[e._v("malformed-json")]),e._v(" entries in "),a("code",[e._v("locale.json")]),e._v(")")]),e._v(" "),a("li",[e._v("Modified the validator to allow "),a("router-link",{attrs:{to:"/guide/basics/validation.html#manual-validation"}},[e._v("manual validation")]),e._v(".")],1)]),e._v(" "),a("h2",{attrs:{id:"v2-0-0"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#v2-0-0"}},[e._v("#")]),e._v(" v2.0.0")]),e._v(" "),a("ul",[a("li",[e._v("Documentation and README improvements.")]),e._v(" "),a("li",[e._v("In the configuration:\n"),a("ul",[a("li",[e._v("The default value of "),a("code",[e._v("dbConnection")]),e._v(" has been changed to "),a("code",[e._v("none")]),e._v(".")]),e._v(" "),a("li",[e._v("The default value of "),a("code",[e._v("dbAutoMigrate")]),e._v(" has been changed to "),a("code",[e._v("false")]),e._v(".")])])]),e._v(" "),a("li",[e._v("Added "),a("router-link",{attrs:{to:"/guide/basics/requests.html#accessors"}},[e._v("request data accessors")]),e._v(".")],1),e._v(" "),a("li",[e._v("Some refactoring and package renaming have been done to better respect the Go conventions.\n"),a("ul",[a("li",[e._v("The "),a("code",[e._v("helpers")]),e._v(" package have been renamed to "),a("code",[e._v("helper")])])])]),e._v(" "),a("li",[e._v("The server now shuts down when it encounters an error.")]),e._v(" "),a("li",[e._v("New "),a("router-link",{attrs:{to:"/guide/basics/validation.html#validation-getfieldtype"}},[a("code",[e._v("validation.GetFieldType")])]),e._v(" function.")],1),e._v(" "),a("li",[e._v("Config and Lang are now protected with a "),a("code",[e._v("sync.RWMutex")]),e._v(" to avoid data races in multi-threaded environments.")]),e._v(" "),a("li",[e._v("Greatly improve concurrency.")]),e._v(" "),a("li",[e._v("Config can now be reloaded manually.")]),e._v(" "),a("li",[e._v("Added the "),a("router-link",{attrs:{to:"/guide/basics/middleware.html#trim"}},[a("code",[e._v("Trim")])]),e._v(" middleware.")],1),e._v(" "),a("li",[a("code",[e._v("goyave.Response")]),e._v(" now implements "),a("code",[e._v("http.ResponseWriter")]),e._v(".\n"),a("ul",[a("li",[e._v("All writing functions can now return an error.")])])]),e._v(" "),a("li",[e._v("Added the "),a("router-link",{attrs:{to:"/guide/basics/routing.html#native-handlers"}},[a("code",[e._v("NativeHandler")])]),e._v(" compatibility layer.")],1),e._v(" "),a("li",[e._v("Fixed a bug preventing the static resources handler to find "),a("code",[e._v("index.html")]),e._v(" if a directory with a depth of one was requested without a trailing slash.")]),e._v(" "),a("li",[e._v("Now panics when calling "),a("code",[e._v("Start()")]),e._v(" while the server is already running.")])])])}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/23.52a712ea.js b/docs/assets/js/23.db2ae409.js similarity index 99% rename from docs/assets/js/23.52a712ea.js rename to docs/assets/js/23.db2ae409.js index 36b2764a..189b59d9 100644 --- a/docs/assets/js/23.52a712ea.js +++ b/docs/assets/js/23.db2ae409.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{231:function(t,e,a){"use strict";a.r(e);var n=a(0),o=Object(n.a)({},(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#configuration"}},[t._v("#")]),t._v(" Configuration")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#environment-configuration"}},[t._v("Environment configuration")])]),a("li",[a("a",{attrs:{href:"#using-the-configuration"}},[t._v("Using the configuration")]),a("ul",[a("li",[a("a",{attrs:{href:"#getting-a-value"}},[t._v("Getting a value")])]),a("li",[a("a",{attrs:{href:"#setting-a-value"}},[t._v("Setting a value")])])])]),a("li",[a("a",{attrs:{href:"#custom-config-entries"}},[t._v("Custom config entries")])]),a("li",[a("a",{attrs:{href:"#configuration-reference"}},[t._v("Configuration reference")])]),a("li",[a("a",{attrs:{href:"#setting-up-https"}},[t._v("Setting up HTTPS")])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[t._v("The Goyave framework lets you configure its core and your application.\nTo configure your application, use the "),a("code",[t._v("config.json")]),t._v(" file at your project's root. If you are using the template project, copy "),a("code",[t._v("config.example.json")]),t._v(" to "),a("code",[t._v("config.json")]),t._v(". "),a("code",[t._v("config.json")]),t._v(" should be ignored in your "),a("code",[t._v(".gitignore")]),t._v(" file as it can differ from one developer to another. To avoid accidental commit or change to the default project's config, it is a good practice to ignore this file and define the project's default config in "),a("code",[t._v("config.example.json")]),t._v(".")]),t._v(" "),a("p",[t._v("If this config file misses some config entries, the default values will be used. All values from the framework's core are "),a("strong",[t._v("validated")]),t._v(". 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)."),a("br"),t._v("\nSee the "),a("a",{attrs:{href:"#configuration-reference"}},[t._v("configuration reference")]),t._v(" for more details.")]),t._v(" "),a("h2",{attrs:{id:"environment-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#environment-configuration"}},[t._v("#")]),t._v(" Environment configuration")]),t._v(" "),a("p",[t._v("Most projects need different configuration values based on the environment. For example, you won't connect to the same database if you're in local development, in a testing environment inside continuous integration pipelines, or in production. Goyave supports multiple configurations and will pick the appropriate one depending on the environment variable "),a("code",[t._v("GOYAVE_ENV")]),t._v(".")]),t._v(" "),a("p",[t._v("Since "),a("code",[t._v("v2.0.0")]),t._v(", you can use custom environments.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("GOYAVE_ENV")]),t._v(" "),a("th",[t._v("Config file")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[t._v("test")]),t._v(" "),a("td",[a("code",[t._v("config.test.json")])])]),t._v(" "),a("tr",[a("td",[t._v("production")]),t._v(" "),a("td",[a("code",[t._v("config.production.json")])])]),t._v(" "),a("tr",[a("td",[a("em",[t._v("custom_env")])]),t._v(" "),a("td",[a("code",[t._v("config.custom_env.json")])])]),t._v(" "),a("tr",[a("td",[t._v("local / localhost / "),a("em",[t._v("not set")])]),t._v(" "),a("td",[a("code",[t._v("config.json")])])])])]),t._v(" "),a("h2",{attrs:{id:"using-the-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#using-the-configuration"}},[t._v("#")]),t._v(" Using the configuration")]),t._v(" "),a("p",[t._v("Before being able to use the config, import the config package:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/config"')]),t._v("\n")])])]),a("p",[t._v("The configuration is loaded automatically when the server starts, but you can reload it manually if needed.")]),t._v(" "),a("h4",{attrs:{id:"config-load"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-load"}},[t._v("#")]),t._v(" config.Load")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("error")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Load")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"getting-a-value"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-a-value"}},[t._v("#")]),t._v(" Getting a value")]),t._v(" "),a("h4",{attrs:{id:"config-get"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-get"}},[t._v("#")]),t._v(" config.Get")]),t._v(" "),a("p",[t._v("Get a generic config entry. You may need to type-assert it before being able to use it. You can do so safely as the config values and types are validated. Panics if the entry doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("key string")])]),t._v(" "),a("td",[a("code",[t._v("interface{}")]),t._v(" or panic")])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"appName"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "goyave"')]),t._v("\n")])])]),a("h4",{attrs:{id:"config-getstring"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-getstring"}},[t._v("#")]),t._v(" config.GetString")]),t._v(" "),a("p",[t._v("Get a string config entry. Panics if the entry doesn't exist or is not a string.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("key string")])]),t._v(" "),a("td",[a("code",[t._v("string")]),t._v(" or panic")])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"protocol"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "http"')]),t._v("\n")])])]),a("h4",{attrs:{id:"config-getbool"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-getbool"}},[t._v("#")]),t._v(" config.GetBool")]),t._v(" "),a("p",[t._v("Get a bool config entry. Panics if the entry doesn't exist or is not a bool.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("key string")])]),t._v(" "),a("td",[a("code",[t._v("bool")]),t._v(" or panic")])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetBool")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"debug"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n")])])]),a("h3",{attrs:{id:"setting-a-value"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#setting-a-value"}},[t._v("#")]),t._v(" Setting a value")]),t._v(" "),a("p",[t._v("You can set a config value at runtime with the "),a("code",[t._v("config.Set(key, value)")]),t._v(" function. Bear in mind that this change "),a("strong",[t._v("temporary")]),t._v(" and will be lost after your application restarts or if the config is reloaded. This function is mainly used for testing purposes. Values set using this function are still being validated, and your application will panic if the validation doesn't pass.")]),t._v(" "),a("h4",{attrs:{id:"config-set"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-set"}},[t._v("#")]),t._v(" config.Set")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("key string")])]),t._v(" "),a("td",[a("code",[t._v("void")]),t._v(" or panic")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("value interface{}")])]),t._v(" "),a("td")])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Set")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"appName"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my awesome app"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"custom-config-entries"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#custom-config-entries"}},[t._v("#")]),t._v(" Custom config entries")]),t._v(" "),a("p",[t._v("The core of the framework contains default values covering most cases, but you can still add custom entries for your most specific needs to the config simply by appending a property to your application's config file. The custom properties are not validated, so you can use the data type you want.")]),t._v(" "),a("h2",{attrs:{id:"configuration-reference"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#configuration-reference"}},[t._v("#")]),t._v(" Configuration reference")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Entry")]),t._v(" "),a("th",[t._v("Type")]),t._v(" "),a("th",[t._v("Accepted values")]),t._v(" "),a("th",[t._v("Default")]),t._v(" "),a("th",[t._v("Note")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[t._v("appName")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"goyave"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("environment")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"localhost"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("maintenance")]),t._v(" "),a("td",[a("code",[t._v("bool")])]),t._v(" "),a("td",[a("code",[t._v("true")]),t._v(", "),a("code",[t._v("false")])]),t._v(" "),a("td",[a("code",[t._v("false")])]),t._v(" "),a("td",[t._v("If "),a("code",[t._v("true")]),t._v(", start the server in maintenance mode. (Always return HTTP 503)")])]),t._v(" "),a("tr",[a("td",[t._v("host")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"127.0.0.1"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("port")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("8080")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("httpsPort")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("8081")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("protocol")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v('"http", "https"')]),t._v(" "),a("td",[t._v('"http"')]),t._v(" "),a("td",[t._v("See the "),a("a",{attrs:{href:"#setting-up-https"}},[t._v("HTTPS")]),t._v(" section")])]),t._v(" "),a("tr",[a("td",[t._v("tlsCert")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v("none")]),t._v(" "),a("td",[t._v("Path to your TLS cert")])]),t._v(" "),a("tr",[a("td",[t._v("tlsKey")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v("none")]),t._v(" "),a("td",[t._v("Path to your TLS key")])]),t._v(" "),a("tr",[a("td",[t._v("debug")]),t._v(" "),a("td",[a("code",[t._v("bool")])]),t._v(" "),a("td",[a("code",[t._v("true")]),t._v(", "),a("code",[t._v("false")])]),t._v(" "),a("td",[a("code",[t._v("true")])]),t._v(" "),a("td",[t._v("When activated, print stacktrace on error and sends error message in response. "),a("strong",[t._v("Disable this in production!")])])]),t._v(" "),a("tr",[a("td",[t._v("timeout")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("10")])]),t._v(" "),a("td",[t._v("Timeout in seconds")])]),t._v(" "),a("tr",[a("td",[t._v("maxUploadSize")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("10")])]),t._v(" "),a("td",[t._v("Max "),a("strong",[t._v("in-memory")]),t._v(" files sent in the request, in MiB")])]),t._v(" "),a("tr",[a("td",[t._v("defaultLanguage")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"en-US"')]),t._v(" "),a("td",[t._v("See the "),a("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[t._v("Localization")]),t._v(" guide")],1)]),t._v(" "),a("tr",[a("td",[t._v("dbConnection")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v('"none", "mysql", "postgres", "sqlite3", "mssql"')]),t._v(" "),a("td",[t._v('"none"')]),t._v(" "),a("td",[t._v("See the "),a("router-link",{attrs:{to:"/guide/basics/database.html"}},[t._v("Database")]),t._v(" guide")],1)]),t._v(" "),a("tr",[a("td",[t._v("dbHost")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"127.0.0.1"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbPort")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("3306")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbName")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"goyave"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbUsername")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"root"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbPassword")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"root"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbOptions")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"charset=utf8&parseTime=true&loc=Local"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbMaxOpenConnections")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("100")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbMaxIdleConnections")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("20")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbAutoMigrate")]),t._v(" "),a("td",[a("code",[t._v("bool")])]),t._v(" "),a("td",[a("code",[t._v("true")]),t._v(", "),a("code",[t._v("false")])]),t._v(" "),a("td",[a("code",[t._v("false")])]),t._v(" "),a("td",[t._v("When activated, migrate all registered models at startup")])])])]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),a("p",[t._v("Numeric values are parsed as "),a("code",[t._v("float64")]),t._v(" even if they are supposed to be integers so it covers the potential use-case of floats in the config.")])]),t._v(" "),a("h2",{attrs:{id:"setting-up-https"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#setting-up-https"}},[t._v("#")]),t._v(" Setting up HTTPS")]),t._v(" "),a("p",[t._v("Setting up HTTPS on your Goyave application is easy. First, turn "),a("code",[t._v("protocol")]),t._v(" to "),a("code",[t._v("https")]),t._v(" in the config. Then, add the "),a("code",[t._v("tlsCert")]),t._v(" and "),a("code",[t._v("tlsKey")]),t._v(" entries in the config. These two entries represent respectively the path to your TLS certificate and your TLS key.")]),t._v(" "),a("p",[a("strong",[t._v("Certbot example:")])]),t._v(" "),a("div",{staticClass:"language-json extra-class"},[a("pre",{pre:!0,attrs:{class:"language-json"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ...\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"protocol"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"tlsCert"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/etc/letsencrypt/live/mydomain.com/cert.pem"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"tlsKey"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/etc/letsencrypt/live/mydomain.com/privkey.pem"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ...\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Restart your server and you should now be able to connect securely to your Goyave application! All HTTP requests will automatically be redirected to HTTPS.")])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{230:function(t,e,a){"use strict";a.r(e);var n=a(0),o=Object(n.a)({},(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#configuration"}},[t._v("#")]),t._v(" Configuration")]),t._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[t._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#environment-configuration"}},[t._v("Environment configuration")])]),a("li",[a("a",{attrs:{href:"#using-the-configuration"}},[t._v("Using the configuration")]),a("ul",[a("li",[a("a",{attrs:{href:"#getting-a-value"}},[t._v("Getting a value")])]),a("li",[a("a",{attrs:{href:"#setting-a-value"}},[t._v("Setting a value")])])])]),a("li",[a("a",{attrs:{href:"#custom-config-entries"}},[t._v("Custom config entries")])]),a("li",[a("a",{attrs:{href:"#configuration-reference"}},[t._v("Configuration reference")])]),a("li",[a("a",{attrs:{href:"#setting-up-https"}},[t._v("Setting up HTTPS")])])])]),a("p"),t._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[t._v("The Goyave framework lets you configure its core and your application.\nTo configure your application, use the "),a("code",[t._v("config.json")]),t._v(" file at your project's root. If you are using the template project, copy "),a("code",[t._v("config.example.json")]),t._v(" to "),a("code",[t._v("config.json")]),t._v(". "),a("code",[t._v("config.json")]),t._v(" should be ignored in your "),a("code",[t._v(".gitignore")]),t._v(" file as it can differ from one developer to another. To avoid accidental commit or change to the default project's config, it is a good practice to ignore this file and define the project's default config in "),a("code",[t._v("config.example.json")]),t._v(".")]),t._v(" "),a("p",[t._v("If this config file misses some config entries, the default values will be used. All values from the framework's core are "),a("strong",[t._v("validated")]),t._v(". 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)."),a("br"),t._v("\nSee the "),a("a",{attrs:{href:"#configuration-reference"}},[t._v("configuration reference")]),t._v(" for more details.")]),t._v(" "),a("h2",{attrs:{id:"environment-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#environment-configuration"}},[t._v("#")]),t._v(" Environment configuration")]),t._v(" "),a("p",[t._v("Most projects need different configuration values based on the environment. For example, you won't connect to the same database if you're in local development, in a testing environment inside continuous integration pipelines, or in production. Goyave supports multiple configurations and will pick the appropriate one depending on the environment variable "),a("code",[t._v("GOYAVE_ENV")]),t._v(".")]),t._v(" "),a("p",[t._v("Since "),a("code",[t._v("v2.0.0")]),t._v(", you can use custom environments.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("GOYAVE_ENV")]),t._v(" "),a("th",[t._v("Config file")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[t._v("test")]),t._v(" "),a("td",[a("code",[t._v("config.test.json")])])]),t._v(" "),a("tr",[a("td",[t._v("production")]),t._v(" "),a("td",[a("code",[t._v("config.production.json")])])]),t._v(" "),a("tr",[a("td",[a("em",[t._v("custom_env")])]),t._v(" "),a("td",[a("code",[t._v("config.custom_env.json")])])]),t._v(" "),a("tr",[a("td",[t._v("local / localhost / "),a("em",[t._v("not set")])]),t._v(" "),a("td",[a("code",[t._v("config.json")])])])])]),t._v(" "),a("h2",{attrs:{id:"using-the-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#using-the-configuration"}},[t._v("#")]),t._v(" Using the configuration")]),t._v(" "),a("p",[t._v("Before being able to use the config, import the config package:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2/config"')]),t._v("\n")])])]),a("p",[t._v("The configuration is loaded automatically when the server starts, but you can reload it manually if needed.")]),t._v(" "),a("h4",{attrs:{id:"config-load"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-load"}},[t._v("#")]),t._v(" config.Load")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td"),t._v(" "),a("td",[a("code",[t._v("error")])])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Load")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"getting-a-value"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-a-value"}},[t._v("#")]),t._v(" Getting a value")]),t._v(" "),a("h4",{attrs:{id:"config-get"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-get"}},[t._v("#")]),t._v(" config.Get")]),t._v(" "),a("p",[t._v("Get a generic config entry. You may need to type-assert it before being able to use it. You can do so safely as the config values and types are validated. Panics if the entry doesn't exist.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("key string")])]),t._v(" "),a("td",[a("code",[t._v("interface{}")]),t._v(" or panic")])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"appName"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "goyave"')]),t._v("\n")])])]),a("h4",{attrs:{id:"config-getstring"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-getstring"}},[t._v("#")]),t._v(" config.GetString")]),t._v(" "),a("p",[t._v("Get a string config entry. Panics if the entry doesn't exist or is not a string.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("key string")])]),t._v(" "),a("td",[a("code",[t._v("string")]),t._v(" or panic")])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"protocol"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// "http"')]),t._v("\n")])])]),a("h4",{attrs:{id:"config-getbool"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-getbool"}},[t._v("#")]),t._v(" config.GetBool")]),t._v(" "),a("p",[t._v("Get a bool config entry. Panics if the entry doesn't exist or is not a bool.")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("key string")])]),t._v(" "),a("td",[a("code",[t._v("bool")]),t._v(" or panic")])])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetBool")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"debug"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n")])])]),a("h3",{attrs:{id:"setting-a-value"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#setting-a-value"}},[t._v("#")]),t._v(" Setting a value")]),t._v(" "),a("p",[t._v("You can set a config value at runtime with the "),a("code",[t._v("config.Set(key, value)")]),t._v(" function. Bear in mind that this change "),a("strong",[t._v("temporary")]),t._v(" and will be lost after your application restarts or if the config is reloaded. This function is mainly used for testing purposes. Values set using this function are still being validated, and your application will panic if the validation doesn't pass.")]),t._v(" "),a("h4",{attrs:{id:"config-set"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#config-set"}},[t._v("#")]),t._v(" config.Set")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Parameters")]),t._v(" "),a("th",[t._v("Return")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[a("code",[t._v("key string")])]),t._v(" "),a("td",[a("code",[t._v("void")]),t._v(" or panic")])]),t._v(" "),a("tr",[a("td",[a("code",[t._v("value interface{}")])]),t._v(" "),a("td")])])]),t._v(" "),a("p",[a("strong",[t._v("Example:")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Set")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"appName"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my awesome app"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"custom-config-entries"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#custom-config-entries"}},[t._v("#")]),t._v(" Custom config entries")]),t._v(" "),a("p",[t._v("The core of the framework contains default values covering most cases, but you can still add custom entries for your most specific needs to the config simply by appending a property to your application's config file. The custom properties are not validated, so you can use the data type you want.")]),t._v(" "),a("h2",{attrs:{id:"configuration-reference"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#configuration-reference"}},[t._v("#")]),t._v(" Configuration reference")]),t._v(" "),a("table",[a("thead",[a("tr",[a("th",[t._v("Entry")]),t._v(" "),a("th",[t._v("Type")]),t._v(" "),a("th",[t._v("Accepted values")]),t._v(" "),a("th",[t._v("Default")]),t._v(" "),a("th",[t._v("Note")])])]),t._v(" "),a("tbody",[a("tr",[a("td",[t._v("appName")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"goyave"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("environment")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"localhost"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("maintenance")]),t._v(" "),a("td",[a("code",[t._v("bool")])]),t._v(" "),a("td",[a("code",[t._v("true")]),t._v(", "),a("code",[t._v("false")])]),t._v(" "),a("td",[a("code",[t._v("false")])]),t._v(" "),a("td",[t._v("If "),a("code",[t._v("true")]),t._v(", start the server in maintenance mode. (Always return HTTP 503)")])]),t._v(" "),a("tr",[a("td",[t._v("host")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"127.0.0.1"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("port")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("8080")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("httpsPort")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("8081")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("protocol")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v('"http", "https"')]),t._v(" "),a("td",[t._v('"http"')]),t._v(" "),a("td",[t._v("See the "),a("a",{attrs:{href:"#setting-up-https"}},[t._v("HTTPS")]),t._v(" section")])]),t._v(" "),a("tr",[a("td",[t._v("tlsCert")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v("none")]),t._v(" "),a("td",[t._v("Path to your TLS cert")])]),t._v(" "),a("tr",[a("td",[t._v("tlsKey")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v("none")]),t._v(" "),a("td",[t._v("Path to your TLS key")])]),t._v(" "),a("tr",[a("td",[t._v("debug")]),t._v(" "),a("td",[a("code",[t._v("bool")])]),t._v(" "),a("td",[a("code",[t._v("true")]),t._v(", "),a("code",[t._v("false")])]),t._v(" "),a("td",[a("code",[t._v("true")])]),t._v(" "),a("td",[t._v("When activated, print stacktrace on error and sends error message in response. "),a("strong",[t._v("Disable this in production!")])])]),t._v(" "),a("tr",[a("td",[t._v("timeout")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("10")])]),t._v(" "),a("td",[t._v("Timeout in seconds")])]),t._v(" "),a("tr",[a("td",[t._v("maxUploadSize")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("10")])]),t._v(" "),a("td",[t._v("Max "),a("strong",[t._v("in-memory")]),t._v(" files sent in the request, in MiB")])]),t._v(" "),a("tr",[a("td",[t._v("defaultLanguage")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"en-US"')]),t._v(" "),a("td",[t._v("See the "),a("router-link",{attrs:{to:"/guide/advanced/localization.html"}},[t._v("Localization")]),t._v(" guide")],1)]),t._v(" "),a("tr",[a("td",[t._v("dbConnection")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v('"none", "mysql", "postgres", "sqlite3", "mssql"')]),t._v(" "),a("td",[t._v('"none"')]),t._v(" "),a("td",[t._v("See the "),a("router-link",{attrs:{to:"/guide/basics/database.html"}},[t._v("Database")]),t._v(" guide")],1)]),t._v(" "),a("tr",[a("td",[t._v("dbHost")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"127.0.0.1"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbPort")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("3306")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbName")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"goyave"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbUsername")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"root"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbPassword")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"root"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbOptions")]),t._v(" "),a("td",[a("code",[t._v("string")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[t._v('"charset=utf8&parseTime=true&loc=Local"')]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbMaxOpenConnections")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("100")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbMaxIdleConnections")]),t._v(" "),a("td",[a("code",[t._v("float64")])]),t._v(" "),a("td",[t._v("any")]),t._v(" "),a("td",[a("code",[t._v("20")])]),t._v(" "),a("td")]),t._v(" "),a("tr",[a("td",[t._v("dbAutoMigrate")]),t._v(" "),a("td",[a("code",[t._v("bool")])]),t._v(" "),a("td",[a("code",[t._v("true")]),t._v(", "),a("code",[t._v("false")])]),t._v(" "),a("td",[a("code",[t._v("false")])]),t._v(" "),a("td",[t._v("When activated, migrate all registered models at startup")])])])]),t._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[t._v("Note")]),t._v(" "),a("p",[t._v("Numeric values are parsed as "),a("code",[t._v("float64")]),t._v(" even if they are supposed to be integers so it covers the potential use-case of floats in the config.")])]),t._v(" "),a("h2",{attrs:{id:"setting-up-https"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#setting-up-https"}},[t._v("#")]),t._v(" Setting up HTTPS")]),t._v(" "),a("p",[t._v("Setting up HTTPS on your Goyave application is easy. First, turn "),a("code",[t._v("protocol")]),t._v(" to "),a("code",[t._v("https")]),t._v(" in the config. Then, add the "),a("code",[t._v("tlsCert")]),t._v(" and "),a("code",[t._v("tlsKey")]),t._v(" entries in the config. These two entries represent respectively the path to your TLS certificate and your TLS key.")]),t._v(" "),a("p",[a("strong",[t._v("Certbot example:")])]),t._v(" "),a("div",{staticClass:"language-json extra-class"},[a("pre",{pre:!0,attrs:{class:"language-json"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ...\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"protocol"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"https"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"tlsCert"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/etc/letsencrypt/live/mydomain.com/cert.pem"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"tlsKey"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/etc/letsencrypt/live/mydomain.com/privkey.pem"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n ...\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Restart your server and you should now be able to connect securely to your Goyave application! All HTTP requests will automatically be redirected to HTTPS.")])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/24.1a71d20e.js b/docs/assets/js/24.8bae4600.js similarity index 94% rename from docs/assets/js/24.1a71d20e.js rename to docs/assets/js/24.8bae4600.js index d9317888..b41fc381 100644 --- a/docs/assets/js/24.1a71d20e.js +++ b/docs/assets/js/24.8bae4600.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{223:function(e,t,o){"use strict";o.r(t);var a=o(0),n=Object(a.a)({},(function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[o("h1",{attrs:{id:"contributing-to-goyave"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#contributing-to-goyave"}},[e._v("#")]),e._v(" Contributing to Goyave")]),e._v(" "),o("p",[e._v("Thank you very much for your time contributing to the Goyave framework!")]),e._v(" "),o("ul",[o("li",[e._v("When reporting an "),o("a",{attrs:{href:"https://github.com/System-Glitch/goyave/issues/new/choose",target:"_blank",rel:"noopener noreferrer"}},[e._v("issue"),o("OutboundLink")],1),e._v(", please use one of the available issue templates.")]),e._v(" "),o("li",[e._v("For pull requests, please use the pull request template and select the "),o("code",[e._v("develop")]),e._v(" branch as target branch.\n"),o("ul",[o("li",[e._v("Ensure that the submitted code works, is documented, respects the "),o("a",{attrs:{href:"https://golang.org/doc/effective_go.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Golang coding style"),o("OutboundLink")],1),e._v(" and is covered by tests. All new pull requests will be automatically tested.")]),e._v(" "),o("li",[e._v("Update the documentation if needed.")])])])]),e._v(" "),o("h2",{attrs:{id:"financial-support"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#financial-support"}},[e._v("#")]),e._v(" Financial support")]),e._v(" "),o("p",[e._v("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.")]),e._v(" "),o("p",[e._v("You can support me on Patreon.")]),e._v(" "),o("p",[o("a",{attrs:{href:"https://www.patreon.com/bePatron?u=25997573","data-patreon-widget-type":"become-patron-button"}},[e._v("Become a Patron!")]),o("script",{attrs:{async:"",src:"https://c6.patreon.com/becomePatronButton.bundle.js"}})])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{222:function(e,t,o){"use strict";o.r(t);var a=o(0),n=Object(a.a)({},(function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[o("h1",{attrs:{id:"contributing-to-goyave"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#contributing-to-goyave"}},[e._v("#")]),e._v(" Contributing to Goyave")]),e._v(" "),o("p",[e._v("Thank you very much for your time contributing to the Goyave framework!")]),e._v(" "),o("ul",[o("li",[e._v("When reporting an "),o("a",{attrs:{href:"https://github.com/System-Glitch/goyave/issues/new/choose",target:"_blank",rel:"noopener noreferrer"}},[e._v("issue"),o("OutboundLink")],1),e._v(", please use one of the available issue templates.")]),e._v(" "),o("li",[e._v("For pull requests, please use the pull request template and select the "),o("code",[e._v("develop")]),e._v(" branch as target branch.\n"),o("ul",[o("li",[e._v("Ensure that the submitted code works, is documented, respects the "),o("a",{attrs:{href:"https://golang.org/doc/effective_go.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Golang coding style"),o("OutboundLink")],1),e._v(" and is covered by tests. All new pull requests will be automatically tested.")]),e._v(" "),o("li",[e._v("Update the documentation if needed.")])])])]),e._v(" "),o("h2",{attrs:{id:"financial-support"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#financial-support"}},[e._v("#")]),e._v(" Financial support")]),e._v(" "),o("p",[e._v("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.")]),e._v(" "),o("p",[e._v("You can support me on Patreon.")]),e._v(" "),o("p",[o("a",{attrs:{href:"https://www.patreon.com/bePatron?u=25997573","data-patreon-widget-type":"become-patron-button"}},[e._v("Become a Patron!")]),o("script",{attrs:{async:"",src:"https://c6.patreon.com/becomePatronButton.bundle.js"}})])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/25.0c60f0d9.js b/docs/assets/js/25.0c60f0d9.js deleted file mode 100644 index bc09ef2e..00000000 --- a/docs/assets/js/25.0c60f0d9.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{224:function(e,t,a){"use strict";a.r(t);var o=a(0),n=Object(o.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"deployment"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#deployment"}},[e._v("#")]),e._v(" Deployment")]),e._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[e._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#application-configuration"}},[e._v("Application configuration")])]),a("li",[a("a",{attrs:{href:"#build"}},[e._v("Build")])]),a("li",[a("a",{attrs:{href:"#deamon"}},[e._v("Deamon")]),a("ul",[a("li",[a("a",{attrs:{href:"#systemd"}},[e._v("Systemd")])])])])])]),a("p"),e._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),a("p",[e._v("There are some important details to think about before deploying your Goyave application to production. We are going to cover them in this section of the guide, and make sure your applications are deployed properly.")]),e._v(" "),a("h2",{attrs:{id:"application-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#application-configuration"}},[e._v("#")]),e._v(" Application configuration")]),e._v(" "),a("p",[e._v("Be sure to deploy your application with a "),a("code",[e._v("config.production.json")]),e._v(" config file containing the correct values for your production environment and "),a("strong",[e._v("set the "),a("code",[e._v("GOYAVE_ENV")]),e._v(" environment variable to "),a("code",[e._v("production")]),e._v(".")])]),e._v(" "),a("ol",[a("li",[e._v("Ensure that the "),a("code",[e._v("environment")]),e._v(" entry is "),a("code",[e._v("production")]),e._v(".")]),e._v(" "),a("li",[e._v("The "),a("code",[e._v("host")]),e._v(" entry should be "),a("code",[e._v("0.0.0.0")]),e._v(" or your domain name.")]),e._v(" "),a("li",[e._v("The "),a("code",[e._v("port")]),e._v(" and "),a("code",[e._v("httpsPort")]),e._v(" will very likely require a change. Most of the time, you need "),a("code",[e._v("80")]),e._v(" and "),a("code",[e._v("443")]),e._v(" respectively.")]),e._v(" "),a("li",[e._v("If you use "),a("code",[e._v("https")]),e._v(", be sure to provide the paths to your "),a("code",[e._v("tlsCert")]),e._v(" and "),a("code",[e._v("tlsKey")]),e._v(". Learn more "),a("router-link",{attrs:{to:"/guide/configuration.html#setting-up-https"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("li",[a("code",[e._v("debug")]),e._v(" "),a("strong",[e._v("must")]),e._v(" be set do "),a("code",[e._v("false")]),e._v(". You don't want anyone to get important information about your internal errors and therefore your code when an error occurs.")]),e._v(" "),a("li",[e._v("Change your database connection credentials. "),a("code",[e._v("dbAutoMigrate")]),e._v(" should be set to "),a("code",[e._v("false")]),e._v(".")])]),e._v(" "),a("h2",{attrs:{id:"build"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#build"}},[e._v("#")]),e._v(" Build")]),e._v(" "),a("p",[e._v("Of course, don't run your application with "),a("code",[e._v("go run")]),e._v(" in production. Build your application using "),a("code",[e._v("go build")]),e._v(" and deploy the executable, alongside the config files and resources directory.")]),e._v(" "),a("h2",{attrs:{id:"deamon"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#deamon"}},[e._v("#")]),e._v(" Deamon")]),e._v(" "),a("p",[e._v("Goyave applications are standalone and don't require any web server (such as Apache or Nginx) to function. However, this also means that you will need some additional installation steps on your production server.")]),e._v(" "),a("p",[e._v("When running a web service, it is important that it stays online. Creating a "),a("strong",[e._v("deamon")]),e._v(" is necessary so your server can run in the background, have the correct filesystem permissions, and restart automatically after a crash or a reboot.")]),e._v(" "),a("p",[e._v("You can achieve this with any supervisor program, but in this guide, we will use systemd as it's the most common one.")]),e._v(" "),a("h3",{attrs:{id:"systemd"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#systemd"}},[e._v("#")]),e._v(" Systemd")]),e._v(" "),a("p",[e._v("First, we need to create a user and its group for our application:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("sudo addgroup goyave\nsudo useradd -r -s /bin/false goyave\nsudo usermod -a -G goyave goyave\n")])])]),a("p",[e._v("You may use the following systemd unit file to deploy your Goyave application:")]),e._v(" "),a("p",[a("code",[e._v("/etc/systemd/system/my-goyave-application.service")]),e._v(":")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('[Unit]\nDescription=Goyave application deamon\n\n# If you are using a database, mysql for example, make sure the application\n# service starts AFTER the database service.\n# After=mysqld.service\nAfter=network.target\nStartLimitIntervalSec=0\n\n[Service]\nEnvironment=GOYAVE_ENV=production\nWorkingDirectory=/path/to/goyave-application\nExecStart=/path/to/goyave-application/executable\n\n# Process management\n####################\n\nType=simple\n\n# Can be changed to "on-failure"\nRestart=always\nRestartSec=1\nTimeoutStopSec=600\n\n# Run as goyave:goyave\nUser=goyave\nGroup=goyave\n\n# Hardening measures\n####################\n\n# Provide a private /tmp and /var/tmp.\nPrivateTmp=true\n\n# Mount /usr, /boot/ and /etc read-only for the process.\nProtectSystem=full\n\n# Deny access to /home, /root and /run/user\nProtectHome=true\n\n# Disallow the process and all of its children to gain\n# new privileges through execve().\nNoNewPrivileges=true\n\n# Use a new /dev namespace only populated with API pseudo devices\n# such as /dev/null, /dev/zero and /dev/random.\nPrivateDevices=true\n\n# Deny the creation of writable and executable memory mappings.\nMemoryDenyWriteExecute=true\n\n[Install]\nWantedBy=multi-user.target\n')])])]),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[e._v("WARNING")]),e._v(" "),a("p",[e._v("Replace "),a("code",[e._v("my-goyave-application")]),e._v(" with the name of your application and "),a("code",[e._v("/path/to/goyave-application")]),e._v(" with the "),a("strong",[e._v("absolute")]),e._v(" path to your application. This is important to have unique application names in case you run multiple goyave applications on the same server. You should also create a separate user and group for each application.")])]),e._v(" "),a("p",[e._v("Now let's run the service and enable it on system startup:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("sudo systemctl start my-goyave-application\nsudo systemctl enable my-goyave-application\n")])])])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/25.2afa8687.js b/docs/assets/js/25.2afa8687.js new file mode 100644 index 00000000..1767d466 --- /dev/null +++ b/docs/assets/js/25.2afa8687.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{223:function(e,t,a){"use strict";a.r(t);var o=a(0),n=Object(o.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"deployment"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#deployment"}},[e._v("#")]),e._v(" Deployment")]),e._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#introduction"}},[e._v("Introduction")])]),a("li",[a("a",{attrs:{href:"#application-configuration"}},[e._v("Application configuration")])]),a("li",[a("a",{attrs:{href:"#build"}},[e._v("Build")])]),a("li",[a("a",{attrs:{href:"#deamon"}},[e._v("Deamon")]),a("ul",[a("li",[a("a",{attrs:{href:"#systemd"}},[e._v("Systemd")])])])])])]),a("p"),e._v(" "),a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),a("p",[e._v("There are some important details to think about before deploying your Goyave application to production. We are going to cover them in this section of the guide, and make sure your applications are deployed properly.")]),e._v(" "),a("h2",{attrs:{id:"application-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#application-configuration"}},[e._v("#")]),e._v(" Application configuration")]),e._v(" "),a("p",[e._v("Be sure to deploy your application with a "),a("code",[e._v("config.production.json")]),e._v(" config file containing the correct values for your production environment and "),a("strong",[e._v("set the "),a("code",[e._v("GOYAVE_ENV")]),e._v(" environment variable to "),a("code",[e._v("production")]),e._v(".")])]),e._v(" "),a("ol",[a("li",[e._v("Ensure that the "),a("code",[e._v("environment")]),e._v(" entry is "),a("code",[e._v("production")]),e._v(".")]),e._v(" "),a("li",[e._v("The "),a("code",[e._v("host")]),e._v(" entry should be "),a("code",[e._v("0.0.0.0")]),e._v(" if you want let open access to your service. If you're using Apache or Nginx as a proxy on the same machine, keep it at "),a("code",[e._v("127.0.0.1")]),e._v(" so the server will only be accessible through the proxy.")]),e._v(" "),a("li",[e._v("The "),a("code",[e._v("port")]),e._v(" and "),a("code",[e._v("httpsPort")]),e._v(" will very likely require a change. Most of the time, you need "),a("code",[e._v("80")]),e._v(" and "),a("code",[e._v("443")]),e._v(" respectively.")]),e._v(" "),a("li",[e._v("If you use "),a("code",[e._v("https")]),e._v(", be sure to provide the paths to your "),a("code",[e._v("tlsCert")]),e._v(" and "),a("code",[e._v("tlsKey")]),e._v(". Learn more "),a("router-link",{attrs:{to:"/guide/configuration.html#setting-up-https"}},[e._v("here")]),e._v(".")],1),e._v(" "),a("li",[a("code",[e._v("debug")]),e._v(" "),a("strong",[e._v("must")]),e._v(" be set do "),a("code",[e._v("false")]),e._v(". You don't want anyone to get important information about your internal errors and therefore your code when an error occurs.")]),e._v(" "),a("li",[e._v("Change your database connection credentials. "),a("code",[e._v("dbAutoMigrate")]),e._v(" should be set to "),a("code",[e._v("false")]),e._v(".")])]),e._v(" "),a("h2",{attrs:{id:"build"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#build"}},[e._v("#")]),e._v(" Build")]),e._v(" "),a("p",[e._v("Of course, don't run your application with "),a("code",[e._v("go run")]),e._v(" in production. Build your application using "),a("code",[e._v("go build")]),e._v(" and deploy the executable, alongside the config files and resources directory.")]),e._v(" "),a("h2",{attrs:{id:"deamon"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#deamon"}},[e._v("#")]),e._v(" Deamon")]),e._v(" "),a("p",[e._v("Goyave applications are standalone and don't require any web server (such as Apache or Nginx) to function. However, this also means that you will need some additional installation steps on your production server.")]),e._v(" "),a("p",[e._v("When running a web service, it is important that it stays online. Creating a "),a("strong",[e._v("deamon")]),e._v(" is necessary so your server can run in the background, have the correct filesystem permissions, and restart automatically after a crash or a reboot.")]),e._v(" "),a("p",[e._v("You can achieve this with any supervisor program, but in this guide, we will use systemd as it's the most common one.")]),e._v(" "),a("h3",{attrs:{id:"systemd"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#systemd"}},[e._v("#")]),e._v(" Systemd")]),e._v(" "),a("p",[e._v("First, we need to create a user and its group for our application:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("sudo addgroup goyave\nsudo useradd -r -s /bin/false goyave\nsudo usermod -a -G goyave goyave\n")])])]),a("p",[e._v("You may use the following systemd unit file to deploy your Goyave application:")]),e._v(" "),a("p",[a("code",[e._v("/etc/systemd/system/my-goyave-application.service")]),e._v(":")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('[Unit]\nDescription=Goyave application deamon\n\n# If you are using a database, mysql for example, make sure the application\n# service starts AFTER the database service.\n# After=mysqld.service\nAfter=network.target\nStartLimitIntervalSec=0\n\n[Service]\nEnvironment=GOYAVE_ENV=production\nWorkingDirectory=/path/to/goyave-application\nExecStart=/path/to/goyave-application/executable\n\n# Process management\n####################\n\nType=simple\n\n# Can be changed to "on-failure"\nRestart=always\nRestartSec=1\nTimeoutStopSec=600\n\n# Run as goyave:goyave\nUser=goyave\nGroup=goyave\n\n# Hardening measures\n####################\n\n# Provide a private /tmp and /var/tmp.\nPrivateTmp=true\n\n# Mount /usr, /boot/ and /etc read-only for the process.\nProtectSystem=full\n\n# Deny access to /home, /root and /run/user\nProtectHome=true\n\n# Disallow the process and all of its children to gain\n# new privileges through execve().\nNoNewPrivileges=true\n\n# Use a new /dev namespace only populated with API pseudo devices\n# such as /dev/null, /dev/zero and /dev/random.\nPrivateDevices=true\n\n# Deny the creation of writable and executable memory mappings.\nMemoryDenyWriteExecute=true\n\n[Install]\nWantedBy=multi-user.target\n')])])]),a("div",{staticClass:"custom-block warning"},[a("p",{staticClass:"custom-block-title"},[e._v("WARNING")]),e._v(" "),a("p",[e._v("Replace "),a("code",[e._v("my-goyave-application")]),e._v(" with the name of your application and "),a("code",[e._v("/path/to/goyave-application")]),e._v(" with the "),a("strong",[e._v("absolute")]),e._v(" path to your application. This is important to have unique application names in case you run multiple goyave applications on the same server. You should also create a separate user and group for each application.")])]),e._v(" "),a("p",[e._v("Now let's run the service and enable it on system startup:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("sudo systemctl start my-goyave-application\nsudo systemctl enable my-goyave-application\n")])])])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/26.afbc7c7d.js b/docs/assets/js/26.afbc7c7d.js deleted file mode 100644 index 40010216..00000000 --- a/docs/assets/js/26.afbc7c7d.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{225:function(t,e,s){"use strict";s.r(e);var a=s(0),r=Object(a.a)({},(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"installation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#installation"}},[t._v("#")]),t._v(" Installation")]),t._v(" "),s("p",[t._v("This guide will walk you through the installation process. The rest of the guide assumes you are using the template project, as it is the recommended option.")]),t._v(" "),s("h2",{attrs:{id:"requirements"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#requirements"}},[t._v("#")]),t._v(" Requirements")]),t._v(" "),s("ul",[s("li",[t._v("Go 1.13+")]),t._v(" "),s("li",[t._v("Go modules")])]),t._v(" "),s("h2",{attrs:{id:"template-project"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#template-project"}},[t._v("#")]),t._v(" Template project")]),t._v(" "),s("p",[t._v("You can bootstrap your project using the "),s("strong",[s("a",{attrs:{href:"https://github.com/System-Glitch/goyave-template",target:"_blank",rel:"noopener noreferrer"}},[t._v("Goyave template project"),s("OutboundLink")],1)]),t._v(". This project has a complete directory structure already set up for you.")]),t._v(" "),s("h4",{attrs:{id:"linux-macos"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#linux-macos"}},[t._v("#")]),t._v(" Linux / MacOS")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ curl https://raw.githubusercontent.com/System-Glitch/goyave/master/install.sh | bash -s my-project\n")])])]),s("h4",{attrs:{id:"windows-powershell"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#windows-powershell"}},[t._v("#")]),t._v(" Windows (Powershell)")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('> & ([scriptblock]::Create((curl "https://raw.githubusercontent.com/System-Glitch/goyave/master/install.ps1").Content)) -projectName my-project\n')])])]),s("hr"),t._v(" "),s("p",[t._v("Run "),s("code",[t._v("go run my-project")]),t._v(" in your project's directory to start the server, then try to request the "),s("code",[t._v("hello")]),t._v(" route.")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ curl http://localhost:8080/hello\nHi!\n")])])]),s("h2",{attrs:{id:"from-scratch"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#from-scratch"}},[t._v("#")]),t._v(" From scratch")]),t._v(" "),s("div",{staticClass:"custom-block warning"},[s("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),s("p",[t._v("Installing your project from scratch is not recommended as you will likely not use the same directory structure as the template project. Respecting the standard "),s("router-link",{attrs:{to:"/guide/architecture-concepts.html#directory-structure"}},[t._v("directory structure")]),t._v(" is important and helps keeping a consistent environment across the Goyave applications.")],1)]),t._v(" "),s("p",[t._v("If you prefer to setup your project from scratch, for example if you don't plan on using some of the framework's features or if you want to use a different directory structure, you can!")]),t._v(" "),s("p",[t._v("In a terminal, run:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ mkdir myproject && cd myproject\n$ go mod init my-project\n$ go get -u github.com/System-Glitch/goyave/v2\n")])])]),s("p",[t._v("Now that your project directory is set up and the dependencies are installed, let's start with the program entry point, "),s("code",[t._v("kernel.go")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my-project/http/route"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Start")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("route"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[s("code",[t._v("goyave.Start()")]),t._v(" is blocking. You can run it in a goroutine if you want to process other things in the background. See the "),s("router-link",{attrs:{to:"/guide/advanced/multi-services.html"}},[t._v("multi-services")]),t._v(" section for more details.")],1)]),t._v(" "),s("p",[t._v("Now we need to create the package in which we will register our routes. Create a new package "),s("code",[t._v("http/route")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ mkdir http\n$ mkdir http/route\n")])])]),s("p",[t._v("Create "),s("code",[t._v("http/route/route.go")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" routes\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Register all the routes")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\trouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/hello"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" hello"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Handler function for the "/hello" route')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("hello")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tresponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hi!"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v('Here we registered a very simple route displaying "Hi!". Learn more about routing '),s("router-link",{attrs:{to:"/guide/basics/routing.html"}},[t._v("here")]),t._v(".")],1),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("Your routes definitions should be separated from the handler functions. Handlers should be defined in a "),s("code",[t._v("http/controller")]),t._v(" directory.")])]),t._v(" "),s("p",[t._v("Run your server and request your route:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ go run my-project\n\n# In another terminal:\n$ curl http://localhost:8080/hello\nHi!\n")])])]),s("p",[t._v("You should also create a config file for your application. Learn more "),s("router-link",{attrs:{to:"/guide/configuration.html"}},[t._v("here")]),t._v(".")],1),t._v(" "),s("p",[t._v("It is a good practice to ignore the actual config to prevent it being added to the version control system. Each developer may have different settings for their environment. To do so, add "),s("code",[t._v("config.json")]),t._v(" to your "),s("code",[t._v(".gitignore")]),t._v(".")])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/26.fc20a042.js b/docs/assets/js/26.fc20a042.js new file mode 100644 index 00000000..3d6b6ecc --- /dev/null +++ b/docs/assets/js/26.fc20a042.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{224:function(t,e,s){"use strict";s.r(e);var a=s(0),r=Object(a.a)({},(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"installation"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#installation"}},[t._v("#")]),t._v(" Installation")]),t._v(" "),s("p",[t._v("This guide will walk you through the installation process. The rest of the guide assumes you are using the template project, as it is the recommended option.")]),t._v(" "),s("h2",{attrs:{id:"requirements"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#requirements"}},[t._v("#")]),t._v(" Requirements")]),t._v(" "),s("ul",[s("li",[t._v("Go 1.13+")]),t._v(" "),s("li",[t._v("Go modules")])]),t._v(" "),s("h2",{attrs:{id:"template-project"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#template-project"}},[t._v("#")]),t._v(" Template project")]),t._v(" "),s("p",[t._v("You can bootstrap your project using the "),s("strong",[s("a",{attrs:{href:"https://github.com/System-Glitch/goyave-template",target:"_blank",rel:"noopener noreferrer"}},[t._v("Goyave template project"),s("OutboundLink")],1)]),t._v(". This project has a complete directory structure already set up for you.")]),t._v(" "),s("h4",{attrs:{id:"linux-macos"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#linux-macos"}},[t._v("#")]),t._v(" Linux / MacOS")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ curl https://raw.githubusercontent.com/System-Glitch/goyave/master/install.sh | bash -s my-project\n")])])]),s("h4",{attrs:{id:"windows-powershell"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#windows-powershell"}},[t._v("#")]),t._v(" Windows (Powershell)")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v('> & ([scriptblock]::Create((curl "https://raw.githubusercontent.com/System-Glitch/goyave/master/install.ps1").Content)) -projectName my-project\n')])])]),s("hr"),t._v(" "),s("p",[t._v("Run "),s("code",[t._v("go run my-project")]),t._v(" in your project's directory to start the server, then try to request the "),s("code",[t._v("hello")]),t._v(" route.")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ curl http://localhost:8080/hello\nHi!\n")])])]),s("p",[t._v("There is also an "),s("code",[t._v("echo")]),t._v(" route, with basic validation of query parameters.")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ curl http://localhost:8080/echo?text=abc%20123\nabc 123\n")])])]),s("h2",{attrs:{id:"from-scratch"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#from-scratch"}},[t._v("#")]),t._v(" From scratch")]),t._v(" "),s("div",{staticClass:"custom-block warning"},[s("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),s("p",[t._v("Installing your project from scratch is not recommended as you will likely not use the same directory structure as the template project. Respecting the standard "),s("router-link",{attrs:{to:"/guide/architecture-concepts.html#directory-structure"}},[t._v("directory structure")]),t._v(" is important and helps keeping a consistent environment across the Goyave applications.")],1)]),t._v(" "),s("p",[t._v("If you prefer to setup your project from scratch, for example if you don't plan on using some of the framework's features or if you want to use a different directory structure, you can!")]),t._v(" "),s("p",[t._v("In a terminal, run:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ mkdir myproject && cd myproject\n$ go mod init my-project\n$ go get -u github.com/System-Glitch/goyave/v2\n")])])]),s("p",[t._v("Now that your project directory is set up and the dependencies are installed, let's start with the program entry point, "),s("code",[t._v("kernel.go")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"my-project/http/route"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Start")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("route"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Register"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[s("code",[t._v("goyave.Start()")]),t._v(" is blocking. You can run it in a goroutine if you want to process other things in the background. See the "),s("router-link",{attrs:{to:"/guide/advanced/multi-services.html"}},[t._v("multi-services")]),t._v(" section for more details.")],1)]),t._v(" "),s("p",[t._v("Now we need to create the package in which we will register our routes. Create a new package "),s("code",[t._v("http/route")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ mkdir http\n$ mkdir http/route\n")])])]),s("p",[t._v("Create "),s("code",[t._v("http/route/route.go")]),t._v(":")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" routes\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/System-Glitch/goyave/v2"')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Register all the routes")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("router "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Router"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\trouter"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Route")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GET"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/hello"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" hello"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Handler function for the "/hello" route')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("hello")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("response "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Response"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" request "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("goyave"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tresponse"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("StatusOK"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hi!"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v('Here we registered a very simple route displaying "Hi!". Learn more about routing '),s("router-link",{attrs:{to:"/guide/basics/routing.html"}},[t._v("here")]),t._v(".")],1),t._v(" "),s("div",{staticClass:"custom-block tip"},[s("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),s("p",[t._v("Your routes definitions should be separated from the handler functions. Handlers should be defined in a "),s("code",[t._v("http/controller")]),t._v(" directory.")])]),t._v(" "),s("p",[t._v("Run your server and request your route:")]),t._v(" "),s("div",{staticClass:"language- extra-class"},[s("pre",{pre:!0,attrs:{class:"language-text"}},[s("code",[t._v("$ go run my-project\n\n# In another terminal:\n$ curl http://localhost:8080/hello\nHi!\n")])])]),s("p",[t._v("You should also create a config file for your application. Learn more "),s("router-link",{attrs:{to:"/guide/configuration.html"}},[t._v("here")]),t._v(".")],1),t._v(" "),s("p",[t._v("It is a good practice to ignore the actual config to prevent it being added to the version control system. Each developer may have different settings for their environment. To do so, add "),s("code",[t._v("config.json")]),t._v(" to your "),s("code",[t._v(".gitignore")]),t._v(".")])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/27.f64d5c03.js b/docs/assets/js/27.81c24ebc.js similarity index 96% rename from docs/assets/js/27.f64d5c03.js rename to docs/assets/js/27.81c24ebc.js index e7a0b48a..f5a375f3 100644 --- a/docs/assets/js/27.f64d5c03.js +++ b/docs/assets/js/27.81c24ebc.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{226:function(e,t,a){"use strict";a.r(t);var o=a(0),s=Object(o.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"upgrade-guide"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#upgrade-guide"}},[e._v("#")]),e._v(" Upgrade Guide")]),e._v(" "),a("p",[e._v("Although Goyave is developed with backwards compatibility, breaking changes can happen, especially in the project's early days. This guide will help you to upgrade your applications using older versions of the framework. Bear in mind that if you are several versions behind, you will have to follow the instructions for each in-between versions.")]),e._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#v1-0-0-to-v2-0-0"}},[e._v("v1.0.0 to v2.0.0")])])])]),a("p"),e._v(" "),a("h2",{attrs:{id:"v1-0-0-to-v2-0-0"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#v1-0-0-to-v2-0-0"}},[e._v("#")]),e._v(" v1.0.0 to v2.0.0")]),e._v(" "),a("p",[e._v("This first update comes with refactoring and package renaming to better fit the Go conventions.")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("goyave.Request.URL()")]),e._v(" has been renamed to "),a("code",[e._v("goyave.Request.URI()")]),e._v(".\n"),a("ul",[a("li",[a("code",[e._v("goyave.Request.URL()")]),e._v(" is now a data accessor for URL fields.")])])]),e._v(" "),a("li",[e._v("The "),a("code",[e._v("helpers")]),e._v(" package has been renamed to "),a("code",[e._v("helper")]),e._v(".\n"),a("ul",[a("li",[e._v("The "),a("code",[e._v("filesystem")]),e._v(" package thus has a different path: "),a("code",[e._v("github.com/System-Glitch/goyave/v2/helper/filesystem")]),e._v(".")])])])]),e._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),a("p",[e._v("Because this version contains breaking changes. Goyave had to move to "),a("code",[e._v("v2.0.0")]),e._v(". You need to change the path of your imports to upgrade.")]),e._v(" "),a("p",[e._v("Change "),a("code",[e._v("github.com/System-Glitch/goyave")]),e._v(" to "),a("code",[e._v("github.com/System-Glitch/goyave/v2")]),e._v(".")])])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{225:function(e,t,a){"use strict";a.r(t);var o=a(0),s=Object(o.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"upgrade-guide"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#upgrade-guide"}},[e._v("#")]),e._v(" Upgrade Guide")]),e._v(" "),a("p",[e._v("Although Goyave is developed with backwards compatibility, breaking changes can happen, especially in the project's early days. This guide will help you to upgrade your applications using older versions of the framework. Bear in mind that if you are several versions behind, you will have to follow the instructions for each in-between versions.")]),e._v(" "),a("p"),a("div",{staticClass:"table-of-contents"},[a("ul",[a("li",[a("a",{attrs:{href:"#v1-0-0-to-v2-0-0"}},[e._v("v1.0.0 to v2.0.0")])])])]),a("p"),e._v(" "),a("h2",{attrs:{id:"v1-0-0-to-v2-0-0"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#v1-0-0-to-v2-0-0"}},[e._v("#")]),e._v(" v1.0.0 to v2.0.0")]),e._v(" "),a("p",[e._v("This first update comes with refactoring and package renaming to better fit the Go conventions.")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("goyave.Request.URL()")]),e._v(" has been renamed to "),a("code",[e._v("goyave.Request.URI()")]),e._v(".\n"),a("ul",[a("li",[a("code",[e._v("goyave.Request.URL()")]),e._v(" is now a data accessor for URL fields.")])])]),e._v(" "),a("li",[e._v("The "),a("code",[e._v("helpers")]),e._v(" package has been renamed to "),a("code",[e._v("helper")]),e._v(".\n"),a("ul",[a("li",[e._v("The "),a("code",[e._v("filesystem")]),e._v(" package thus has a different path: "),a("code",[e._v("github.com/System-Glitch/goyave/v2/helper/filesystem")]),e._v(".")])])])]),e._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),a("p",[e._v("Because this version contains breaking changes. Goyave had to move to "),a("code",[e._v("v2.0.0")]),e._v(". You need to change the path of your imports to upgrade.")]),e._v(" "),a("p",[e._v("Change "),a("code",[e._v("github.com/System-Glitch/goyave")]),e._v(" to "),a("code",[e._v("github.com/System-Glitch/goyave/v2")]),e._v(".")])])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/28.57bb5ec4.js b/docs/assets/js/28.a9f38de4.js similarity index 100% rename from docs/assets/js/28.57bb5ec4.js rename to docs/assets/js/28.a9f38de4.js diff --git a/docs/assets/js/3.e099aa3a.js b/docs/assets/js/3.7dea0142.js similarity index 100% rename from docs/assets/js/3.e099aa3a.js rename to docs/assets/js/3.7dea0142.js diff --git a/docs/assets/js/4.c70817cb.js b/docs/assets/js/4.e651b8a0.js similarity index 100% rename from docs/assets/js/4.c70817cb.js rename to docs/assets/js/4.e651b8a0.js diff --git a/docs/assets/js/5.142fa08f.js b/docs/assets/js/5.911574e0.js similarity index 93% rename from docs/assets/js/5.142fa08f.js rename to docs/assets/js/5.911574e0.js index 9d6923b6..1d36ee11 100644 --- a/docs/assets/js/5.142fa08f.js +++ b/docs/assets/js/5.911574e0.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{210:function(e,a,t){"use strict";t.r(a);var s=t(0),n=Object(s.a)({},(function(){var e=this,a=e.$createElement,t=e._self._c||a;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",{staticClass:"center"},[e._v("\nGoyave is a progressive and accessible web application framework, aimed at making development easy and enjoyable. It has a philosophy of cleanliness and conciseness to make programs more elegant, easier to maintain and more focused.\n")]),e._v(" "),t("div",{staticClass:"features"},[t("div",{staticClass:"feature",attrs:{id:"feature-clean"}},[t("img",{attrs:{src:e.$withBase("/undraw_code_typing_7jnv.svg"),width:"275",alt:"Clean"}}),e._v(" "),t("div",[t("h2",[e._v("Clean Code")]),e._v(" "),t("p",[e._v("Goyave has an expressive, elegant syntax, a robust structure and conventions. Minimalist calls and reduced redundancy are among the Goyave's core principles.")])])]),e._v(" "),t("div",{staticClass:"feature",attrs:{id:"feature-fast"}},[t("img",{attrs:{src:e.$withBase("/undraw_speed_test_wxl0.svg"),width:"275",alt:"Fast"}}),e._v(" "),t("div",[t("h2",[e._v("Fast Development")]),e._v(" "),t("p",[e._v("Develop faster and concentrate on the business logic of your application thanks to the many helpers and built-in functions.")])])]),e._v(" "),t("div",{staticClass:"feature",attrs:{id:"feature-powerful"}},[t("img",{attrs:{src:e.$withBase("/undraw_upgrade_06a0.svg"),width:"275",alt:"Powerful"}}),e._v(" "),t("div",[t("h2",[e._v("Powerful functionalities")]),e._v(" "),t("p",[e._v("Goyave is accessible, yet powerful. The framework includes routing, request parsing, validation, localization, and more!")])])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{210:function(e,a,t){"use strict";t.r(a);var s=t(0),n=Object(s.a)({},(function(){var e=this,a=e.$createElement,t=e._self._c||a;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",{staticClass:"center"},[e._v("\nGoyave is a progressive and accessible web application framework, aimed at making development easy and enjoyable. It has a philosophy of cleanliness and conciseness to make programs more elegant, easier to maintain and more focused.\n")]),e._v(" "),t("div",{staticClass:"features"},[t("div",{staticClass:"feature",attrs:{id:"feature-clean"}},[t("img",{attrs:{src:e.$withBase("/undraw_code_typing_7jnv.svg"),width:"275",alt:"Clean"}}),e._v(" "),t("div",[t("h2",[e._v("Clean Code")]),e._v(" "),t("p",[e._v("Goyave has an expressive, elegant syntax, a robust structure and conventions. Minimalist calls and reduced redundancy are among the Goyave's core principles.")])])]),e._v(" "),t("div",{staticClass:"feature",attrs:{id:"feature-fast"}},[t("img",{attrs:{src:e.$withBase("/undraw_speed_test_wxl0.svg"),width:"275",alt:"Fast"}}),e._v(" "),t("div",[t("h2",[e._v("Fast Development")]),e._v(" "),t("p",[e._v("Develop faster and concentrate on the business logic of your application thanks to the many helpers and built-in functions.")])])]),e._v(" "),t("div",{staticClass:"feature",attrs:{id:"feature-powerful"}},[t("img",{attrs:{src:e.$withBase("/undraw_upgrade_06a0.svg"),width:"275",alt:"Powerful"}}),e._v(" "),t("div",[t("h2",[e._v("Powerful functionalities")]),e._v(" "),t("p",[e._v("Goyave is accessible, yet powerful. The framework includes routing, request parsing, validation, localization, testing, and more!")])])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/6.26cc1488.js b/docs/assets/js/6.26cc1488.js deleted file mode 100644 index 9eb37424..00000000 --- a/docs/assets/js/6.26cc1488.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{211:function(e,t,r){"use strict";r.r(t);var a=r(0),o=Object(a.a)({},(function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[r("h1",{attrs:{id:"introduction"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),r("p",[e._v("Welcome to the Goyave documentation!")]),e._v(" "),r("p",[e._v("This documentation is both a guide and a reference for Goyave application building. You will find instructions covering the basics as well as more advanced topics, from project setup to deployment. But first, let's talk about the framework itself.")]),e._v(" "),r("p",[e._v("Goyave is a framework aiming at "),r("strong",[e._v("cleanliness")]),e._v(", "),r("strong",[e._v("speed")]),e._v(" and "),r("strong",[e._v("power")]),e._v(". Goyave applications stay clean and concise thanks to minimalist function calls and route handlers. The framework gives you all the tools to create an easily readable and maintainable web application, which let you concentrate on the business logic. Although Goyave handles many things for you, such as headers or marshaling, this characteristic doesn't compromise on your freedom of code.")]),e._v(" "),r("p",[e._v("Most golang frameworks for web development don't have a strong directory structure nor conventions to make applications have a uniform architecture and limit redundancy. This makes it difficult to work with them on different projects. In companies, having a well-defined and documented architecture helps new developers integrate projects faster, and reduces the time needed for maintaining them. For open source projects, it helps newcomers understanding the project and makes it easier to contribute.")]),e._v(" "),r("div",{staticClass:"custom-block tip"},[r("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),r("p",[e._v("Please feel free to sudgest changes, ask for more details, report grammar errors, or notice of uncovered scenarios by "),r("a",{attrs:{href:"https://github.com/System-Glitch/goyave/issues/new/choose",target:"_blank",rel:"noopener noreferrer"}},[e._v("creating an issue"),r("OutboundLink")],1),e._v(" with the proposal template.")])]),e._v(" "),r("h2",{attrs:{id:"roadmap"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#roadmap"}},[e._v("#")]),e._v(" Roadmap")]),e._v(" "),r("div",{staticClass:"img-row left"},[r("img",{attrs:{src:e.$withBase("/undraw_to_do_list_a49b.svg"),height:"150",alt:"Roadmap"}}),r("div",{staticClass:"row-content"},[r("h3",{attrs:{id:"next-release"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#next-release"}},[e._v("#")]),e._v(" Next release")]),e._v(" "),r("ul",[r("li",[e._v("Integrated testing functions")])])])]),r("h3",{attrs:{id:"ideas-for-future-releases"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#ideas-for-future-releases"}},[e._v("#")]),e._v(" Ideas for future releases")]),e._v(" "),r("ul",[r("li",[e._v("Direct support for authentication")]),e._v(" "),r("li",[e._v("Plugins")]),e._v(" "),r("li",[e._v("Improved Gorm integration")]),e._v(" "),r("li",[e._v("CLI utility to help creating controllers, middlewares, etc")]),e._v(" "),r("li",[e._v("Email helpers")]),e._v(" "),r("li",[e._v("Server shutdown hooks (to gracefully close websocket connections for example)")]),e._v(" "),r("li",[e._v("Queues/Scheduler system")]),e._v(" "),r("li",[e._v("Logging")]),e._v(" "),r("li",[e._v("Custom HTTP error handlers (for custom 404/500/... messages)")]),e._v(" "),r("li",[e._v("Named routes, CORS")]),e._v(" "),r("li",[e._v("Placeholders in language lines and pluralization")]),e._v(" "),r("li",[e._v("Support for gzip compression")]),e._v(" "),r("li",[e._v("Direct support for the OPTIONS method")]),e._v(" "),r("li",[e._v("And more!")])]),e._v(" "),r("h2",{attrs:{id:"contributors"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#contributors"}},[e._v("#")]),e._v(" Contributors")]),e._v(" "),r("p",[e._v('A big "Thank you" to the Goyave contributors:')]),e._v(" "),r("ul",[r("li",[r("a",{attrs:{href:"https://github.com/Kuinox",target:"_blank",rel:"noopener noreferrer"}},[e._v("Kuinox"),r("OutboundLink")],1),e._v(" (Powershell install script)")]),e._v(" "),r("li",[r("a",{attrs:{href:"https://github.com/alexandregv",target:"_blank",rel:"noopener noreferrer"}},[e._v("Alexandre GV."),r("OutboundLink")],1),e._v(" (Install script MacOS compatibility)")])])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/6.ffa47bc6.js b/docs/assets/js/6.ffa47bc6.js new file mode 100644 index 00000000..bcbd9a00 --- /dev/null +++ b/docs/assets/js/6.ffa47bc6.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{211:function(e,t,a){"use strict";a.r(t);var r=a(0),o=Object(r.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),a("p",[e._v("Welcome to the Goyave documentation!")]),e._v(" "),a("p",[e._v("This documentation is both a guide and a reference for Goyave application building. You will find instructions covering the basics as well as more advanced topics, from project setup to deployment. But first, let's talk about the framework itself.")]),e._v(" "),a("p",[e._v("Goyave is a framework aiming at "),a("strong",[e._v("cleanliness")]),e._v(", "),a("strong",[e._v("fast development")]),e._v(" and "),a("strong",[e._v("power")]),e._v(". Goyave applications stay clean and concise thanks to minimalist function calls and route handlers. The framework gives you all the tools to create an easily readable and maintainable web application, which let you concentrate on the business logic. Although Goyave handles many things for you, such as headers or marshaling, this characteristic doesn't compromise on your freedom of code.")]),e._v(" "),a("p",[e._v("Most golang frameworks for web development don't have a strong directory structure nor conventions to make applications have a uniform architecture and limit redundancy. This makes it difficult to work with them on different projects. In companies, having a well-defined and documented architecture helps new developers integrate projects faster, and reduces the time needed for maintaining them. For open source projects, it helps newcomers understanding the project and makes it easier to contribute.")]),e._v(" "),a("div",{staticClass:"custom-block tip"},[a("p",{staticClass:"custom-block-title"},[e._v("Note")]),e._v(" "),a("p",[e._v("Please feel free to sudgest changes, ask for more details, report grammar errors, or notice of uncovered scenarios by "),a("a",{attrs:{href:"https://github.com/System-Glitch/goyave/issues/new/choose",target:"_blank",rel:"noopener noreferrer"}},[e._v("creating an issue"),a("OutboundLink")],1),e._v(" with the proposal template.")])]),e._v(" "),a("h2",{attrs:{id:"roadmap"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#roadmap"}},[e._v("#")]),e._v(" Roadmap")]),e._v(" "),a("div",{staticClass:"img-row left"},[a("img",{attrs:{src:e.$withBase("/undraw_to_do_list_a49b.svg"),height:"150",alt:"Roadmap"}}),a("div",{staticClass:"row-content"},[a("h3",{attrs:{id:"next-release"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#next-release"}},[e._v("#")]),e._v(" Next release")]),e._v(" "),a("ul",[a("li",[e._v("Direct support for authentication")])])])]),a("h3",{attrs:{id:"ideas-for-future-releases"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#ideas-for-future-releases"}},[e._v("#")]),e._v(" Ideas for future releases")]),e._v(" "),a("ul",[a("li",[e._v("Plugins")]),e._v(" "),a("li",[e._v("CLI utility to help creating controllers, middlewares, etc")]),e._v(" "),a("li",[e._v("Email helpers")]),e._v(" "),a("li",[e._v("Queues/Scheduler system")]),e._v(" "),a("li",[e._v("Logging")]),e._v(" "),a("li",[e._v("Custom HTTP error handlers (for custom 404/500/... messages)")]),e._v(" "),a("li",[e._v("Named routes, CORS")]),e._v(" "),a("li",[e._v("Placeholders in language lines and pluralization")]),e._v(" "),a("li",[e._v("Support for gzip compression")]),e._v(" "),a("li",[e._v("Direct support for the OPTIONS method")]),e._v(" "),a("li",[e._v("And more!")])]),e._v(" "),a("h2",{attrs:{id:"contributors"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#contributors"}},[e._v("#")]),e._v(" Contributors")]),e._v(" "),a("p",[e._v('A big "Thank you" to the Goyave contributors:')]),e._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://github.com/Kuinox",target:"_blank",rel:"noopener noreferrer"}},[e._v("Kuinox"),a("OutboundLink")],1),e._v(" (Powershell install script)")]),e._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/alexandregv",target:"_blank",rel:"noopener noreferrer"}},[e._v("Alexandre GV."),a("OutboundLink")],1),e._v(" (Install script MacOS compatibility)")])])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/docs/assets/js/7.1f9c7719.js b/docs/assets/js/7.0624cd52.js similarity index 100% rename from docs/assets/js/7.1f9c7719.js rename to docs/assets/js/7.0624cd52.js diff --git a/docs/assets/js/8.7cf85661.js b/docs/assets/js/8.3ca2a95e.js similarity index 100% rename from docs/assets/js/8.7cf85661.js rename to docs/assets/js/8.3ca2a95e.js diff --git a/docs/assets/js/9.e316c4ab.js b/docs/assets/js/9.43e11177.js similarity index 100% rename from docs/assets/js/9.e316c4ab.js rename to docs/assets/js/9.43e11177.js diff --git a/docs/assets/js/app.12b71617.js b/docs/assets/js/app.12b71617.js deleted file mode 100644 index 06412cbb..00000000 --- a/docs/assets/js/app.12b71617.js +++ /dev/null @@ -1,14 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,s=e[0],c=e[1],u=e[2],f=0,p=[];f
'};function o(t,e,n){return tn?n:t}function i(t){return 100*(-1+t)}n.configure=function(t){var e,n;for(e in t)void 0!==(n=t[e])&&t.hasOwnProperty(e)&&(r[e]=n);return this},n.status=null,n.set=function(t){var e=n.isStarted();t=o(t,r.minimum,1),n.status=1===t?null:t;var c=n.render(!e),u=c.querySelector(r.barSelector),l=r.speed,f=r.easing;return c.offsetWidth,a((function(e){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(u,function(t,e,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+i(t)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+i(t)+"%,0)"}:{"margin-left":i(t)+"%"}).transition="all "+e+"ms "+n,o}(t,l,f)),1===t?(s(c,{transition:"none",opacity:1}),c.offsetWidth,setTimeout((function(){s(c,{transition:"all "+l+"ms linear",opacity:0}),setTimeout((function(){n.remove(),e()}),l)}),l)):setTimeout(e,l)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var t=function(){setTimeout((function(){n.status&&(n.trickle(),t())}),r.trickleSpeed)};return r.trickle&&t(),this},n.done=function(t){return t||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(t){var e=n.status;return e?("number"!=typeof t&&(t=(1-e)*o(Math.random()*e,.1,.95)),e=o(e+t,0,.994),n.set(e)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},t=0,e=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===e&&n.start(),t++,e++,r.always((function(){0==--e?(t=0,n.done()):n.set((t-e)/t)})),this):this},n.render=function(t){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var e=document.createElement("div");e.id="nprogress",e.innerHTML=r.template;var o,a=e.querySelector(r.barSelector),c=t?"-100":i(n.status||0),l=document.querySelector(r.parent);return s(a,{transition:"all 0 linear",transform:"translate3d("+c+"%,0,0)"}),r.showSpinner||(o=e.querySelector(r.spinnerSelector))&&p(o),l!=document.body&&u(l,"nprogress-custom-parent"),l.appendChild(e),e},n.remove=function(){l(document.documentElement,"nprogress-busy"),l(document.querySelector(r.parent),"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&p(t)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var t=document.body.style,e="WebkitTransform"in t?"Webkit":"MozTransform"in t?"Moz":"msTransform"in t?"ms":"OTransform"in t?"O":"";return e+"Perspective"in t?"translate3d":e+"Transform"in t?"translate":"margin"};var a=function(){var t=[];function e(){var n=t.shift();n&&n(e)}return function(n){t.push(n),1==t.length&&e()}}(),s=function(){var t=["Webkit","O","Moz","ms"],e={};function n(n){return n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(t,e){return e.toUpperCase()})),e[n]||(e[n]=function(e){var n=document.body.style;if(e in n)return e;for(var r,o=t.length,i=e.charAt(0).toUpperCase()+e.slice(1);o--;)if((r=t[o]+i)in n)return r;return e}(n))}function r(t,e,r){e=n(e),t.style[e]=r}return function(t,e){var n,o,i=arguments;if(2==i.length)for(n in e)void 0!==(o=e[n])&&e.hasOwnProperty(n)&&r(t,n,o);else r(t,i[1],i[2])}}();function c(t,e){return("string"==typeof t?t:f(t)).indexOf(" "+e+" ")>=0}function u(t,e){var n=f(t),r=n+e;c(n,e)||(t.className=r.substring(1))}function l(t,e){var n,r=f(t);c(t,e)&&(n=r.replace(" "+e+" "," "),t.className=n.substring(1,n.length-1))}function f(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}function p(t){t&&t.parentNode&&t.parentNode.removeChild(t)}return n})?r.call(e,n,e,t):r)||(t.exports=o)},function(t,e,n){var r=n(5),o=n(26),i=n(13),a=Object.defineProperty;e.f=n(2)?Object.defineProperty:function(t,e,n){if(r(t),e=i(e,!0),r(n),o)try{return a(t,e,n)}catch(t){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){var r=n(36),o=n(15);t.exports=function(t){return r(o(t))}},function(t,e){var n=t.exports={version:"2.6.10"};"number"==typeof __e&&(__e=n)},function(t,e,n){var r=n(3);t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},function(t,e){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,e){t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},function(t,e,n){var r=n(10),o=n(21);t.exports=n(2)?function(t,e,n){return r.f(t,e,o(1,n))}:function(t,e,n){return t[e]=n,t}},function(t,e,n){var r=n(1),o=n(16),i=n(6),a=n(24)("src"),s=n(50),c=(""+s).split("toString");n(12).inspectSource=function(t){return s.call(t)},(t.exports=function(t,e,n,s){var u="function"==typeof n;u&&(i(n,"name")||o(n,"name",e)),t[e]!==n&&(u&&(i(n,a)||o(n,a,t[e]?""+t[e]:c.join(String(e)))),t===r?t[e]=n:s?t[e]?t[e]=n:o(t,e,n):(delete t[e],o(t,e,n)))})(Function.prototype,"toString",(function(){return"function"==typeof this&&this[a]||s.call(this)}))},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e){var n=Math.ceil,r=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?r:n)(t)}},function(t,e,n){var r=n(47);t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,o){return t.call(e,n,r,o)}}return function(){return t.apply(e,arguments)}}},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var r=n(23)("keys"),o=n(24);t.exports=function(t){return r[t]||(r[t]=o(t))}},function(t,e,n){var r=n(12),o=n(1),i=o["__core-js_shared__"]||(o["__core-js_shared__"]={});(t.exports=function(t,e){return i[t]||(i[t]=void 0!==e?e:{})})("versions",[]).push({version:r.version,mode:n(38)?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(t,e){var n=0,r=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++n+r).toString(36))}},function(t,e,n){var r=n(48),o=n(21),i=n(11),a=n(13),s=n(6),c=n(26),u=Object.getOwnPropertyDescriptor;e.f=n(2)?u:function(t,e){if(t=i(t),e=a(e,!0),c)try{return u(t,e)}catch(t){}if(s(t,e))return o(!r.f.call(t,e),t[e])}},function(t,e,n){t.exports=!n(2)&&!n(4)((function(){return 7!=Object.defineProperty(n(27)("div"),"a",{get:function(){return 7}}).a}))},function(t,e,n){var r=n(3),o=n(1).document,i=r(o)&&r(o.createElement);t.exports=function(t){return i?o.createElement(t):{}}},function(t,e,n){var r=n(6),o=n(11),i=n(33)(!1),a=n(22)("IE_PROTO");t.exports=function(t,e){var n,s=o(t),c=0,u=[];for(n in s)n!=a&&r(s,n)&&u.push(n);for(;e.length>c;)r(s,n=e[c++])&&(~i(u,n)||u.push(n));return u}},function(t,e,n){!function(){"use strict";t.exports={polyfill:function(){var t=window,e=document;if(!("scrollBehavior"in e.documentElement.style&&!0!==t.__forceSmoothScrollPolyfill__)){var n,r=t.HTMLElement||t.Element,o=468,i={scroll:t.scroll||t.scrollTo,scrollBy:t.scrollBy,elementScroll:r.prototype.scroll||c,scrollIntoView:r.prototype.scrollIntoView},a=t.performance&&t.performance.now?t.performance.now.bind(t.performance):Date.now,s=(n=t.navigator.userAgent,new RegExp(["MSIE ","Trident/","Edge/"].join("|")).test(n)?1:0);t.scroll=t.scrollTo=function(){void 0!==arguments[0]&&(!0!==u(arguments[0])?v.call(t,e.body,void 0!==arguments[0].left?~~arguments[0].left:t.scrollX||t.pageXOffset,void 0!==arguments[0].top?~~arguments[0].top:t.scrollY||t.pageYOffset):i.scroll.call(t,void 0!==arguments[0].left?arguments[0].left:"object"!=typeof arguments[0]?arguments[0]:t.scrollX||t.pageXOffset,void 0!==arguments[0].top?arguments[0].top:void 0!==arguments[1]?arguments[1]:t.scrollY||t.pageYOffset))},t.scrollBy=function(){void 0!==arguments[0]&&(u(arguments[0])?i.scrollBy.call(t,void 0!==arguments[0].left?arguments[0].left:"object"!=typeof arguments[0]?arguments[0]:0,void 0!==arguments[0].top?arguments[0].top:void 0!==arguments[1]?arguments[1]:0):v.call(t,e.body,~~arguments[0].left+(t.scrollX||t.pageXOffset),~~arguments[0].top+(t.scrollY||t.pageYOffset)))},r.prototype.scroll=r.prototype.scrollTo=function(){if(void 0!==arguments[0])if(!0!==u(arguments[0])){var t=arguments[0].left,e=arguments[0].top;v.call(this,this,void 0===t?this.scrollLeft:~~t,void 0===e?this.scrollTop:~~e)}else{if("number"==typeof arguments[0]&&void 0===arguments[1])throw new SyntaxError("Value could not be converted");i.elementScroll.call(this,void 0!==arguments[0].left?~~arguments[0].left:"object"!=typeof arguments[0]?~~arguments[0]:this.scrollLeft,void 0!==arguments[0].top?~~arguments[0].top:void 0!==arguments[1]?~~arguments[1]:this.scrollTop)}},r.prototype.scrollBy=function(){void 0!==arguments[0]&&(!0!==u(arguments[0])?this.scroll({left:~~arguments[0].left+this.scrollLeft,top:~~arguments[0].top+this.scrollTop,behavior:arguments[0].behavior}):i.elementScroll.call(this,void 0!==arguments[0].left?~~arguments[0].left+this.scrollLeft:~~arguments[0]+this.scrollLeft,void 0!==arguments[0].top?~~arguments[0].top+this.scrollTop:~~arguments[1]+this.scrollTop))},r.prototype.scrollIntoView=function(){if(!0!==u(arguments[0])){var n=d(this),r=n.getBoundingClientRect(),o=this.getBoundingClientRect();n!==e.body?(v.call(this,n,n.scrollLeft+o.left-r.left,n.scrollTop+o.top-r.top),"fixed"!==t.getComputedStyle(n).position&&t.scrollBy({left:r.left,top:r.top,behavior:"smooth"})):t.scrollBy({left:o.left,top:o.top,behavior:"smooth"})}else i.scrollIntoView.call(this,void 0===arguments[0]||arguments[0])}}function c(t,e){this.scrollLeft=t,this.scrollTop=e}function u(t){if(null===t||"object"!=typeof t||void 0===t.behavior||"auto"===t.behavior||"instant"===t.behavior)return!0;if("object"==typeof t&&"smooth"===t.behavior)return!1;throw new TypeError("behavior member of ScrollOptions "+t.behavior+" is not a valid value for enumeration ScrollBehavior.")}function l(t,e){return"Y"===e?t.clientHeight+s1?1:c,n=.5*(1-Math.cos(Math.PI*s)),r=e.startX+(e.x-e.startX)*n,i=e.startY+(e.y-e.startY)*n,e.method.call(e.scrollable,r,i),r===e.x&&i===e.y||t.requestAnimationFrame(h.bind(t,e))}function v(n,r,o){var s,u,l,f,p=a();n===e.body?(s=t,u=t.scrollX||t.pageXOffset,l=t.scrollY||t.pageYOffset,f=i.scroll):(s=n,u=n.scrollLeft,l=n.scrollTop,f=c),h({scrollable:s,method:f,startTime:p,startX:u,startY:l,x:r,y:o})}}}}()},function(t,e){var n="Expected a function",r=NaN,o="[object Symbol]",i=/^\s+|\s+$/g,a=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,c=/^0o[0-7]+$/i,u=parseInt,l="object"==typeof global&&global&&global.Object===Object&&global,f="object"==typeof self&&self&&self.Object===Object&&self,p=l||f||Function("return this")(),d=Object.prototype.toString,h=Math.max,v=Math.min,m=function(){return p.Date.now()};function g(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function y(t){if("number"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return!!t&&"object"==typeof t}(t)&&d.call(t)==o}(t))return r;if(g(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=g(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(i,"");var n=s.test(t);return n||c.test(t)?u(t.slice(2),n?2:8):a.test(t)?r:+t}t.exports=function(t,e,r){var o,i,a,s,c,u,l=0,f=!1,p=!1,d=!0;if("function"!=typeof t)throw new TypeError(n);function b(e){var n=o,r=i;return o=i=void 0,l=e,s=t.apply(r,n)}function _(t){var n=t-u;return void 0===u||n>=e||n<0||p&&t-l>=a}function w(){var t=m();if(_(t))return x(t);c=setTimeout(w,function(t){var n=e-(t-u);return p?v(n,a-(t-l)):n}(t))}function x(t){return c=void 0,d&&o?b(t):(o=i=void 0,s)}function $(){var t=m(),n=_(t);if(o=arguments,i=this,u=t,n){if(void 0===c)return function(t){return l=t,c=setTimeout(w,e),f?b(t):s}(u);if(p)return c=setTimeout(w,e),b(u)}return void 0===c&&(c=setTimeout(w,e)),s}return e=y(e)||0,g(r)&&(f=!!r.leading,a=(p="maxWait"in r)?h(y(r.maxWait)||0,e):a,d="trailing"in r?!!r.trailing:d),$.cancel=function(){void 0!==c&&clearTimeout(c),l=0,o=u=i=c=void 0},$.flush=function(){return void 0===c?s:x(m())},$}},function(t,e,n){var r=n(1),o=n(12),i=n(16),a=n(17),s=n(20),c=function(t,e,n){var u,l,f,p,d=t&c.F,h=t&c.G,v=t&c.S,m=t&c.P,g=t&c.B,y=h?r:v?r[e]||(r[e]={}):(r[e]||{}).prototype,b=h?o:o[e]||(o[e]={}),_=b.prototype||(b.prototype={});for(u in h&&(n=e),n)f=((l=!d&&y&&void 0!==y[u])?y:n)[u],p=g&&l?s(f,r):m&&"function"==typeof f?s(Function.call,f):f,y&&a(y,u,f,t&c.U),b[u]!=f&&i(b,u,p),m&&_[u]!=f&&(_[u]=f)};r.core=o,c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,t.exports=c},function(t,e,n){var r=n(19),o=Math.min;t.exports=function(t){return t>0?o(r(t),9007199254740991):0}},function(t,e,n){var r=n(11),o=n(32),i=n(49);t.exports=function(t){return function(e,n,a){var s,c=r(e),u=o(c.length),l=i(a,u);if(t&&n!=n){for(;u>l;)if((s=c[l++])!=s)return!0}else for(;u>l;l++)if((t||l in c)&&c[l]===n)return t||l||0;return!t&&-1}}},function(t,e,n){var r=n(28),o=n(14);t.exports=Object.keys||function(t){return r(t,o)}},function(t,e,n){var r=n(3),o=n(46).set;t.exports=function(t,e,n){var i,a=e.constructor;return a!==n&&"function"==typeof a&&(i=a.prototype)!==n.prototype&&r(i)&&o&&o(t,i),t}},function(t,e,n){var r=n(18);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==r(t)?t.split(""):Object(t)}},function(t,e,n){var r=n(28),o=n(14).concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return r(t,o)}},function(t,e){t.exports=!1},function(t,e,n){var r=n(31),o=n(15),i=n(4),a=n(51),s="["+a+"]",c=RegExp("^"+s+s+"*"),u=RegExp(s+s+"*$"),l=function(t,e,n){var o={},s=i((function(){return!!a[t]()||"​…"!="​…"[t]()})),c=o[t]=s?e(f):a[t];n&&(o[n]=c),r(r.P+r.F*s,"String",o)},f=l.trim=function(t,e){return t=String(o(t)),1&e&&(t=t.replace(c,"")),2&e&&(t=t.replace(u,"")),t};t.exports=l},function(t,e,n){var r=n(5),o=n(52),i=n(14),a=n(22)("IE_PROTO"),s=function(){},c=function(){var t,e=n(27)("iframe"),r=i.length;for(e.style.display="none",n(53).appendChild(e),e.src="javascript:",(t=e.contentWindow.document).open(),t.write(" + diff --git a/docs/guide/advanced/helpers.html b/docs/guide/advanced/helpers.html index 4e9d0ffa..74c120e5 100644 --- a/docs/guide/advanced/helpers.html +++ b/docs/guide/advanced/helpers.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/advanced/index.html b/docs/guide/advanced/index.html index f40e1943..90d73bc8 100644 --- a/docs/guide/advanced/index.html +++ b/docs/guide/advanced/index.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/advanced/localization.html b/docs/guide/advanced/localization.html index 7f00b431..e5cd69ad 100644 --- a/docs/guide/advanced/localization.html +++ b/docs/guide/advanced/localization.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/advanced/multi-services.html b/docs/guide/advanced/multi-services.html index 71caefa6..4b431157 100644 --- a/docs/guide/advanced/multi-services.html +++ b/docs/guide/advanced/multi-services.html @@ -12,8 +12,8 @@ - - + +
- + diff --git a/docs/guide/advanced/plugins.html b/docs/guide/advanced/plugins.html index 745eef0c..f5ce564d 100644 --- a/docs/guide/advanced/plugins.html +++ b/docs/guide/advanced/plugins.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/advanced/testing.html b/docs/guide/advanced/testing.html index 2c84f0db..cac3682a 100644 --- a/docs/guide/advanced/testing.html +++ b/docs/guide/advanced/testing.html @@ -12,19 +12,163 @@ - - + +

# Testing

In progress

WARNING

This feature is not implemented yet and is coming in a future release.

Watch the github repository to stay updated.

# Database testing

# Factories

# Seeders

- + diff --git a/docs/guide/architecture-concepts.html b/docs/guide/architecture-concepts.html index f723cd66..71ca8418 100644 --- a/docs/guide/architecture-concepts.html +++ b/docs/guide/architecture-concepts.html @@ -12,19 +12,21 @@ - - + +

# Architecture Concepts

# Introduction

Understanding your development tools and knowing what happens in the background is crucial. Mastering your tools and environment incredibily decreases the risk of errors, the ease of debugging and helps making your code work in harmony with the framework. The goal of this section is to give you an overview of the general functioning and design of the framework, to make you more comfortable and confident using it.

# Terminology

This section will briefly explain the technical words used in the following sections.

Lifecycle: An execution from start to finish, with intermediary steps.

Framework core: Features and behaviors executed internally and that are invisible to the application developer.

Handler: A function receiving incoming requests and a response writer. Multiple handlers can be executed for the same request.

Router: The root-level handler responsible for the execution of the correct controller handler.

Route: A URI definition linked to a controller handler. If a request matches the definition, the router will execute the associated controller handler.

Controller: A source file implementing the business logic linked to a specific resource and associated routes.

Middleware: A handler executed before controller handlers. Middleware can intercept the request, modify its data, and send a response before the controller handler is reached.

Application: A program using the Goyave framework as a library.

Model: A structure reflecting a database table structure. An instance of a model is a single database record.

# Lifecycle

# Server

The very first step of the server lifecycle is the server setup, taking place when you call goyave.Start(route.Register) in your application's main function.

Goyave starts by loading the configuration file from the core of the framework. The application's configuration file is then loaded, overriding the default values.

The second step of the initialization takes a very similar approach to load the language files. The en-US language is available by default inside the framework and is used as the default language. When it's loaded, the framework will look for custom language files inside the working directory and will override the en-US language entries if needed.

Then, if enabled, the automatic migrations are run, thus creating the database connection pool. If the automatic migrations are not enabled, no connection to the database will be established until the application requires one.

That is only now that routes are registered using the route registrer provided to the Start() function. That means that at this registrer has already access to all the configuration and language features, which can be handy if you want to generate different routes based on the languages your application supports.

Finally, the framework starts listening for incoming HTTP requests and serves them. The server also listens for interruption and termination signals so it can finish serving ongoing requests before shutting down gracefully. In the next section, we will get into more details about the lifecycle of each request.

# Requests

When an incoming request is received, it's first passed through the Gorilla Mux router so your server knows which handler to execute when a user requests a specific URI. Then, the framework's internal handler creates a goyave.Request object and a goyave.Response object from the raw request. These two objects are fundamental features of the framework as you are going to use them to retrieve the requests' data and write your responses.

Before executing the handler, the middleware are executed. The framework features a few core middleware, which are executed first and for all routes and all requests.

# 1. Recovery

The recovery middleware is executed. This middleware ensures that any unrecovered panic is handled. Instead of never returning a response in case of a panic, the server will then return an HTTP 500 Error. If debugging is enabled if the configuration, the response will contain the error message and the stacktrace will be printed in the console. It's important to keep this behavior in mind when handling errors in your handlers.

# 2. Parsing

The request is parsed by a second middleware. This middleware will automatically detect the request's body format based on the headers and attempt to parse it. If the request can't be parsed, the request's data is simply set to nil. This middleware supports JSON requests.

# 3. Language

The Accept-Language header is checked. If it's there, its value is parsed and the request's language attribute is set accordingly so localization is easy in the following handlers. If the header is missing, invalid, or asks for an unsupported language, the framework falls back to the default language defined in the configuration. Learn more here.

# 4. Application middlewares

Application middlewares are executed. These middlewares are implemented and defined by the application developer. Note that some application middleware are already available in the framework. Learn more in the middlewares section. At this stage of the lifecycle, the request is not validated yet, so application middleware can be used for authentication or automatic string trimming for example. Bear in mind that manipulating unvalidated data can be dangerous, especially in form-data where the data types are not converted by the validator yet.

# 5. Validation

The data is validated last. The validation middleware immediately passes if no rules have been defined for the current route, else, it check if the data parsing was successful. An automatic response is sent if that is not the case. The data is passed through the validator, which converts the data types and validates it. The request is stopped if the validation is not successful, and the validation errors are sent as a response. Be careful when working with unvalidated requests (which you should never do!) because if the request's parsing fails, request.Data will be nil.

# 6. Controller handler

Finally, if the request has not been stopped by a middleware, the controller handler is executed. +

# Architecture Concepts

# Introduction

Understanding your development tools and knowing what happens in the background is crucial. Mastering your tools and environment incredibily decreases the risk of errors, the ease of debugging and helps making your code work in harmony with the framework. The goal of this section is to give you an overview of the general functioning and design of the framework, to make you more comfortable and confident using it.

# Terminology

This section will briefly explain the technical words used in the following sections.

Lifecycle: An execution from start to finish, with intermediary steps.

Framework core: Features and behaviors executed internally and that are invisible to the application developer.

Handler: A function receiving incoming requests and a response writer. Multiple handlers can be executed for the same request.

Router: The root-level handler responsible for the execution of the correct controller handler.

Route: A URI definition linked to a controller handler. If a request matches the definition, the router will execute the associated controller handler.

Controller: A source file implementing the business logic linked to a specific resource and associated routes.

Middleware: A handler executed before controller handlers. Middleware can intercept the request, modify its data, and send a response before the controller handler is reached.

Application: A program using the Goyave framework as a library.

Model: A structure reflecting a database table structure. An instance of a model is a single database record.

Seeder: A function which creates a number of random records in the database.

# Lifecycle

# Server

The very first step of the server lifecycle is the server setup, taking place when you call goyave.Start(route.Register) in your application's main function.

Goyave starts by loading the configuration file from the core of the framework. The application's configuration file is then loaded, overriding the default values.

The second step of the initialization takes a very similar approach to load the language files. The en-US language is available by default inside the framework and is used as the default language. When it's loaded, the framework will look for custom language files inside the working directory and will override the en-US language entries if needed.

Then, if enabled, the automatic migrations are run, thus creating the database connection pool. If the automatic migrations are not enabled, no connection to the database will be established until the application requires one.

That is only now that routes are registered using the route registrer provided to the Start() function. That means that at this registrer has already access to all the configuration and language features, which can be handy if you want to generate different routes based on the languages your application supports.

Finally, the framework starts listening for incoming HTTP requests and serves them. The server also listens for interruption and termination signals so it can finish serving ongoing requests before shutting down gracefully. In the next section, we will get into more details about the lifecycle of each request.

# Requests

When an incoming request is received, it's first passed through the Gorilla Mux router so your server knows which handler to execute when a user requests a specific URI. Then, the framework's internal handler creates a goyave.Request object and a goyave.Response object from the raw request. These two objects are fundamental features of the framework as you are going to use them to retrieve the requests' data and write your responses.

Before executing the handler, the middleware are executed. The framework features a few core middleware, which are executed first and for all routes and all requests.

# 1. Recovery

The recovery middleware is executed. This middleware ensures that any unrecovered panic is handled. Instead of never returning a response in case of a panic, the server will then return an HTTP 500 Error. If debugging is enabled if the configuration, the response will contain the error message and the stacktrace will be printed in the console. It's important to keep this behavior in mind when handling errors in your handlers.

# 2. Parsing

The request is parsed by a second middleware. This middleware will automatically detect the request's body format based on the headers and attempt to parse it. If the request can't be parsed, the request's data is simply set to nil. This middleware supports JSON requests.

# 3. Language

The Accept-Language header is checked. If it's there, its value is parsed and the request's language attribute is set accordingly so localization is easy in the following handlers. If the header is missing, invalid, or asks for an unsupported language, the framework falls back to the default language defined in the configuration. Learn more here.

# 4. Application middlewares

Application middlewares are executed. These middlewares are implemented and defined by the application developer. Note that some application middleware are already available in the framework. Learn more in the middlewares section. At this stage of the lifecycle, the request is not validated yet, so application middleware can be used for authentication or automatic string trimming for example. Bear in mind that manipulating unvalidated data can be dangerous, especially in form-data where the data types are not converted by the validator yet.

# 5. Validation

The data is validated last. The validation middleware immediately passes if no rules have been defined for the current route, else, it check if the data parsing was successful. An automatic response is sent if that is not the case. The data is passed through the validator, which converts the data types and validates it. The request is stopped if the validation is not successful, and the validation errors are sent as a response. Be careful when working with unvalidated requests (which you should never do!) because if the request's parsing fails, request.Data will be nil.

# 6. Controller handler

Finally, if the request has not been stopped by a middleware, the controller handler is executed. If the controller handler didn't write anything as a response, an empty response with the HTTP status code 204 "No Content" is automatically sent, so you don't have to do it yourself.

# Directory structure

Goyave follows the principle of "Convention is better than configuration". That means that the framework will attempt to automatically get the resources it needs from predefined directories. The typical and recommended directory structure for Goyave applications is as follows:

. ├── database -│   └── model +│   ├── model +│   | └── ... +│   └── seeder │   └── ... ├── http │   ├── controller @@ -46,16 +48,19 @@ │   │   └── rules.json (optional) │   └── img (optional) │      └── ... -│  +│ +├── test +| └── ... +| ├── .gitignore ├── config.json ├── go.mod └── kernel.go

-

# Database directory

The database directory stores the models. Each model should have its own file in the models package. This directory can also contain database-related code such as repositories, if you want to use this pattern.

# HTTP directory

The http directory contains all the HTTP-related code. This is where most of your code will be written.

# HTTP controllers

The http/controller directory contains the controller packages. 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. Learn more here.

# HTTP middleware

The http/middleware directory contains the application middleware. Each middleware should have its own file. Learn more here.

# HTTP request

The http/request directory contains the requests validation rules sets. You should have one package per feature, regrouping all requests handled by the same controller.

This directory can also contain a placeholders.go file, which will define validation rule messages placeholders. Learn more here.

This directory can also contain a validation.go file, which will define custom validation rules. Learn more here.

# HTTP Routes

The http/route directory contains the routes définitions. By default, all routes are registered in the route.go file, but for bigger projects, split the route definitions into multiple files.

# Resources directory

The resources directory is meant to store static resources such as images, HTML documents and language files. This directory shouldn't be used as a storage for dynamic content such as user profile pictures.

# Language resources directory

The resources/lang directory contains your application's supported languages and translations. Each language has its own directory and should be named with an ISO 639-1 language code. You can also append a variant to your languages: en-US, en-UK, fr-FR, fr-CA, ... Case is important.

Each language directory contains three files. Each file is optional.

  • fields.json: field names translations and field-specific rule messages.
  • locale.json: all other language lines.
  • rules.json: validation rules messages.

Learn more about localization here.

# Custom directories

You may add custom directories for your custom utilities, as they don't belong to any of the above directories. For example, if you develop a service manipulating images, the image processing code shouldn't be written in controller handlers, they are not part of the business logic. You would then create a processing directory, containing your code in images.go for example.

# Database

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.

If automatic migrations are enabled, all registered models at the time of startup will be auto-migrated. They must be registered before the server starts, ideally from an init() function next to each model definition.

Learn more in the database section.

- + diff --git a/docs/guide/basics/controllers.html b/docs/guide/basics/controllers.html index 74566e07..94afb9ac 100644 --- a/docs/guide/basics/controllers.html +++ b/docs/guide/basics/controllers.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/basics/database.html b/docs/guide/basics/database.html index 6fd22f3e..487958c5 100644 --- a/docs/guide/basics/database.html +++ b/docs/guide/basics/database.html @@ -12,8 +12,8 @@ - - + +

Learn more about model declaration in the Gorm documentation.

# database.RegisterModel

Registers a model for auto-migration.

Parameters Return
model interface{} void

# database.GetRegisteredModels

Get the registered models. The returned slice is a copy of the original, so it cannot be modified.

Parameters Return
[]interface{}

# database.ClearRegisteredModels

Unregister all models.

Parameters Return
void

# Automatic migrations

If the dbAutoMigrate config option is set to true, all registered models will be automatically migrated when the server starts.

WARNING

Automatic migrations only create tables, missing columns and missing indexes. They wont't change existing column’s type or delete unused columns.

If you would like to know more about migrations using Gorm, read their documentation.

- + diff --git a/docs/guide/basics/middleware.html b/docs/guide/basics/middleware.html index 6ed9d9f6..a7953b68 100644 --- a/docs/guide/basics/middleware.html +++ b/docs/guide/basics/middleware.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/basics/requests.html b/docs/guide/basics/requests.html index ffc47620..b6b27b3a 100644 --- a/docs/guide/basics/requests.html +++ b/docs/guide/basics/requests.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/basics/responses.html b/docs/guide/basics/responses.html index a62c11d2..a7793ddc 100644 --- a/docs/guide/basics/responses.html +++ b/docs/guide/basics/responses.html @@ -12,8 +12,8 @@ - - + +

# Responses

Handlers receive a goyave.Response and a goyave.Request as parameters. This section is a technical reference of the Response object.

goyave.Response implements http.ResponseWriter. This object brings a number of convenient methods to write HTTP responses.

If you didn't write anything before the request lifecycle ends, 204 No Content is automatically written.

All functions below require the goyave package to be imported.

import "github.com/System-Glitch/goyave/v2"
-

List of response methods:

# Response.Header

Returns the Header map that will be sent.

Parameters Return
http.Header

Example:

header := response.Header()
+

List of response methods:

# Response.Header

Returns the Header map that will be sent.

Parameters Return
http.Header

Example:

header := response.Header()
 header.Set("Content-Type", "application/json")
 

# Response.Status

Write the given status code.

Parameters Return
status int void

Example:

response.Status(http.StatusOK)
 

# Response.JSON

Write JSON data as a response. This method automatically sets the Content-Type header.

Parameters Return
responseCode int error
data interface{}

Example:

response.JSON(http.StatusOK, map[string]interface{}{
@@ -41,16 +41,11 @@
 response.Cookie(cookie)
 

# Response.Redirect

Send a permanent redirect response. (HTTP 308)

Parameters Return
url string void

Example:

response.Redirect("/login")
 

# Response.TemporaryRedirect

Send a temporary redirect response. (HTTP 307)

Parameters Return
url string void

Example:

response.TemporaryRedirect("/maintenance")
-

# Response.CreateTestResponse

Create an empty response with the given response writer. This function is aimed at making it easier to unit test Responses.

Parameters Return
recorder http.ResponseWriter void

Example:

writer := httptest.NewRecorder()
-response := goyave.CreateTestResponse(writer)
-response.Status(http.StatusNoContent)
-result := writer.Result()
-fmt.Println(result.StatusCode) // 204
 
- + diff --git a/docs/guide/basics/routing.html b/docs/guide/basics/routing.html index 81c36aef..9baae0a5 100644 --- a/docs/guide/basics/routing.html +++ b/docs/guide/basics/routing.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/basics/validation.html b/docs/guide/basics/validation.html index abf80749..302c6c69 100644 --- a/docs/guide/basics/validation.html +++ b/docs/guide/basics/validation.html @@ -12,8 +12,8 @@ - - + +
- + diff --git a/docs/guide/changelog.html b/docs/guide/changelog.html index aaf5e8da..2de7f31d 100644 --- a/docs/guide/changelog.html +++ b/docs/guide/changelog.html @@ -12,23 +12,23 @@ - - + +

# Changelog

# v2.1.0

  • filesystem.GetMIMEType now detects css, js, json and jsonld files based on their extension.
  • Added maintenance mode. +

    # Changelog

    # v2.2.0

    # v2.1.0

    • filesystem.GetMIMEType now detects css, js, json and jsonld files based on their extension.
    • Added maintenance mode.
      • Can be toggled at runtime.
      • The server can be started in maintenance mode using the maintenance config option. (Defaults to false)
    • Added advanced array validation, with support for n-dimensional arrays.BETA
    • Malformed request messages can now be localized. (malformed-request and malformed-json entries in locale.json)
    • Modified the validator to allow manual validation.

    # v2.0.0

    • Documentation and README improvements.
    • In the configuration:
      • The default value of dbConnection has been changed to none.
      • The default value of dbAutoMigrate has been changed to false.
    • Added request data accessors.
    • Some refactoring and package renaming have been done to better respect the Go conventions. -
      • The helpers package have been renamed to helper
    • The server now shuts down when it encounters an error.
    • New validation.GetFieldType function.
    • Config and Lang are now protected with a sync.RWMutex to avoid data races in multi-threaded environments.
    • Greatly improve concurrency.
    • Config can now be reloaded manually.
    • Added the Trim middleware.
    • goyave.Response now implements http.ResponseWriter. +
      • The helpers package have been renamed to helper
    • The server now shuts down when it encounters an error during startup.
    • New validation.GetFieldType function.
    • Config and Lang are now protected with a sync.RWMutex to avoid data races in multi-threaded environments.
    • Greatly improve concurrency.
    • Config can now be reloaded manually.
    • Added the Trim middleware.
    • goyave.Response now implements http.ResponseWriter.
      • All writing functions can now return an error.
    • Added the NativeHandler compatibility layer.
    • Fixed a bug preventing the static resources handler to find index.html if a directory with a depth of one was requested without a trailing slash.
    • Now panics when calling Start() while the server is already running.
- + diff --git a/docs/guide/configuration.html b/docs/guide/configuration.html index 96b562c6..064dd0f0 100644 --- a/docs/guide/configuration.html +++ b/docs/guide/configuration.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/contribution-guide.html b/docs/guide/contribution-guide.html index f83dd2a5..75687619 100644 --- a/docs/guide/contribution-guide.html +++ b/docs/guide/contribution-guide.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/guide/deployment.html b/docs/guide/deployment.html index bd3ea3b8..fcf8f60c 100644 --- a/docs/guide/deployment.html +++ b/docs/guide/deployment.html @@ -12,15 +12,15 @@ - - + +

# Deployment

# Introduction

There are some important details to think about before deploying your Goyave application to production. We are going to cover them in this section of the guide, and make sure your applications are deployed properly.

# Application configuration

Be sure to deploy your application with a config.production.json config file containing the correct values for your production environment and set the GOYAVE_ENV environment variable to production.

  1. Ensure that the environment entry is production.
  2. The host entry should be 0.0.0.0 or your domain name.
  3. The port and httpsPort will very likely require a change. Most of the time, you need 80 and 443 respectively.
  4. If you use https, be sure to provide the paths to your tlsCert and tlsKey. Learn more here.
  5. debug must be set do false. You don't want anyone to get important information about your internal errors and therefore your code when an error occurs.
  6. Change your database connection credentials. dbAutoMigrate should be set to false.

# Build

Of course, don't run your application with go run in production. Build your application using go build and deploy the executable, alongside the config files and resources directory.

# Deamon

Goyave applications are standalone and don't require any web server (such as Apache or Nginx) to function. However, this also means that you will need some additional installation steps on your production server.

When running a web service, it is important that it stays online. Creating a deamon is necessary so your server can run in the background, have the correct filesystem permissions, and restart automatically after a crash or a reboot.

You can achieve this with any supervisor program, but in this guide, we will use systemd as it's the most common one.

# Systemd

First, we need to create a user and its group for our application:

sudo addgroup goyave
+        

# Deployment

# Introduction

There are some important details to think about before deploying your Goyave application to production. We are going to cover them in this section of the guide, and make sure your applications are deployed properly.

# Application configuration

Be sure to deploy your application with a config.production.json config file containing the correct values for your production environment and set the GOYAVE_ENV environment variable to production.

  1. Ensure that the environment entry is production.
  2. The host entry should be 0.0.0.0 if you want let open access to your service. If you're using Apache or Nginx as a proxy on the same machine, keep it at 127.0.0.1 so the server will only be accessible through the proxy.
  3. The port and httpsPort will very likely require a change. Most of the time, you need 80 and 443 respectively.
  4. If you use https, be sure to provide the paths to your tlsCert and tlsKey. Learn more here.
  5. debug must be set do false. You don't want anyone to get important information about your internal errors and therefore your code when an error occurs.
  6. Change your database connection credentials. dbAutoMigrate should be set to false.

# Build

Of course, don't run your application with go run in production. Build your application using go build and deploy the executable, alongside the config files and resources directory.

# Deamon

Goyave applications are standalone and don't require any web server (such as Apache or Nginx) to function. However, this also means that you will need some additional installation steps on your production server.

When running a web service, it is important that it stays online. Creating a deamon is necessary so your server can run in the background, have the correct filesystem permissions, and restart automatically after a crash or a reboot.

You can achieve this with any supervisor program, but in this guide, we will use systemd as it's the most common one.

# Systemd

First, we need to create a user and its group for our application:

sudo addgroup goyave
 sudo useradd -r -s /bin/false goyave
 sudo usermod -a -G goyave goyave
 

You may use the following systemd unit file to deploy your Goyave application:

/etc/systemd/system/my-goyave-application.service:

[Unit]
@@ -83,6 +83,6 @@
        Contributing to Goyave

- + diff --git a/docs/guide/index.html b/docs/guide/index.html index 8f35ad80..f531bfa7 100644 --- a/docs/guide/index.html +++ b/docs/guide/index.html @@ -12,17 +12,17 @@ - - + +

# Introduction

Welcome to the Goyave documentation!

This documentation is both a guide and a reference for Goyave application building. You will find instructions covering the basics as well as more advanced topics, from project setup to deployment. But first, let's talk about the framework itself.

Goyave is a framework aiming at cleanliness, speed and power. Goyave applications stay clean and concise thanks to minimalist function calls and route handlers. The framework gives you all the tools to create an easily readable and maintainable web application, which let you concentrate on the business logic. Although Goyave handles many things for you, such as headers or marshaling, this characteristic doesn't compromise on your freedom of code.

Most golang frameworks for web development don't have a strong directory structure nor conventions to make applications have a uniform architecture and limit redundancy. This makes it difficult to work with them on different projects. In companies, having a well-defined and documented architecture helps new developers integrate projects faster, and reduces the time needed for maintaining them. For open source projects, it helps newcomers understanding the project and makes it easier to contribute.

Note

Please feel free to sudgest changes, ask for more details, report grammar errors, or notice of uncovered scenarios by creating an issue with the proposal template.

# Roadmap

Roadmap

# Next release

  • Integrated testing functions

# Ideas for future releases

  • Direct support for authentication
  • Plugins
  • Improved Gorm integration
  • CLI utility to help creating controllers, middlewares, etc
  • Email helpers
  • Server shutdown hooks (to gracefully close websocket connections for example)
  • Queues/Scheduler system
  • Logging
  • Custom HTTP error handlers (for custom 404/500/... messages)
  • Named routes, CORS
  • Placeholders in language lines and pluralization
  • Support for gzip compression
  • Direct support for the OPTIONS method
  • And more!

# Contributors

A big "Thank you" to the Goyave contributors:

- + diff --git a/docs/guide/installation.html b/docs/guide/installation.html index a9a59470..e07d5062 100644 --- a/docs/guide/installation.html +++ b/docs/guide/installation.html @@ -12,8 +12,8 @@ - - + +
- + diff --git a/docs/guide/upgrade-guide.html b/docs/guide/upgrade-guide.html index 9e7a9edf..6687843c 100644 --- a/docs/guide/upgrade-guide.html +++ b/docs/guide/upgrade-guide.html @@ -12,8 +12,8 @@ - - + + - + diff --git a/docs/index.html b/docs/index.html index d799accf..ac40c664 100644 --- a/docs/index.html +++ b/docs/index.html @@ -12,8 +12,8 @@ - - + +

Goyave is a progressive and accessible web application framework, aimed at making development easy and enjoyable. It has a philosophy of cleanliness and conciseness to make programs more elegant, easier to maintain and more focused. -

Clean

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.

Fast

Fast Development

Develop faster and concentrate on the business logic of your application thanks to the many helpers and built-in functions.

Powerful

Powerful functionalities

Goyave is accessible, yet powerful. The framework includes routing, request parsing, validation, localization, and more!

- +