Menu
Coddy logo textTech

Interfaccia http.Handler

Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 77 di 107.

L'interfaccia http.Handler è il fondamento dell'architettura del server web di Go. Definisce come vengono elaborate le richieste HTTP e qualsiasi tipo che la implementi può gestire richieste web.

L'interfaccia è straordinariamente semplice:

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

Qualsiasi tipo con un metodo ServeHTTP può gestire richieste HTTP. Ecco un handler personalizzato:

type GreetHandler struct {
    Greeting string
}

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

Puoi usare questo gestore direttamente con un server:

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

Per i casi più semplici, Go fornisce http.HandlerFunc, un tipo che ti permette di convertire una funzione normale in un gestore:

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

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

La potenza di questa interfaccia diventa evidente quando ti rendi conto che gli handler possono avvolgere altri handler. Questo consente di adottare schemi middleware in cui aggiungi registrazione, autenticazione o altri aspetti trasversali senza modificare la logica originale degli handler.

challenge icon

Sfida

Facile

Creiamo un semplice sistema di gestori HTTP che simula come vengono elaborate le richieste web! Poiché in questo ambiente non possiamo eseguire un vero server HTTP, creerai dei gestori che implementano l’interfaccia http.Handler e mostrerai come elaborano le richieste lavorando con oggetti di richiesta/risposta simulati.

Organizzerai il codice in due file:

  • handlers.go: definisci i tuoi gestori HTTP personalizzati.

    Crea una struct MockResponseWriter che acquisisce ciò che verrebbe scritto in una risposta HTTP. Dovrebbe memorizzare il corpo della risposta come stringa e implementare un metodo Write(data []byte) (int, error) che aggiunge i dati al corpo. Aggiungi un metodo Body() string per recuperare la risposta accumulata.

    Crea una struct MockRequest con i campi stringa Path e Method per simulare una richiesta HTTP.

    Ora crea due struct gestore che implementano il modello dell’interfaccia http.Handler (con un metodo ServeHTTP che accetta *MockResponseWriter e *MockRequest):

    • WelcomeHandler con un campo Message: scrive il messaggio seguito dal percorso della richiesta
    • MethodHandler: scrive risposte diverse in base al metodo della richiesta: "Fetching data" per GET, "Creating resource" per POST e "Method not supported" per qualsiasi altro metodo
  • main.go: elabora le richieste tramite i tuoi gestori.

    Leggi un tipo di gestore (welcome o method), poi leggi i dettagli della richiesta. Per il gestore di benvenuto, leggi anche il messaggio di benvenuto.

    Crea il gestore appropriato, costruisci una richiesta simulata e chiama ServeHTTP per elaborarla. Stampa il corpo della risposta.

Verranno forniti i seguenti input:

  • Riga 1: tipo di gestore (welcome o method)
  • Riga 2: percorso della richiesta
  • Riga 3: metodo della richiesta
  • Riga 4 (solo per welcome): messaggio di benvenuto

Per esempio, dato:

welcome
/home
GET
Hello from

Il tuo output dovrebbe essere:

Hello from /home

E dato:

method
/api/users
POST

Il tuo output dovrebbe essere:

Creating resource

E dato:

method
/api/data
GET

Il tuo output dovrebbe essere:

Fetching data

E dato:

method
/api/items
DELETE

Il tuo output dovrebbe essere:

Method not supported

Questa sfida illustra il concetto fondamentale dell’interfaccia http.Handler: qualsiasi tipo con un metodo ServeHTTP può gestire le richieste. Nelle applicazioni reali, http.ResponseWriter e *http.Request provengono dalla libreria standard di Go, ma il modello per implementare i gestori rimane esattamente lo stesso.

Provalo tu

package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// Leggi il tipo di handler
	scanner.Scan()
	handlerType := scanner.Text()
	
	// Leggi il percorso della richiesta
	scanner.Scan()
	path := scanner.Text()
	
	// Leggi il metodo della richiesta
	scanner.Scan()
	method := scanner.Text()
	
	// Crea una richiesta simulata
	request := &MockRequest{
		Path:   path,
		Method: method,
	}
	
	// Crea un writer di risposta simulato
	response := &MockResponseWriter{}
	
	// TODO: In base a handlerType, crea l'handler appropriato
	// Se handlerType è "welcome", leggi il messaggio di benvenuto e crea WelcomeHandler
	// Se handlerType è "method", crea MethodHandler
	// Chiama ServeHTTP sull'handler con response e request
	
	if handlerType == "welcome" {
		scanner.Scan()
		message := scanner.Text()
		// TODO: Crea WelcomeHandler con il messaggio e chiama ServeHTTP
		_ = message // Rimuovi questa riga durante l'implementazione
	} else if handlerType == "method" {
		// TODO: Crea MethodHandler e chiama ServeHTTP
	}
	
	// Stampa il corpo della risposta
	fmt.Println(response.Body())
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Go online