Menu
Coddy logo textTech

Interfejs http.Handler

Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 77 z 107.

Interfejs http.Handler stanowi podstawę architektury serwerów internetowych w Go. Określa sposób przetwarzania żądań HTTP, a każdy typ, który go implementuje, może obsługiwać żądania internetowe.

Interfejs jest niezwykle prosty:

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

Każdy typ z metodą ServeHTTP może obsługiwać żądania HTTP. Oto własny program obsługi:

type GreetHandler struct {
    Greeting string
}

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

Możesz użyć tego modułu obsługi bezpośrednio z serwerem:

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

W prostszych przypadkach Go udostępnia http.HandlerFunc, typ, który pozwala przekształcić zwykłą funkcję w procedurę obsługi:

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

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

Potęgę tego interfejsu dostrzeżesz, gdy uświadomisz sobie, że procedury obsługi mogą opakowywać inne procedury obsługi. Umożliwia to stosowanie wzorców oprogramowania pośredniczącego, dzięki którym możesz dodawać rejestrowanie, uwierzytelnianie lub inne zagadnienia przekrojowe bez modyfikowania oryginalnej logiki procedury obsługi.

challenge icon

Wyzwanie

Łatwy

Stwórzmy prosty system obsługi HTTP, który symuluje sposób przetwarzania żądań internetowych! Ponieważ w tym środowisku nie możemy uruchomić prawdziwego serwera HTTP, utworzysz procedury obsługi implementujące interfejs http.Handler i pokażesz, jak przetwarzają żądania, korzystając z obiektów żądania i odpowiedzi będących atrapami.

Rozmieścisz swój kod w dwóch plikach:

  • handlers.go: Zdefiniuj własne procedury obsługi HTTP.

    Utwórz strukturę MockResponseWriter, która przechwytuje to, co zostałoby zapisane w odpowiedzi HTTP. Powinna przechowywać treść odpowiedzi jako ciąg znaków i implementować metodę Write(data []byte) (int, error), która dopisuje dane do treści. Dodaj metodę Body() string, aby pobierać zgromadzoną odpowiedź.

    Utwórz strukturę MockRequest z polami tekstowymi Path i Method, aby symulować żądanie HTTP.

    Teraz utwórz dwie struktury procedur obsługi, które implementują wzorzec interfejsu http.Handler (z metodą ServeHTTP, która przyjmuje *MockResponseWriter i *MockRequest):

    • WelcomeHandler z polem Message — zapisuje wiadomość, a po niej ścieżkę żądania
    • MethodHandler — zapisuje różne odpowiedzi w zależności od metody żądania: "Fetching data" dla GET, "Creating resource" dla POST i "Method not supported" dla każdej innej metody
  • main.go: Przetwarzaj żądania za pomocą procedur obsługi.

    Odczytaj typ procedury obsługi (welcome lub method), a następnie odczytaj szczegóły żądania. W przypadku procedury obsługi powitania odczytaj również wiadomość powitalną.

    Utwórz odpowiednią procedurę obsługi, zbuduj atrapę żądania i wywołaj ServeHTTP, aby je przetworzyć. Wypisz treść odpowiedzi.

Podane zostaną następujące dane wejściowe:

  • Wiersz 1: Typ procedury obsługi (welcome lub method)
  • Wiersz 2: Ścieżka żądania
  • Wiersz 3: Metoda żądania
  • Wiersz 4 (tylko dla welcome): Wiadomość powitalna

Na przykład dla danych:

welcome
/home
GET
Hello from

Wynik powinien być następujący:

Hello from /home

A dla danych:

method
/api/users
POST

Wynik powinien być następujący:

Creating resource

A dla danych:

method
/api/data
GET

Wynik powinien być następujący:

Fetching data

A dla danych:

method
/api/items
DELETE

Wynik powinien być następujący:

Method not supported

To wyzwanie pokazuje podstawową koncepcję interfejsu http.Handler: każdy typ mający metodę ServeHTTP może obsługiwać żądania. W rzeczywistych aplikacjach http.ResponseWriter i *http.Request pochodzą ze standardowej biblioteki Go, ale wzorzec implementowania procedur obsługi pozostaje dokładnie taki sam.

Spróbuj swoich sił

package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Odczytaj typ procedury obsługi
	scanner.Scan()
	handlerType := scanner.Text()
	
	// Odczytaj ścieżkę żądania
	scanner.Scan()
	path := scanner.Text()
	
	// Odczytaj metodę żądania
	scanner.Scan()
	method := scanner.Text()
	
	// Utwórz atrapę żądania
	request := &MockRequest{
		Path:   path,
		Method: method,
	}
	
	// Utwórz atrapę obiektu zapisującego odpowiedź
	response := &MockResponseWriter{}
	
	// TODO: Na podstawie handlerType utwórz odpowiednią procedurę obsługi
	// Jeśli handlerType ma wartość "welcome", odczytaj wiadomość powitalną i utwórz WelcomeHandler
	// Jeśli handlerType ma wartość "method", utwórz MethodHandler
	// Wywołaj ServeHTTP na procedurze obsługi, przekazując response i request
	
	if handlerType == "welcome" {
		scanner.Scan()
		message := scanner.Text()
		// TODO: Utwórz WelcomeHandler z wiadomością i wywołaj ServeHTTP
		_ = message // Usuń ten wiersz podczas implementacji
	} else if handlerType == "method" {
		// TODO: Utwórz MethodHandler i wywołaj ServeHTTP
	}
	
	// Wypisz treść odpowiedzi
	fmt.Println(response.Body())
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Go online