การเส้นทาง (Routing)
บทบาทของการเส้นทางในกรอบ Go Fiber คือการผูก URL ต่าง ๆ กับฟังก์ชันการจัดการเพื่อรองรับการประมวลผลคำขอ HTTP ซึ่งเป็นจุดเริ่มต้นสำหรับการขอข้อมูลเว็บโฟร์เฟรมทั้งหมด
ผู้จัดการเส้นทาง (Functions)
ลงทะเบียนเส้นทางที่ผูกกับเมธอด HTTP ที่แน่นอน
หมายเหตุ: ในบางกรอบการทำงาน เส้นทางผู้จัดการถูกเรียกว่าตัวควบคุม (controllers) ซึ่งมักจะมีความหมายเดียวกัน คือ การกำหนดฟังก์ชัน (เมธอด) ที่จะจัดการคำขอ HTTP เข้า
ลายเซ็นเจ้าของฟังก์ชัน:
// เมธอด HTTP
func (app *App) Get(path string, handlers ...Handler) Router
func (app *App) Head(path string, handlers ...Handler) Router
func (app *App) Post(path string, handlers ...Handler) Router
func (app *App) Put(path string, handlers ...Handler) Router
func (app *App) Delete(path string, handlers ...Handler) Router
func (app *App) Connect(path string, handlers ...Handler) Router
func (app *App) Options(path string, handlers ...Handler) Router
func (app *App) Trace(path string, handlers ...Handler) Router
func (app *App) Patch(path string, handlers ...Handler) Router
// Add ช่วยให้คุณระบุเมธอดเป็นค่า
func (app *App) Add(method, path string, handlers ...Handler) Router
// ทั้งหมดจดทะเบียนเส้นทางทั้งหมดของ HTTP เมธอด
// คล้ายกับ app.Use แต่ไม่ผูกคำนำหน้า
func (app *App) All(path string, handlers ...Handler) Router
ตัวอย่าง:
// ผู้จัดการ GET ง่าย ๆ
app.Get("/api/list", func(c *fiber.Ctx) error {
return c.SendString("นี่คือคำขอ GET!")
})
// ผู้จัดการ POST ง่าย ๆ
app.Post("/api/register", func(c *fiber.Ctx) error {
return c.SendString("นี่คือคำขอ POST!")
})
Use ถูกใช้ในการโหลด middleware และฟังก์ชันป้อนตัวกระทา พวกระทดีแค่ตรงเริงแต่แถินของแต่ละเส้นทางเท่านั้น เช่น /john
จะตรงกับ /john/doe
, /johnnnnn
, และอื่น ๆ
ลายเซ็น middleware ที่กำหนดเอง:
func (app *App) Use(args ...interface{}) Router
ตัวอย่าง:
// ตรงกับคำขอใด ๆ
app.Use(func(c *fiber.Ctx) error {
return c.Next()
})
// ตรงกับคำขอที่เริ่มด้วย /api
app.Use("/api", func(c *fiber.Ctx) error {
return c.Next()
})
// ตรงกับคำขอที่เริ่มด้วย /api หรือ /home (รองรับคำนำหน้าหลายตำนะ)
app.Use([]string{"/api", "/home"}, func(c *fiber.Ctx) error {
return c.Next()
})
// เพิ่มผู้จัดการหลายคน
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.Next()
})
เส้นทาง (Path)
เส้นทางเส้นทางร่วมกับเมธอดการขอไลน์นั้นกำหนดจุดสิ้นสุดที่สามารถเข้าถึงได้ เส้นทางเส้นทางอาจเป็น สตริง หรือ รูปแบบสตริง
ตัวอย่างเส้นทางที่ใช้สตริงเป็นพื้นฐาน
// เส้นทางนี้จะตรงกับคำขอไปยังเส้นหลัก, "/":
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("เส้นทางหลัก")
})
// เส้นทางนี้จะตรงกับคำขอไปยัง "/about":
app.Get("/about", func(c *fiber.Ctx) error {
return c.SendString("เกี่ยวกับ")
})
// เส้นทางนี้จะตรงกับคำขอไปยัง "/random.txt":
app.Get("/random.txt", func(c *fiber.Ctx) error {
return c.SendString("Random.txt")
เหมือนกับกรอบ expressJs ลำดับ ในการประกาศเส้นทางมีความสำคัญ เมื่อได้รับคำขอ จะตรวจสอบเส้นทางในลำดับที่ประกาศ
โปรดทราบ: ตรวจสอบว่าเส้นทางที่มีพารามิเตอร์แปรต้องเขียนหลังเส้นทางที่มีส่วนคงที่เพื่อป้องกันไม่ให้ชิ่วของพารามิเตอร์ดังกล่าวถูกตรงตราไปที่ส่วนที่คงที่ซึ่งอาจเป็นสาเหตุของการทำงานที่ไม่คาดคิด และอาจนำไปสู่พฤติกรรมที่ไม่คาดคิด
พารามิเตอร์ของเส้นทาง
พารามิเตอร์ของเส้นทางเป็นองค์ประกอบที่เปลี่ยนไปในเส้นทางและสามารถเป็นได้ทั้ง ชื่อ หรือ คนละหมู่ ที่ใช้เพื่อจับค่าที่ตำแหน่งที่ระบุใน URL คุณสามารถใช้ฟังก์ชัน Params เพื่อเรียกดึงค่าเหล่านี้ ซึ่งพารามิเตอร์ของฟังก์ชันคือชื่อของพารามิเตอร์ของเส้นทางในเส้นทาง หรือสำหรับพารามิเตอร์ที่ไม่มีชื่อ คือตัวอักษร (*, +) และจำนวนของมัน
Wildcard (*) หรือเครื่องหมายพลัส (+) แทนพารามิเตอร์ที่เรียกร้อย
เส้นทางยังมีความเป็นไปได้ในการใช้พารามิเตอร์ที่เป็นไปได้ สำหรับพารามิเตอร์ที่มีชื่อ พารามิเตอร์เหล่านี้ตามหลังโดยคำถาม (?) ในขณะที่เครื่องหมายพลัสไม่ใช่ได้เลือกใช้ตัวอักษรสุ่มเพื่อแทนพารามิเตอร์ที่เป็นไปได้และเรียกร้อย
ตัวอย่างการกำหนดเส้นทางพร้อมพารามิเตอร์ของเส้นทาง
// พารามิเตอร์
app.Get("/user/:name/books/:title", func(c *fiber.Ctx) error {
fmt.Fprintf(c, "%s\n", c.Params("name"))
fmt.Fprintf(c, "%s\n", c.Params("title"))
return nil
})
// พลัส - เรียกร้อย - ไม่เลือกใช้
app.Get("/user/+", func(c *fiber.Ctx) error {
return c.SendString(c.Params("+"))
})
// พารามิเตอร์ที่เป็นไปได้
app.Get("/user/:name?", func(c *fiber.Ctx) error {
return c.SendString(c.Params("name"))
})
// พร้อมพารามิเตอร์ ที่เรียกร้อย ที่เป็นไปได้
app.Get("/user/*", func(c *fiber.Ctx) error {
return c.SendString(c.Params("*"))
})
// เส้นทางนี้จะตรงกับคำขอ "/v1/some/resource/name:customVerb" เพราะว่าตัวอักษรพารามิเตอร์ถูกหนีบ
app.Get(`/v1/some/resource/name\:customVerb`, func(c *fiber.Ctx) error {
return c.SendString("สวัสดี ชุมชน")
})
เนื่องจากเครื่องหมายขีดล่าง (-) และจุด (.) ถูกตีความไร้อยุำจริง พวกเครื่องหมายเหล่านี้สามารถใช้ร่วมกับพารามิเตอร์ของเส้นทางเพื่อให้ได้ประโยชน์
ตัวอักษรพารามิเตอร์ทางพิเศษทั้งหมดยังสามารถหนีลํเวยใช้
\
และค่าของพวกนี้จะถูกละเลย เพื่อนถ้าคุณต้องการใช้พวกมันในเส้นทาง แนะนำให้ใช้เป็น backticks ``, ตามเอกสารของ Go regular expression พวกมันถูกใช้เสมอเพื่อให้แน่ใจว่าไม่มีความกำกวม และตัวอักษรหนีไม่มีผลต่อเครื่องหมายของ regular expression pattern
// http://localhost:3000/plantae/prunus.persica
app.Get("/plantae/:genus.:species", func(c *fiber.Ctx) error {
fmt.Fprintf(c, "%s.%s\n", c.Params("genus"), c.Params("species"))
return nil // prunus.persica
})
// http://localhost:3000/flights/LAX-SFO
app.Get("/flights/:from-:to", func(c *fiber.Ctx) error {
fmt.Fprintf(c, "%s-%s\n", c.Params("from"), c.Params("to"))
return nil // LAX-SFO
})
สเมารท์เราท์ของเราจะรับรู้ว่าตัวอักษรพารามิเตอร์ที่ถูกเสนอในกรณีนี้ควรเป็นส่วนหนึ่งของเส้นทาไฟน์และสามารถจัดการได้แบบนั้น
// http://localhost:3000/shop/product/color:blue/size:xs
app.Get("/shop/product/color::color/size::size", func(c *fiber.Ctx) error {
fmt.Fprintf(c, "%s:%s\n", c.Params("color"), c.Params("size"))
return nil // blue:xs
})
นอกจากนี้ เส้นทางสามารถใช้พารามิเตอรที่หลายตัวและตัวอักษรพารามิเตอร์ที่ไร้ชื่อหลายตัวติดต่อกันได้ เช่น ตัวอักษรสุ่มหรือเครื่องหมายพลัส ทำให้เป็นไปได้ที่มากขึ้นสำหรับผู้ใช้ในเส้นทาง
// GET /@v1
// Params: "sign" -> "@", "param" -> "v1"
app.Get("/:sign:param", handler)
// GET /api-v1
// Params: "name" -> "v1"
app.Get("/api-:name", handler)
// GET /customer/v1/cart/proxy
// Params: "*1" -> "customer/", "*2" -> "/cart"
app.Get("/*v1*/proxy", handler)
// GET /v1/brand/4/shop/blue/xs
// Params: "*1" -> "brand/4", "*2" -> "blue/xs"
app.Get("/v1/*/shop/*", handler)
เราได้ปรับการสะดวกใช้เส้นทางไปให้รอบ Express แล้วแต่เรายังไม่รองรับเข้าไปที่ regular expressions เพราะพวกมันเร็วน้อยลง
ข้อจำกัด
เมื่อ URL ขาเข้ามีการตรงกันและเส้นทาง URL ถูกแบ่งเป็นค่าเส้นทางผ่านพารามิเตอร์มูล, เงื่อนไขจะถูกดำเนินการ คุณลักษณะนี้ถูกนำเสนอใน v2.37.0
และได้รับแรงบัลลาดจาก .NET Core.
เงื่อนไขนั้นไม่ได้ใช้สำหรับการตรวจสอบพารามิเตอร์ หากเงื่อนไขไม่ถูกต้องสำหรับค่าพารามิเตอร์, Fiber จะส่งกลับ 404 handler.
เงื่อนไข | ตัวอย่าง | ตัวอย่างที่ตรงกัน |
---|---|---|
int | :id |
123456789, -123456789 |
bool | :active |
true, false |
guid | :id |
CD2C1638-1638-72D5-1638-DEADBEEF1638 |
float | :weight |
1.234, -1,001.01e8 |
minLen(value) | :username<minLen(4)> | test (อย่างน้อย 4 ตัวอักษร) |
maxLen(value) | :filename<maxLen(8)> | MyFile (สูงสุด 8 ตัวอักษร) |
len(length) | :filename<len(12)> | somefile.txt (12 ตัวอักษร) |
min(value) | :age<min(18)> | 19 (ค่าจำนวนเต็มต้องอยู่อย่างน้อยที่ 18) |
max(value) | :age<max(120)> | 91 (ค่าจำนวนเต็มไม่สามารถเกิน 120) |
range(min,max) | :age<range(18,120)> | 91 (ค่าจำนวนเต็มจำเป็นต้องอยู่อย่างน้อยที่ 18 แต่ไม่สามารถเกิน 120) |
alpha | :name |
Rick (สตริงจะต้องประกอบด้วยตัวอักษรอักษรตัวพิมพ์เล็กหรือใหญ่ ที่มีแทนกันขึ้นอย่างน้อยหนึ่งตัว) |
datetime | :dob<datetime(2006\\-01\\-02)> | 2005-11-01 |
regex(expression) | :date<regex(\d{4}-\d{2}-\d{2})> | 2022-08-27 (จะต้องตรงกับ regular expression) |
ตัวอย่าง
- เงื่อนไขเดี่ยว
- เงื่อนไขหลายอัน
- เงืนไข regular expression
app.Get("/:test", func(c *fiber.Ctx) error {
return c.SendString(c.Params("test"))
})
// curl -X GET http://localhost:3000/12 // 12
// curl -X GET http://localhost:3000/1 // ไม่พบ GET /1
คุณสามารถใช้ `;` เพื่อเพิ่มเงื่อนไขหลายอัน
app.Get("/:test", func(c *fiber.Ctx) error { return c.SendString(c.Params("test")) })
// curl -X GET http://localhost:3000/120000 // ไม่พบ GET /120000
// curl -X GET http://localhost:3000/1 // ไม่พบ GET /1
// curl -X GET http://localhost:3000/250 // 250
Fiber ทำการคอมไพล์ regular expression queries ล่วงหน้าเมื่อลงทะเบียนเส้นทาง, ทำให้ไม่มีความล่าช้าในประสิทธิภาพสำหรับเงื่อนไข regular expression.
```go
app.Get(`/:date`, func(c *fiber.Ctx) error {
return c.SendString(c.Params("date"))
})
// curl -X GET http://localhost:3000/125 // ไม่พบ GET /125
// curl -X GET http://localhost:3000/test // ไม่พบ GET /test
// curl -X GET http://localhost:3000/2022-08-27 // 2022-08-27
> เมื่อใช้เงื่อนไข date-time (`*`,`+`,`?`,`:`,`/`, `_`,``,`>`,';`,`(`,`)`), ให้ใช้ `\\` ก่อนการใช้ตัวอักษรพิเศษในเส้นทางเพื่อหลีกเลี่ยงการเข้าใจผิดพลาด.
**ตัวอย่างพารามิเตอร์ที่เลือกได้**
คุณยังสามารถเพิ่มเงื่อนไขให้กับพารามิเตอร์ที่เลือกได้.
```go
app.Get("/:test?", func(c *fiber.Ctx) error {
return c.SendString(c.Params("test"))
})
// curl -X GET http://localhost:3000/42
// 42
// curl -X GET http://localhost:3000/
//
// curl -X GET http://localhost:3000/7.0
// ไม่พบ GET /7.0
มิดเดิลแวร์ (Middleware)
ฟังก์ชันที่ออกแบบมาเพื่อจัดการกับคำขอหรือการตอบกลับเรียกว่า middleware functions Next
เป็นฟังก์ชันเส้นทางของ Fiber ที่เมื่อเรียกใช้งานจะ execute next
ฟังก์ชันที่ตรงกับเส้นทางปัจจุบัน
ตัวอย่างของฟังก์ชัน Middleware
app.Use(func(c *fiber.Ctx) error {
// Set a custom header in all responses:
c.Set("X-Custom-Header", "Hello, world")
// Proceed to the next middleware:
return c.Next()
})
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, world!")
})
เส้นทางสำหรับเมทอด Use
สามารถเป็น mount path หรือ prefix และจำกัด middleware ที่จะใช้กับคำขอเฉพาะที่มีเส้นทางเริ่มต้นด้วยเส้นทางนั้นเท่านั้น
เพิ่มข้อจำกัดของเส้นทางระหว่างระบบในระหว่างการทำงาน
เนื่องจากการออกแบบและประสิทธิภาพ การเพิ่มเส้นทางไดนามิกหลังจากเริ่มแอปพลิเคชันไม่ได้รับการสนับสนุน กรุณาตรวจสอบให้แน่ใจว่าเส้นทางทั้งหมดถูกกำหนดก่อนที่แอปพลิเคชันจะเริ่ม
การจัดกลุ่ม (Grouping)
หากคุณมีเส้นทางมากมาย คุณสามารถใช้ Group
เพื่อจัดระเบียบเส้นทาง
func main() {
app := fiber.New()
api := app.Group("/api", middleware) // /api
v1 := api.Group("/v1", middleware) // /api/v1
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user
v2 := api.Group("/v2", middleware) // /api/v2
v2.Get("/list", handler) // /api/v2/list
v2.Get("/user", handler) // /api/v2/user
log.Fatal(app.Listen(":3000"))
}