توجيه

دور المسار في اطار Go Fiber هو ربط عناوين URL مختلفة بدوال المعالجة، من أجل دعم معالجة طلبات HTTP. إنه نقطة الدخول لجميع طلبات اطار الويب.

معالجي المسارات (الدوال)

قم بتسجيل المسارات المرتبطة بأساليب HTTP محددة.

ملاحظة: في بعض الأطر العمل، يُطلق على معالجي المسارات مصطلح المتحكمات، والتي تحمل بشكل عام المعنى نفسه - تحديد الدالة (الأسلوب) التي ستتعامل مع الطلب الوارد عبر 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 يُستخدم لتحميل الوسيطة واعتراضات URL بادئة. هذه المسارات تتطابق فقط مع بداية كل مسار، على سبيل المثال، سيُتطابق /john مع /john/doe، /johnnnnn، وهلم جرا.

توقيع الدالة للوسيطة المخصصة:

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()
})

مسار

مسار الطريق، جنبًا إلى جنب مع أسلوب الطلب، يُحدد نقاط النهاية التي يمكن الوصول إليها. يمكن أن يكون مسار الطريق سلسلة نصية أو نمط سلسلة نصية.

أمثلة على مسارات الطريق القائمة على السلسلة النصية

// سيحتوي هذا المسار على الطلبات إلى المسار الأساسي، "/":
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("ملف_عشوائي.txt")

بالمثل لاطار expressJs، النظام الذي يتم فيه إعلان المسارات مهم. عند تلقي الطلب، يتم التحقق من المسارات تبعًا لترتيب إعلانها.

يرجى ملاحظة: تأكد من كتابة المسارات التي تحتوي على معلمات متغيرة بعد المسارات التي تحتوي على أجزاء ثابتة لتجنب تطابق هذه الأجزاء المتغيرة بشكل خاطئ، مما قد يؤدي إلى سلوك غير متوقع.

معلمات المسار

معلمات المسار هي عناصر ديناميكية في المسار ويمكن أن تكون إما أسماء الفرع أو شرائح غير مسماة. يتم استخدام هذه الشرائح لالتقاط القيم في مواقع محددة في عنوان URL. يمكنك استخدام دالة البارامترات لاسترداد هذه القيم، حيث يكون معلم الدالة اسم معلم المسار في المسار، أو بالنسبة للمعالم غير المسماة، فإنه يكون الحروف (*, +) وعددها.

الرمز النجمي (*) أو إشارة الجمع (+) تمثل المعلمات الجشعة.

توفر المسارات أيضًا إمكانية استخدام المعلمات الاختيارية. بالنسبة للمعلمات المسماة، يتبع هذه المعلمات رمز الاستفهام (?)، في حين أن إشارة الجمع ليست اختيارية. يمكنك استخدام الحروف الجاموسية لتمثيل مجموعة معلمات اختيارية وجشعة.

مثال على تعريف مسار مع معلمات المسار

// معلمات
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("مرحبًا، مجتمع")
})

`

نظرًا لأن الشرطات (-) والنقط (.) يُفسران بشكل حرفي، يمكن استخدامهما جنبًا إلى جنب مع معلمات المسار لتحقيق أغراض مفيدة.

يمكن أن تُحول جميع الأحرف الخاصة للمعلمات أيضًا باستخدام \ وسيتم تجاهل قيمهم، لذلك إذا كنت ترغب في استخدامها في المسار. من المستحسن استخدام علامات الاقتباس العكسي ``, كما في وثائق تعبيرات Go العادية حيث يتم استخدامها دائمًا لضمان عدم وجود أي ابهام، ولا تؤثر الأحرف المنقولة بطريق الخطأ على نمط التعبير العادي.

// 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
// الباراماترات: "اشارة" -> "@", "معلم" -> "v1"
app.Get("/:sign:param", handler)

// GET /api-v1
// الباراماترات: "اسم" -> "v1"
app.Get("/api-:name", handler)

// GET /customer/v1/cart/proxy
// الباراماترات: "*1" -> "customer/", "*2" -> "/cart"
app.Get("/*v1*/proxy", handler)

// GET /v1/brand/4/shop/blue/xs
// الباراماترات: "*1" -> "brand/4", "*2" -> "blue/xs"
app.Get("/v1/*/shop/*", handler)

` لقد قمنا بالفعل بتكييف التوجيه الخاص بنا لتوجيه Express، ولكنه لا يدعم بعد التعابير العادية لأنها بطيئة نسبيًا.

القيود

عندما يحدث تطابق مع عنوان URL الوارد ويتم تقسيم مسار URL إلى قيم مسار من خلال المعلمات، سيتم تنفيذ القيود. تم إدخال هذه الميزة في "الإصدار 2.37.0" واستلهمت من .NET Core.

القيود ليست لتحقق صحة المعلمة. إذا كانت القيود غير صالحة بالنسبة لقيمة المعلمة، فسيقوم Fiber بإرجاع معالج 404.

القيود المثال أمثلة المطابقة
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 (يجب أن تتكون السلسلة من حرف أو أكثر أبجدي، غير حساس للحالة، a-z)
datetime :dob<datetime(2006\\-01\\-02)> 2005-11-01
regex(expression) :date<regex(\d{4}-\d{2}-\d{2})> 2022-08-27 (يجب أن تتطابق مع التعبير العادي)

أمثلة

  • القيد الفردي
  • القيود المتعددة
  • القيد بتعبير عادي
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 بتجهيز استعلامات التعبير العادي مسبقًا أثناء تسجيل المسارات، لذا لا يوجد أي تأثير على الأداء بسبب قيود التعبير العادي.

```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


> عند استخدام قيود الوقت والتاريخ (`*`,`+`,`?`,`:`,`/`,``,``,`>`,';`,`(`,`)`), استخدم `\\` قبل استخدام الرموز الخاصة في المسار لتجنب التفسير الخاطئ.

**مثال على العلامة الاختيارية للمعلمة**

يمكنك أيضًا إضافة قيود إلى المعلمات الاختيارية.

```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

الوسيط البرمجي

الوظائف المصممة للتلاعب بالطلبات أو الردود تُسمى وظائف الوسيط. Next هي وظيفة توجيه Fiber التي عند استدعائها، تُنفذ الدالة next التي تُطابق المسار الحالي.

مثال على وظيفة الوسيط

app.Use(func(c *fiber.Ctx) error {
  // ضبط رأس مخصص في كل الردود:
  c.Set("X-Custom-Header", "مرحباً، العالم")

  // المتابعة إلى الوسيط التالي:
  return c.Next()
})

app.Get("/", func(c *fiber.Ctx) error {
  return c.SendString("مرحباً، العالم!")
})

يمكن أن يكون المسار لطريقة Use مسار الربط أو مسار البادئة، ويُحد من تطبيق الوسيط وتطبيقه فقط على الطلبات التي تبدأ بذلك المسار.

إضافة قيود للمسارات في وقت التشغيل

نظرًا للاعتبارات التصميمية والأداء، لا يدعم إضافة المسارات بشكل ديناميكي بعد بدء تشغيل التطبيق. يرجى التأكد من تعريف جميع المسارات قبل بدء التطبيق.

التجميع

إذا كان لديك العديد من نقاط النهاية، يمكنك استخدام 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"))
}