Why use Go Fiber?

Out of curiosity, I’ve heard about this framework before, although I don’t know Express. I heard that Fiber is a Web framework that references Express and is based on the fastest FasthttpHTTP engine written in Go.

According to the official website: both simplify zero memory allocation and improve performance for rapid development.

As for why not use Gin, Beego, Iris, Echo, GF… I feel that there are already many people on the market who have their own scaffolding for teaching! I myself have not been back for long due to my new contact with GO! It’s great to learn something while experimenting! So give it a try!

At present, it has been out of the V2 version, and the difference between V1 is relatively large! After Baidu, there is no tutorial! Practice! Ha ha move brick series ~ official website!!

Fiber features (Advantages)

The official website of the big guy to a few points:

  • Powerful Routing
  • Static file service
  • Ultimate performance
  • Low memory usage
  • API interface
  • Middleware and Next support
  • Fast server-side programming
  • Template engines
  • WebSocket support
  • Frequency limiter
  • 15 languages

Fiber restrictions

Because Fiber uses the Unsafe feature, it may not be compatible with the latest Go version. Fiber 2.18.0 has been validated on Go 1.14 through 1.17. Fiber is incompatible with the NET/HTTP interface. This means you can’t use GQlen, Go-Swagger, or any other project that belongs in the NET/HTTP ecosystem.

Fiber V2.21.0 for initial use

Content of this section:

  • Hot update plugin is used
  • Fiber Configuration item of the APP object
  • Fiber APP routing and routing groups
  • Fiber APP starts listening customization (HTTP and HTTPS configurations)

Sample code from the official website

1.1 Fresh Hot Restart

Plug-in:

D:\code\go\awesomeProject1>go get github.com/pilu/fresh
Copy the code

Use:

D:\code\go\awesomeProject1>fresh
20:23:57 runner      | InitFolders
20:23:57 runner      | mkdir ./tmp
20:23:57 runner      | mkdir ./tmp: Cannot create a file when that file already exists.
20:23:57 watcher     | Watching .
20:23:57 main        | Waiting (loop 1)...
20:23:57 main        | receiving first event /
20:23:57 main        | sleeping for 600 milliseconds
20:23:57 main        | flushing events
20:23:57 main        | Started! (5 Goroutines)
20:23:57 main        | remove tmp\runner-build-errors.log: The system cannot find the file specified.
20:23:57 build       | Building...
20:23:58 runner      | Running...

Copy the code

Example code to play yourself:

Package the main import (" FMT "" github.com/gofiber/fiber/v2") func main () {app: = fiber. The New () / / define global middleware app. Use (func (c * fiber.ctx) error {fmt.println ("🥇 First 2222Handler ") return c.ext ()}) // define route app.get ("/", Func (c * fiber.ctx) error {return c. sendString (" Hello, xiaozhong! ) }) app.Listen(":3000") }Copy the code

Startup icon:

Then access the interface: http://127.0.0.1:3000/

In fact, compared with the Fastapi framework, in fact, the framework of most lesi, but also our GIN is generally similar.


1.2 Other official website examples of Amway

📖 Basic Route

func main() { app := fiber.New() // GET /api/register app.Get("/api/*", Func (c * fiber.ctx) error {MSG := ftt.sprintf ("✋ %s", C. params ("*")) return c. sinstring (MSG) // => ✋ register}) // GET /flights/LAX-SFO app. GET ("/flights/:from-:to", Func (c * fiber.ctx) error {MSG := fmt.sprintf ("💸 From: %s, To: % s ", c.P arams (" from "), c.P arams c.s. endString (" to ")) return (MSG) / / = > 💸 from: LAX, to: SFO}) // GET /dictionary. TXT app.get ("/:file.:ext", func(c *fiber. c.Params("file"), C. params ("ext")) return c. sendstring (MSG) // => 📃 dictionary.txt}) // GET/John /75 app.get ("/:name/:age/:gender?" , func(c * fiber.ctx) error {MSG := ftt.sprintf ("👴 %s is %s years old", c.params ("name"), C. params ("age")) return c. sendstring (MSG) // => 👴 John is 75 years old}) // GET/John app.get ("/:name", Func (c * fiber.ctx) error {MSG := fmt.sprintf ("Hello, %s 👋!" , c. params ("name")) return c. sendstring (MSG) // => Hello John 👋! }) log.Fatal(app.Listen(":3000")) }Copy the code

📖 Static file service

func main() {
    app := fiber.New()

    app.Static("/", "./public")
    // => http://localhost:3000/js/script.js
    // => http://localhost:3000/css/style.css

    app.Static("/prefix", "./public")
    // => http://localhost:3000/prefix/js/script.js
    // => http://localhost:3000/prefix/css/style.css

    app.Static("*", "./public/index.html")
    // => http://localhost:3000/any/path/shows/index/html

    log.Fatal(app.Listen(":3000"))
}
Copy the code

📖 Middleware and Next

Func main() {app := fiber.new () App.use (func(c * fiber.ctx) error {fmt.println ("🥇 First handler") return c.ext ()}) // Matches all routes starting with/API app.Use("/api", Func (c * fiber.ctx) error {fmt.println ("🥈 Second handler") return c.ext ()}) // Configure multiple middleware to Use app.use ("/ API ",func(c) *fiber.Ctx) error { c.Set("X-Custom-Header", random.String(32)) return c.Next() }, Func (c * fiber.ctx) error {return c.ext ()}) Get("/ API /list", func(c * fiber.ctx) error {fmt.println ("🥉 Last handler") return c.sendString ("Hello, World 👋!" ) }) log.Fatal(app.Listen(":3000")) }Copy the code

📖 Based on the extended example on the official website – Obtaining path parameters (1)

Package the main import (" FMT "" github.com/gofiber/fiber/v2") func main () {app: = fiber. The New () / / define global middleware app. Use (func (c * fiber.ctx) error {fmt.println ("🥇 First 2222handler") return c.ext ()}) app.get ("/:value", func(c *fiber.Ctx) error { return c.SendString("value: " + c.Params("value")) // => Get request with value: hello world }) app.Listen(":3000") }Copy the code

The results of the visit address: http://127.0.0.1:3000/sdf43534 output is:

value: sdf43534
Copy the code

📖 – Obtain the number of paths T (2)

Package the main import (" FMT "" github.com/gofiber/fiber/v2") func main () {app: = fiber. The New () / / define global middleware app. Use (func (c * fiber.ctx) error {fmt.println ("🥇 First 2222Handler ") return c.ext ()}) func(c *fiber.Ctx) error { if c.Params("name") ! = "" { return c.SendString("Hello " + c.Params("name")) // => Hello john } return c.SendString("Where is john?" ) }) app.Listen(":3000") }Copy the code

Results of the interview:

Address: http://127.0.0.1:3000/name results: Hello name = = = = = = = = = = = = address: http://127.0.0.1:3000 results: Where is John?Copy the code

📖 According to the extended example on the official website – Obtain path t number (3) – Wildcard format

Package the main import (" FMT "" github.com/gofiber/fiber/v2") func main () {app: = fiber. The New () / / define global middleware app. Use (func (c * fiber.ctx) error {fmt.println ("🥇 First 2222Handler ") return c.ext ()}) func(c *fiber.Ctx) error { return c.SendString("API path: " + c.Params("*")) // => API path: user/john }) app.Listen(":3000") }Copy the code

Access:

Results: the address: http://127.0.0.1:3000/api/34534/3453 API path: 34534/3453 = = = = = = = = = = = =Copy the code

📖 [added] Multiple applications are similar to flask and FastAPI’s multiple applications!

func main() {
    micro := fiber.New()
    micro.Get("/doe", func(c *fiber.Ctx) error {
        return c.SendStatus(fiber.StatusOK)
    })
    app := fiber.New()
    app.Mount("/john", micro) // GET /john/doe -> 200 OK
    log.Fatal(app.Listen(":3000"))
}
Copy the code

GET/John /doe -> 200 OK

2, Fiber instance object configuration

This official website is a bit not authentic, lock good translation of many languages! Unfortunately, the official website is still in English! Ha ha

That also had to should gnaw!

In fact, the Fiber instance object configuration is the same concept as our fastAPI configuration, which is to initialize our Fiber instance object with special parameters.

2.1 new uses the default configuration

app := fiber.New()
Copy the code

2.2 Customizing Customized personal configuration initialization information

app := fiber.New(fiber.Config{
    Prefork:       true,
    CaseSensitive: true,
    StrictRouting: true,
    ServerHeader:  "Fiber",
})
Copy the code

Prefork: true, :

2.3 Configuring Initialization Information – What are the configuration items?

Pick some noteworthy ones:


  • Prefork: whether to enable multiple processes

    • The default value is false
    • Note: If multi-process mode is enabled, the application will need to run in the shell, because pre-fork mode sets environment variables. If you are using Docker, make sure the application is run with CMD./app or CMD [“sh”, “-c”, “/app”]
    • For example, if multiple processes are enabled:

    Prefork: true, :


  • ServerHeader: The tag header that defines the Server in the response header
    • The default value is:
    • Effect: Enables the Server to use HTTP headers with the given values.
    • For example, write ServerHeader: “Fiber”, :

    Then our request response header will have:


  • CaseSensitive: Routes define matching of case problems
    • The default value is false
    • Function: When enabled, /Foo and /Foo are different routes.

  • Immutable: a case in which context values are described as being reusable or not, and was used by GIN in the past
    • The default value is false
    • Effect: All values returned by context methods are immutable with this enabled. By default, they are valid until returned from the handler

  • UnescapePath: The solution should be the encoding of all the coded characters in the route

  • ETag: Cache issues should be addressed

  • BodyLimit:
  • The default value is 4 x 1024 x 1024 of the int type
  • Effect: Sets the maximum allowed size for the Request body. If the size exceeds the configured limit, it will send a 413-Request Entity Too Large response

  • Concurrency:

    • The default value is 256 x 1024 for int
    • Maximum number of concurrent connections.
  • ReadTimeout:

    • The default value is time.duration
    • Display of timeout for read request completion. Default is unconstrained.
  • WriteTimeout:

    • The default value is time.duration
    • Maximum write response time, default is unconstrained.
  • ReadBufferSize: The size of each connection buffer requested to read

  • DisableKeepalive: Disables Keepalive connection. The server closes the incoming connection after sending the first response to the client.

  • ErrorHandler

  • Default global error exception handling.

2.4 Application static file service

2.4.1 Not Setting a Virtual Path

Configuring static files:

For example, to set a directory for static files:

app.Static("/", "./public")
Copy the code

Complete code:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New(fiber.Config{ Prefork: true, CaseSensitive: true, StrictRouting: true, ServerHeader: "Fiber", }) app.Static("/", Use(func(c * fiber.ctx) error {fmt.println ("🥇 First 2222Handler ") return c.ext ()}) App.get ("/ API /*", func(c * fiber.ctx) error {return c.string ("API path: "+ c.params ("*"))) // => API path: user/john }) app.Listen(":3000") }Copy the code

Direct access:

http://127.0.0.1:3000/
Copy the code

2.4.2 Setting a Virtual Path

Where the path does not actually exist in the file system, static method, static directory to specify a prefix path

Configuring static files:

For example, to set a directory for static files:

	app.Static("/static", "./public")
Copy the code

Complete code:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New(fiber.Config{ Prefork: true, CaseSensitive: true, StrictRouting: true, ServerHeader: "Fiber", }) //app.Static("/", "./public") app.Static("/static", Use(func(c * fiber.ctx) error {fmt.println ("🥇 First 2222Handler ") return c.ext ()}) App.get ("/ API /*", func(c * fiber.ctx) error {return c.string ("API path: "+ c.params ("*"))) // => API path: user/john }) app.Listen(":3000") }Copy the code

Visit address:

http://127.0.0.1:3000/static/hello.html
Copy the code

Results:

2.4.3 More Static Service Configuration Items

Static("/", "./public", fiber.Static{Compress: true, // whether compression is enabled ByteRange: true, // whether ByteRange requests are enabled. Browse: true, // Enable directory browsing Index: "index.html" // Default access CacheDuration: 10 * time.Second,// cache time MaxAge: 3600,})Copy the code

3. Fiber routing and routing group

3.1 Fiber Routing and Routing Group

In fact, the concept is similar to GIN, if you have contact with GIN in fact, the same nature. Complete example:

package main import ( "log" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New(fiber.Config{ Prefork: true, CaseSensitive: true, StrictRouting: true, ServerHeader: "Fiber",}) handler := func(c * fiber.ctx) error {c.set (" x-custom-header ", "saaaaaaaaaa") return c.sendString (" I am your who! 111111!" ) } api := app.Group("/api", handler) // /api v1 := api.Group("/v1", handler) // /api/v1 v1.Get("/list", handler) // /api/v1/list v1.Get("/user", handler) // /api/v1/user v2 := api.Group("/v2", handler) // /api/v2 v2.Get("/list", handler) // /api/v2/list v2.Get("/user", handler) // /api/v2/user log.Fatal(app.Listen(":3000")) app.Listen(":3000") }Copy the code

Specific results:

3.2 Viewing the Routing Information List

package main import ( "encoding/json" "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() //app.Server().MaxConnsPerIP = 1 handler := func(c *fiber.Ctx) error { c.Set("X-Custom-Header", "Saaaaaaaaaa ") return C. sendstring (" I am your who! 111111!" ) } api := app.Group("/api", handler) // /api v1 := api.Group("/v1", handler) // /api/v1 v1.Get("/list", handler) // /api/v1/list v1.Get("/user", handler) // /api/v1/user v2 := api.Group("/v2", // API /v2/list v2.Get("/user", handler) // API /v2/user // print data, _ := json.MarshalIndent(app.Stack(), "", " ") fmt.Println(string(data)) app.Listen(":3000") }Copy the code

The output is:

4. Fiber start monitoring

HTTP startup listening:

In general, the HOST and PORT of our startup can be customized, and Fiber can also be provided:

HOTS+ port app.listen ("127.0.0.1:8080") // Set the listening port to start. The default HOTS is local app.listen (":8080")Copy the code

HTTPS startup listening:

app.ListenTLS(":443", "./cert.pem", "./cert.key");
Copy the code

HTTPS can also be configured:

&tls.Config{
    MinVersion:               tls.VersionTLS12,
    PreferServerCipherSuites: true,
    Certificates: []tls.Certificate{
        cert,
    },
}
Copy the code

Use Net.listen to start

package main import ( "crypto/tls" "net" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() //app.Server().MaxConnsPerIP = 1 handler := func(c *fiber.Ctx) error { c.Set("X-Custom-Header", "Saaaaaaaaaa ") return C. sendstring (" I am your who! 111111!" ) } api := app.Group("/api", handler) // /api v1 := api.Group("/v1", handler) // /api/v1 v1.Get("/list", handler) // /api/v1/list v1.Get("/user", handler) // /api/v1/user v2 := api.Group("/v2", // API /v2/list v2.Get("/user", handler) // API /v2/user // print //data, _ := json.MarshalIndent(app.Stack(), "", " ") //fmt.Println(string(data)) ln, _ := net.Listen("tcp", ":3000") cer, _ := tls.LoadX509KeyPair("server.crt", "server.key") ln = tls.NewListener(ln, &tls.Config{Certificates: []tls.Certificate{cer}}) app.Listener(ln) }Copy the code

5. Fiber request context

5.1 Adding Response Header Information

package main import ( "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() //app.Server().MaxConnsPerIP = 1 app.Get("/", func(c *fiber.Ctx) error { c.Accepts("png") //c.Accepts("json", "Text ") // "json" // c.acepts ("application/json") // "application/json" // new response header information -- the following fields will appear in the response header c.apend ("Link", "Test") c.Append("Link", "http://google.com", "http://localhost") // Return APP routing Stack c.son (c.app.stack ())}) app.listen (":3000")}Copy the code

Results:

Other methods for setting responses c.et () :

app.Get("/", func(c *fiber.Ctx) error {
   c.Set("Content-Type", "text/plain")
   // => "Content-type: text/plain"
   // ...
   c.Vary("Accept-Encoding", "Accept")
})
Copy the code

5.2 Return DATA in JSON format

  return c.JSON(c.App().Stack())
Copy the code

Complete example:

package main

import (
   "github.com/gofiber/fiber/v2"
)

func main() {
   app := fiber.New()

   type SomeStruct struct {
      Name string
      Age  uint8
   }
   app.Get("/json1", func(c *fiber.Ctx) error {
      // Create data struct:
      data := SomeStruct{
         Name: "Grame",
         Age:  20,
      }
      return c.JSON(data)
   })
   app.Get("/json2", func(c *fiber.Ctx) error {
      return c.JSON(fiber.Map{
         "name": "Gram222e",
         "age":  2000,
      })
      
   })

   app.Listen(":3000")
}
Copy the code

Or a chained return:

return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": err.Error(),
})
Copy the code

5.3 Obtaining the requested Baseurl and HotsName

fmt.Println("c.BaseURL()", c.BaseURL())
fmt.Println("c.Hostname()", c.Hostname())

Copy the code

5.4 Obtaining the POST Submittedbodyparameter

Example:

package main


import (
   "fmt"
   "github.com/gofiber/fiber/v2"
)

func main() {
   app := fiber.New()
  
   app.Post("/", func(c *fiber.Ctx) error {
      // Get raw body from POST request:
      return c.Send(c.Body()) // []byte("user=john")
   })

   app.Listen(":3000")
}
Copy the code

Results:

5.5 in the POSTbodyParameter binding resolution

Sample code:

package main import ( "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() //app.Server().MaxConnsPerIP = 1 type Person struct { Name string `json:"name" xml:"name" form:"name"` Pass string `json:"pass" xml:"pass" form:"pass"` }  app.Post("/", func(c *fiber.Ctx) error { p := new(Person) if err := c.BodyParser(p); err ! = nil { return err } return c.JSON(p) }) app.Listen(":3000") }Copy the code

Results:

5.6 Setting and deleting cookies

package main import ( "time" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() //app.Server().MaxConnsPerIP = 1 type Cookie struct { Name string `json:"name"` Value string `json:"value"` Path string `json:"path"` Domain string `json:"domain"` MaxAge int `json:"max_age"` Expires time.Time `json:"expires"` Secure bool `json:"secure"` HTTPOnly bool `json:"http_only"` SameSite string `json:"same_site"` } app.Get("/", func(c *fiber.Ctx) error { cookie := new(fiber.Cookie) cookie.Name = "john" cookie.Value = "doe" cookie.Expires = Time.now ().add (24 * time.hour) // Set cookie c.cookie (cookie) return c.sendString (" Set cookie successfully!" ) }) app.Post("/", Func (c * fiber.ctx) error {// Delete all ClearCookie c.clear cookie () // delete c.clear cookie ("user") return based on key/value pairs C. sendString (" Cookie deleted successfully!" ) }) app.Listen(":3000") }Copy the code

5.7 Downloading and Sending Files

  • Download file sample code:
package main import ( "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() //app.Server().MaxConnsPerIP = 1 app.Get("/", func(c *fiber.Ctx) error { //return c.Download("./files/report-12345.pdf"); // => Download report-12345.pdf return c.daownLoad ("./小 school.txt ", Download report.pdf}) app.listen (":3000")}Copy the code

Results:


  • Example code for sending a file:

Transfers files from the given path. Sets the content-type response HTTP header field

PS: When sending files, gzipping compression is enabled by default. To disable this function, set it to false, as shown in the following figure

c.SendFile("./static/index.html", false);
Copy the code

Demo file structure:

Sample code:

package main

import (
   "github.com/gofiber/fiber/v2"
)

func main() {
   app := fiber.New()
   app.Get("/sendfile", func(c *fiber.Ctx) error {
      return c.SendFile("./public/hello.html")
      // Disable compression
      //return c.SendFile("./static/index.html", false);
   })

   app.Listen(":3000")
}
Copy the code

Perform:

5.8 Uploading files – Obtain the form file content

The paper says:

  • 1: form-data is used to upload parameters in the form of key-value pairs. Parameters are separated by ampersand (&). Files can also be uploaded.

  • 2: x-www-form-urlencode can only be passed as key-value pairs, but cannot be passed to files.

Retrieve the MultipartForm file by name, first returning the file from the given key

Sample code:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() //app.Server().MaxConnsPerIP = 1 app.Post("/", func(c *fiber.Ctx) error { // Get first file from form field "document": / / MultipartForm (). This will return a map[string][] String file, _ := c.vormfile ("5gmsg.conf") // Save file to root directory: Println(" file name ", file.filename) return c.savefile (file, fmt.sprintf ("./%s", file.filename))}) app.listen (":3000")}Copy the code

Code execution result:

After uploading:

5.9 Receiving Multiple Files – Obtain the form file content

Sample code:

``` package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Post("/", Func (c * fiber.ctx) error {//MultipartForm(). This returns a map[string][] String if form, err := c.multiPartForm (); Err == nil {FMT.Println(" output form info,", form) files := form.File["5gmsg.conf"] FMT.Println(" output files Info,", files) for _, file := range files { fmt.Println(file.Filename, file.Size, file.Header["Content-Type"][0]) if err := c.SaveFile(file, fmt.Sprintf("./%s", file.Filename)); err ! = nil {return c.endString (" Upload failed!" }}} return c. sendString (" Upload successful!" ) }) app.Listen(":3000") } ```Copy the code

Code execution result:

After uploading:

5.10 Obtaining form value content Information

Sample code:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Post("/", Func (c * fiber.ctx) error {//MultipartForm(). This returns a map[string][]string fmt.Println("name form value information ", c.formValue ("name")) fmt.Println("age form value information ", Sprintf("%s-%s-%s", "the form value is: ", c.FormValue("name"), c.FormValue("age"))) }) app.Listen(":3000") }Copy the code

Output result:

5.11 Obtaining User-defined Request Header Information

Sample code:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Get("/", Func (c * fiber.ctx) error {//MultipartForm(). This will return a map[string][]string c. set (" content-type ") // "text/plain" return c. sendString (FMT.Sprintf("%s-%s-%s", "The request header is: ", c.Get("Content-Type"), c.Get("xiaozhong"))) }) app.Listen(":3000") }Copy the code

Example:

5.12 Obtaining The IP Address Requested by a Client

c.IP(), c.IPs()
Copy the code

Sample code:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Get("/", Func (c * fiber.ctx) error {//MultipartForm(). Sprintf("%s-%s-%s", "Request IP information is: ", c.IP(), c.IPs())) }) app.Listen(":3000") }Copy the code

Execution screenshot:

5.13 Determine the Content-Type and whether an XHR request is received

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Get("/", Func (c * fiber.ctx) error {c.I. S (" HTML ") // true c.I. S (".html") // true c.I. S ("json") // false c.xhr () // Check whether XHRjQuery is committed Sprintf("%s-%s-%s"," ", c.Is("html"), c.Is(".html"), c.Is("json"))) }) app.Listen(":3000") }Copy the code

5.14 Storage variable transfer (Information transfer between middleware)

This is actually very useful for the subsequent authentication drop, such as my authentication completed, wear the TOKEN to the next interface!

Sample code:

Package the main import (" github.com/gofiber/fiber/v2 ") func main () {app: = fiber. The New () / / global middleware in our information - setting a parameter value App.use (func(c * fibre.ctx) error {c.loop ("user", "c * fibre.ctx ") return c.ext ()}) app.get ("/", func(c *fiber.Ctx) error { return c.JSON(fiber.Map{ "name": c.Locals("user"), "age": 2000, }) }) app.Listen(":3000") }Copy the code

Execution Result:

5.15 Redirection for 301 or 302


Sample code:

Package the main import (" github.com/gofiber/fiber/v2 ") func main () {app: = fiber. The New () / / global middleware in our information - setting a parameter value app.Get("/coffee", func(c *fiber.Ctx) error { return c.Redirect("/teapot") }) app.Get("/teapot", Func (c * fiber.ctx) error {return c.status (fiber.statusteapot).sendString (" I am redirected!" ) }) app.Listen(":3000") }Copy the code

Access address: http://127.0.0.1:3000/coffee execution result:


Other examples:

app.Get("/", func(c *fiber.Ctx) error { return c.Redirect("/foo/bar") return c.Redirect(".. /login") return c.Redirect("http://example.com") return c.Redirect("http://example.com", 301) })Copy the code

5.16 Params Parameter – Obtains the path parameter


Code examples:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Get("/user/:name", Func (c * fiber.ctx) error {c.params ("name") return c.sendString (fmt.sprintf ("%s-%s", ", c.Params("name"))) }) app.Listen(":3000") }Copy the code

Visit address:

http://127.0.0.1:3000/user/nihao
Copy the code

Execution Result:


Examples of complex matching:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Get("/user/:name", Func (c * fiber.ctx) error {c.params ("name") return c.sendString (fmt.sprintf ("%s-%s", ", c.Params("name"))) }) app.Get("/user2/*", func(c *fiber.Ctx) error { return c.SendString(fmt.Sprintf("%s-%s-%s", "For path parameter name value:", c.P arams (" * "), c.P arams (" * 1 ")))}) app. Listen: "3000")}Copy the code

Accessible address:

http://127.0.0.1:3000/user2/nihao/3453
http://127.0.0.1:3000/user2/nihao3453
http://127.0.0.1:3000/user2/nihao=3453
Copy the code

5.17 Obtaining Query and QueryParser Parameters


Example of obtaining parameters:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Get("/user", Func (c * fibre.ctx) error {return c. sendString (fmt.sprintf ("%s-%s-%s"," ", c.Query("name"), c.Query("age"))) }) app.Listen(":3000") }Copy the code

The request returns:


Example binding resolution:

package main import ( "github.com/gofiber/fiber/v2" ) type Person struct { Name string `query:"name"` Age string `query:"age"` } func main() { app := fiber.New() app.Get("/user", func(c *fiber.Ctx) error { p := new(Person) if err := c.QueryParser(p); err ! = nil { return err } return c.JSON(p) }) app.Listen(":3000") }Copy the code

Request execution:


Get is the request path and parameter information:

package main import ( "fmt" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Get("/user", Func (c * fiber.ctx) error {return c.endString ("%s-%s"," ", c.OriginalURL())) }) app.Listen(":3000") }Copy the code

Execution Result:

5.18 Response byte stream data

Sample code:

package main import ( "bytes" "github.com/gofiber/fiber/v2" ) func main() { app := fiber.New() app.Get("/", func(c *fiber.Ctx) error { return c.Send([]byte("Hello, World!" )) // => "Hello, World!" }) app.Get("/user", func(c *fiber.Ctx) error { return c.SendStream(bytes.NewReader([]byte("Hello, World!" ))) // => "Hello, World!" }) app.Listen(":3000") }Copy the code

Appending to byte stream information:

Get("/ok1", func(c * fibre.ctx) error {c.wowrite ([]byte("Hello, World! 111")) // => "Hello, World!" c.Write([]byte("Hello, World! 222")) // => "Hello, World!" c.Status(200) return nil })Copy the code

Execution Result:

5.19 Setting response Code and response body at the same time

Sample code:

Package main import (" github.com/gofiber/fiber/v2 ") func main () {app: = fiber. The New () / / just set the response code information app. Get ("/ok1 ", func(c *fiber.Ctx) error { c.Status(200) return nil }) app.Get("/ok2", func(c *fiber.Ctx) error { return c.Status(400).SendString("Bad Request") }) app.Get("/ok3", func(c *fiber.Ctx) error { return c.Status(404).SendFile("./public/gopher.png") }) app.Listen(":3000") }Copy the code

5.20 Customizing error response handling of 404

PS: key pit point: this custom 404, you need to put when all routes are registered before it can be used, otherwise all its addresses will not be found! PS: key pit point: this custom 404, you need to put when all routes are registered before it can be used, otherwise all its addresses will not be found! PS: key pit point: this custom 404, you need to put when all routes are registered before it can be used, otherwise all its addresses will not be found!

The main use of middleware to deal with.

Example code for this rule:

package main import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/recover" ) func main() { app := fiber.new () // // Pay attention to !!!!! // Pay attention to !!!!! app.Use(func(c *fiber.Ctx) error { return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ "code": "404", "msg": "Can't find the address! You must have the wrong address!" Get("/ok1", func(c * fiber.ctx) error {return c.status (200).sendString (" log!! ") Use(recover.new (recover.config) {//Next: func(c *fiber.Ctx) bool { // return c.Query("refresh") == "true" //}, EnableStackTrace: true, StackTraceHandler: Func (e interface{}) {stack info},})) // This panic will be caught by the middleware app.get ("/", func(c *fiber.Ctx) error { panic("I'm an error") }) app.Listen(":3000") }Copy the code

The correct one is put at the end:

package main import ( "fmt" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/recover" ) func main()  { app := fiber.New(fiber.Config{ ErrorHandler: func(c *fiber.Ctx, err error) error { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "code": fiber.StatusInternalServerError, "msg": Err.error ()},)},}) app.get ("/ok1", func(c * fiber.ctx) Error {return c.status (200).sendString (" Log!!" Use(recover.new (recover.config) {//Next: func(c *fiber.Ctx) bool { // return c.Query("refresh") == "true" //}, EnableStackTrace: true, StackTraceHandler: Func (e interface{}) {stack info},})) // This panic will be caught by the middleware app.get ("/", Func (c * fibre.ctx) error {panic(" yes!" }) // Put it last! app.Use(func(c *fiber.Ctx) error { fmt.Println(c) return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ "code": "404", "MSG ":" Can't find this address! You must have the wrong address!" , }) }) app.Listen(":3000") }Copy the code

Perform access:

6. Fiber Middleware

From the official website of the document moving brick series!

6.1 introduction:

Fiberv1 and Fiberv2 have different middleware,

Middleware in Fiberv2 must have return c.ext ()!

In fact, this middleware and we know fastAPI and gin’s general function is the same, are similar to the hook function.

FiberV2 has a lot of middleware built in itself:

  • Middleware for basic username and password authentication – BasicAuth
  • Cache middleware – Cache
  • Intermediate component used for compression – Compress
  • Cross-domain middleware – CORS
  • Middleware for out-of-date Settings – ETag
  • Middleware that sets access to Favicon ICONS
  • Configure some configuration information middleware for static file services -# FileSystem
  • Current Limiting middleware -# Limiter
  • Performance Analysis Middleware -# Pprof
  • Logging middleware -# Logger
  • Global exception catch Recover middleware
  • The proxy requests access to the middleware
  • Global link tracking RequestID middleware
  • Session processing middleware
  • Timeout middleware for interface request Timeout limits

Below I begin to move brick!! I’ll just pick a few to talk about! One by one practice to see the specific middleware gameplay!

6.2 BasicAuth User Name and password based authentication middleware

First of all, BasicAuth is actually the request when you need to provide the username and account, to verify!

Sample code:

package main import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/basicauth" ) func main() { ----- simple configuration app.use (basicauth.new (basicauth.config {Users:) map[string]string{ "name": "xiaozhong", "password": "123456",},})) // Just set the response code information app.get ("/ok1", Func (c * fiber.ctx) error {return c.status (200).SendString(" Basicauth authentication successfully!!" ) }) app.Listen(":3000") }Copy the code

Browser access! Then access the address:

You need to provide the username and password:

package main import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/basicauth" ) func main() { ----- simple configuration app.use (basicauth.new (basicauth.config {Users:) map[string]string{ "xiaozhong": "123456", "tongxue": "123456", }, Realm: "Forbidden", Authorizer: func(user, pass string) bool { if user == "xiaozhong" && pass == "123456" { return true } if user == "tongxue" && pass == "123456" {return true} return false}, // Authentication failed, the machine makes it pop-up window !!!!! //Unauthorized: func(c * fiber.ctx) error {// // return c.status (200).SendString(" Basicauth authentication failure !!!! Illegal access!" ) //}, ContextUsername: "_user", ContextPassword: Get("/ok1", func(c * fiber.ctx) error {return c.status (200).sendString (" Basicauth authentication successfully processed! !" ) }) app.Listen(":3000") }Copy the code

Enter a user name and password:

6.3 Cross-domain Middleware

  • Cross-domain default configuration
var ConfigDefault = Config{
   Next:             nil,
   AllowOrigins:     "*",
   AllowMethods:     "GET,POST,HEAD,PUT,DELETE,PATCH",
   AllowHeaders:     "",
   AllowCredentials: false,
   ExposeHeaders:    "",
   MaxAge:           0,
}
Copy the code
  • Cross-domain middleware usage
package main import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" ) func main() { app :=  fiber.New() app.Use(cors.New()) // Or extend your config for customization app.Use(cors.New(cors.Config{ AllowOrigins: "https://gofiber.io, https://gofiber.net", AllowHeaders: "Origin, content-type, Accept",})) app.get ("/ok1", Func (c * fiber.ctx) error {return c.status (200).SendString(" Basicauth authentication successfully!!" ) }) app.Listen(":3000") }Copy the code

6.4 Traffic Limiting Middleware

  • Default configuration of traffic limiting components
var ConfigDefault = Config{
   Max:        5,
   Expiration: 1 * time.Minute,
   KeyGenerator: func(c *fiber.Ctx) string {
      return c.IP()
   },
   LimitReached: func(c *fiber.Ctx) error {
      return c.SendStatus(fiber.StatusTooManyRequests)
   },
}
Copy the code
  • Flow limiting middleware uses:

Example: Maximum 2 accesses in 5 seconds!

package main import ( "time" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/limiter" ) func Main () {app := fibre.new () app.use (limiter.New(limiter.Config{Next: nil, Max: 2, // Expiration: 5 * time.Second, KeyGenerator: func(c *fiber.Ctx) string { return c.Get("x-forwarded-for") }, LimitReached: Func (c * fiber.ctx) error {return c.status (429).SendString(" your access is so fast!!" ) }, //Store: MyCustomStore {}})) // Just set the response code information app.get ("/ok1", Func (c * fiber.ctx) error {return c.status (200).SendString(" Basicauth authentication successfully!!" ) }) app.Listen(":3000") }Copy the code

When over:Normal:

6.5 Logging Middleware

The documentation on the official website hints at a number of parameters:

It even includes the response body!! Don’t need me fastAPI that also need to write a time!! It seems possible! Ha ha

For example, the following constant information can be recorded in logs:

// Logger variables const ( TagPid = "pid" TagTime = "time" TagReferer = "referer" TagProtocol = "protocol" TagIP = "ip"  TagIPs = "ips" TagHost = "host" TagMethod = "method" TagPath = "path" TagURL = "url" TagUA = "ua" TagLatency = "latency" TagStatus = "status" // response status TagResBody = "resBody" // response body TagQueryStringParams = "queryParams" // request query parameters TagBody = "body" // request body TagBytesSent = "bytesSent" TagBytesReceived =  "bytesReceived" TagRoute = "route" TagError = "error" TagHeader = "header:" // request header TagQuery = "query:" // request query TagForm = "form:" // request form TagCookie = "cookie:" // request cookie TagLocals = "locals:" // colors TagBlack = "black" TagRed = "red" TagGreen = "green" TagYellow = "yellow" TagBlue = "blue" TagMagenta = "magenta" TagCyan = "cyan" TagWhite = "white" TagReset = "reset" )Copy the code

The default logging middleware configuration:

var ConfigDefault = Config{
   Next:         nil,
   Format:       "[${time}] ${status} - ${latency} ${method} ${path}\n",
   TimeFormat:   "15:04:05",
   TimeZone:     "Local",
   TimeInterval: 500 * time.Millisecond,
   Output:       os.Stderr,
}
Copy the code
  • Next: Handles whether to pass to the Next and can be customized
  • Format: Defines the log Format
  • TimeFormat: TimeFormat for logging
  • TimeZone: indicates the TimeZone in which logs are recorded
  • TimeInterval: Time is that
  • Output: Where to Output, default is console

Default log configuration

app.Use(logger.New())
Copy the code

The request interface console then outputs a log message:

Add global trace ID logging configuration

package main import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/requestid" ) func main() { app := fiber.New() app.Use(requestid.New()) app.Use(logger.New(logger.Config{ Format: "${pid} ${locals:requestid} ${status} - ${method} ${path}\n", TimeFormat: "02-Jan-2006", TimeZone: Get("/ok1", func(c * fiber.ctx) error {return c.status (200).sendString (" log!! ") ) }) app.Listen(":3000") }Copy the code

In the example above, after executing, I see no Requestid at all

So go ahead and try it out:

package main import ( "log" "os" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/requestid" ) func main() { app := fiber.New() app.Use(requestid.New()) file, err := os.OpenFile("./req.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err ! = nil { log.Fatalf("error opening file: %v", err) } defer file.Close() app.Use(logger.New(logger.Config{ Format: "${pid} ${locals:requestid} ${status} - ${method} ${path}\n", TimeFormat: "02-Jan-2006", TimeZone: "Asia/Shanghai", Output: Get("/ok1", func(c * fiber.ctx) error {return c.status (200).sendString (" log!! ") ) }) app.Listen(":3000") }Copy the code

Check out our log file /req.log:

15784 9e7bd80c-4198-4d3e-800a-7fef42810a55 200 - GET /ok1
15784 9f7bd80c-4198-4d3e-800a-7fef42810a55 200 - GET /ok1
15784 a07bd80c-4198-4d3e-800a-7fef42810a55 200 - GET /ok1
Copy the code

Yeah, I kind of read !!!!

6.6 Global Exception Middleware

  • Default configuration information:
var ConfigDefault = Config{
   Next:              nil,
   EnableStackTrace:  false,
   StackTraceHandler: defaultStackTraceHandler,
}
Copy the code

Example:

package main import ( "github.com/gofiber/fiber/v2/middleware/recover" "github.com/gofiber/fiber/v2" ) func main() { app Get("/ok1", func(c * fiber.ctx) error {return c.status (200).sendString (" log!! ") ) }) app.Use(recover.New()) // This panic will be catch by the middleware app.Get("/", func(c *fiber.Ctx) error { panic("I'm an error") }) app.Listen(":3000") }Copy the code

Execution Result:

There is a question here, I want to capture my own definition of how reality is displayed? A custom example:

package main import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/recover" ) func main() { app Get("/ok1", func(c * fiber.ctx) error {return c.status (200).sendString (" log!! ") Use(recover.new (recover.config) {//Next: func(c *fiber.Ctx) bool { // return c.Query("refresh") == "true" //}, EnableStackTrace: true, StackTraceHandler: Func (e interface{}) {stack info},})) // This panic will be caught by the middleware app.get ("/", func(c *fiber.Ctx) error { panic("I'm an error") }) app.Listen(":3000") }Copy the code

Still a little confused? What if the global processing is wrong? Our fibre. New configuration item actually has an ErrorHandler, we just need to define our own handler in this place!!

Custom global exception handlers:

package main import ( "fmt" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/recover" ) func main()  { app := fiber.New(fiber.Config{ // Override default error handler ErrorHandler: Func (CTX * fiber CTX, err error) error {/ / get the current exception response code code: = fiber. StatusInternalServerError / / if there is one custom response code, If e, ok := err.(* fibre.error); Ok {code = e.code} fmt.println (code) fmt.println (err) // Send custom error response page //err = ctx.Status(code).SendFile(fmt.Sprintf("./%d.html", code)) err = ctx.JSON(fiber.Map{ "code": code, "msg": Err.error (),}) // If the page cannot be found, then some other exception if err! = nil {/ / In case the SendFile fails return CTX. Status (fiber. StatusInternalServerError). SendString (" programmer brother sleep deprivation, a system crash!" } // return nil},}) // Just set the response code information app.get ("/ok1", Func (c * fiber.ctx) error {return c.status (200).sendString (" log!!" Use(recover.new (recover.config) {//Next: func(c *fiber.Ctx) bool { // return c.Query("refresh") == "true" //}, EnableStackTrace: true, StackTraceHandler: Func (e interface{}) {stack info},})) // This panic will be caught by the middleware app.get ("/", Func (c * fiber.ctx) error {panic(" I did it on purpose!" ) }) app.Listen(":3000") }Copy the code

Then access validation:

6.7 Global Exception Middleware – Extracts global error handling problems

app := fiber.New(fiber.Config{
   ErrorHandler: func(c *fiber.Ctx, err error) error {
      return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
         "code": 500,
         "msg":  err.Error()},
      )
   },
})
Copy the code

3. Summary


The above is just a personal combination of the official website to do a series of practice summary comb, if there are clerical errors! Welcome criticism and correction! Thank you!

Code word is not easy, or you like bai Ha ha!

At the end

END

Jane: www.jianshu.com/u/d6960089b…

The Denver nuggets: juejin. Cn/user / 296393…

Public account: wechat search [children to a pot of wolfberry wine tea]

Let students | article | QQ: welcome to learn communication 】 【 308711822