Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

واجهة http.Handler

جزء من قسم البرمجة كائنية التوجه في رحلة GO على Coddy. الدرس 77 من 107.

واجهة http.Handler هي الأساس لبنية خادم الويب في Go. وهي تحدد كيفية معالجة طلبات HTTP، ويمكن لأي نوع يقوم بتنفيذها تقديم طلبات الويب.

الواجهة بسيطة بشكل ملحوظ:

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

يمكن لأي نوع يحتوي على method باسم ServeHTTP معالجة طلبات HTTP. إليك handler مخصصًا:

type GreetHandler struct {
    Greeting string
}

func (h GreetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%s, visitor!", h.Greeting)
}

يمكنك استخدام هذا المعالج مباشرةً مع خادم:

handler := GreetHandler{Greeting: "Welcome"}
http.Handle("/greet", handler)

للحالات الأبسط، توفّر Go النوع http.HandlerFunc، الذي يتيح لك تحويل دالة عادية إلى معالج:

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello!")
}

http.Handle("/hello", http.HandlerFunc(hello))

تتضح قوة هذه الواجهة عندما تدرك أن معالجات الطلبات يمكنها تغليف معالجات طلبات أخرى. يتيح ذلك أنماط البرمجيات الوسيطة، حيث تضيف التسجيل أو المصادقة أو اهتمامات أخرى مشتركة دون تعديل منطق معالج الطلب الأصلي.

challenge icon

التحدي

سهل

لنبنِ نظامًا بسيطًا لمعالجات HTTP يحاكي كيفية معالجة طلبات الويب! نظرًا إلى أننا لا نستطيع تشغيل خادم HTTP فعلي في هذه البيئة، ستنشئ معالجات تطبّق واجهة http.Handler وتوضّح كيفية معالجتها للطلبات من خلال العمل مع كائنات mock للطلب والاستجابة.

ستنظّم التعليمات البرمجية عبر ملفين:

  • handlers.go: عرّف معالجات HTTP المخصّصة.

    أنشئ بنية MockResponseWriter تلتقط ما كان سيُكتب إلى استجابة HTTP. ينبغي أن تخزّن نص الاستجابة كسلسلة نصية وأن تطبّق method باسم Write(data []byte) (int, error) تُلحق data بجسم الاستجابة. أضف method باسم Body() string لاسترداد جسم الاستجابة المتراكم.

    أنشئ بنية MockRequest تحتوي على حقلي السلسلة النصية Path وMethod لمحاكاة طلب HTTP.

    أنشئ الآن بنيتي معالجات تطبّقان نمط واجهة http.Handler (مع method باسم ServeHTTP يستقبل *MockResponseWriter و*MockRequest):

    • WelcomeHandler مع حقل باسم Message - يكتب message متبوعًا بمسار الطلب
    • MethodHandler - يكتب استجابات مختلفة بناءً على method الطلب: "Fetching data" لـ GET، و"Creating resource" لـ POST، و"Method not supported" لأي شيء آخر
  • main.go: عالج الطلبات من خلال معالجاتك.

    اقرأ نوع المعالج (welcome أو method)، ثم اقرأ تفاصيل الطلب. بالنسبة إلى معالج الترحيب، اقرأ أيضًا رسالة الترحيب.

    أنشئ المعالج المناسب، وابنِ طلبًا وهميًا، واستدعِ ServeHTTP لمعالجته. اطبع جسم الاستجابة.

سيتم توفير المُدخلات التالية:

  • السطر 1: نوع المعالج (welcome أو method)
  • السطر 2: مسار الطلب
  • السطر 3: method الطلب
  • السطر 4 (لـ welcome فقط): رسالة الترحيب

على سبيل المثال، عند إعطاء:

welcome
/home
GET
Hello from

ينبغي أن يكون الناتج:

Hello from /home

وعند إعطاء:

method
/api/users
POST

ينبغي أن يكون الناتج:

Creating resource

وعند إعطاء:

method
/api/data
GET

ينبغي أن يكون الناتج:

Fetching data

وعند إعطاء:

method
/api/items
DELETE

ينبغي أن يكون الناتج:

Method not supported

يوضّح هذا التحدي المفهوم الأساسي لواجهة http.Handler: يمكن لأي نوع يمتلك method باسم ServeHTTP معالجة الطلبات. في التطبيقات الحقيقية، تأتي http.ResponseWriter و*http.Request من المكتبة القياسية للغة Go، لكن يظل نمط تطبيق المعالجات مطابقًا تمامًا.

جرّب بنفسك

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// اقرأ نوع المعالج
	scanner.Scan()
	handlerType := scanner.Text()
	
	// اقرأ مسار الطلب
	scanner.Scan()
	path := scanner.Text()
	
	// اقرأ طريقة الطلب
	scanner.Scan()
	method := scanner.Text()
	
	// أنشئ طلبًا وهميًا
	request := &MockRequest{
		Path:   path,
		Method: method,
	}
	
	// أنشئ كاتب استجابة وهمي
	response := &MockResponseWriter{}
	
	// TODO: بناءً على handlerType، أنشئ المعالج المناسب
	// إذا كان handlerType هو "welcome"، اقرأ رسالة الترحيب وأنشئ WelcomeHandler
	// إذا كان handlerType هو "method"، أنشئ MethodHandler
	// استدعِ ServeHTTP على المعالج مع response و request
	
	if handlerType == "welcome" {
		scanner.Scan()
		message := scanner.Text()
		// TODO: أنشئ WelcomeHandler مع الرسالة واستدعِ ServeHTTP
		_ = message // أزل هذا السطر عند التنفيذ
	} else if handlerType == "method" {
		// TODO: أنشئ MethodHandler واستدعِ ServeHTTP
	}
	
	// اطبع جسم الاستجابة
	fmt.Println(response.Body())
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Go عبر الإنترنت