Framework HTTP — Go 1.22+ · stdlib uniquement

Routing, templates, Vite

goWebFlow pose trois pièces sur net/http : un routeur qui retourne des erreurs, un système layout/page html/template, et une intégration Vite clé en main. Zéro dépendance externe.

00 Cycle d'une requête

Du socket au handler — une goroutine par requête.

licence
MIT
deps
0
go
≥ 1.22
01

Trois pièces, assemblées proprement.

Chaque couche est lisible, remplaçable, testable indépendamment.

01

Routeur avec erreurs

Les handlers retournent une error au lieu de paniquer. ErrHTTP(404, err) déclenche le bon handler d'erreur. Routing via http.ServeMux Go 1.22 — paramètres {id} inclus.

02

Layout + page

Un layout (base.html), des pages (*.html), fusionnés via {{block "content" .}}. Hot reload automatique en dev. Données passées directement au template.

03

Vite intégré

{{ vite "src/main.js" }} dans le layout. En dev : proxy vers localhost:5173. En prod : hashes depuis le manifest. Aucune config supplémentaire.

Construit à la main sur net/http — zéro dépendance externe.
02

Voilà à quoi ça ressemble.

Un type App, une Config, et des handlers net/http standard.

main.go ↳ go 1.22
package main

import (
    "log"
    "net/http"
    "github.com/Florian418/gowebflow/pkg/httpd"
)

func main() {
    app, err := httpd.New(httpd.Config{
        LayoutDir:   "./ui/layouts",
        PageDir:     "./ui/pages",
        StaticDir:   "./ui/dist",
        StaticURL:   "/static/",
        ActiveTheme: "gwfer",
        Dev:         true,
    })
    if err != nil {
        log.Fatal(err)
    }

    app.Get("/", func(w http.ResponseWriter, r *http.Request) error {
        return app.Render(w, "home.html", nil)
    })

    app.NotFound(func(w http.ResponseWriter, r *http.Request) error {
        w.WriteHeader(http.StatusNotFound)
        return app.Render(w, "404.html", nil)
    })

    log.Fatal(app.Listen(":8080"))
}
i

Handler standard

Signature func(w http.ResponseWriter, r *http.Request) error — net/http pur, sans type propriétaire. L'erreur remonte au dispatcher au lieu de paniquer.

ii

404 personnalisable

app.NotFound() branche un handler Go standard. Même signature, même logique — ici on rend une page template comme n'importe quelle route.

iii

Vite via ActiveTheme

ActiveTheme pointe vers le sous-dossier du build Vite. En dev : proxy automatique vers localhost:5173. En prod : hashes lus depuis manifest.json.

03

Chaque erreur a son handler.

Les handlers retournent une error — le framework l'intercepte, la logge, et appelle le bon handler. Masquer un 500 en 404 est un choix explicite, pas un défaut.

main.go ↳ gestion d'erreurs
// 404 — chemin dispo en data dans le template
app.NotFound(func(w http.ResponseWriter, r *http.Request) error {
    w.WriteHeader(http.StatusNotFound)
    return app.Render(w, "404.html", r.URL.Path)
})

// 500 masqué en 404 — l'erreur reste loggée côté serveur
app.OnError(http.StatusInternalServerError, func(w http.ResponseWriter, r *http.Request) error {
    w.WriteHeader(http.StatusNotFound)
    return app.Render(w, "404.html", nil)
})

// Déclencher un code précis depuis une route
app.Get("/admin", func(w http.ResponseWriter, r *http.Request) error {
    if !isAdmin(r) {
        return httpd.ErrHTTP(http.StatusForbidden, fmt.Errorf("forbidden"))
    }
    return app.Render(w, "admin.html", nil)
})
i

WriteHeader avant Render

Go envoie un 200 automatiquement dès que le premier octet est écrit dans le body. w.WriteHeader(code) doit toujours précéder Render dans un handler d'erreur.

ii

Masquage explicite

Renvoyer 404 pour un 500 ou un 403 est une décision de sécurité — ne pas révéler si la ressource existe ou si le serveur a crashé. L'erreur réelle est loggée par wrap(), seul le code HTTP côté client change.

iii

ErrHTTP

ErrHTTP(code, err) signale au framework quel handler OnError appeler. Tout code HTTP est valide — le handler décide ensuite de ce que le navigateur reçoit réellement.

04

Un projet en trois commandes.

Structure générée,
zéro config manuelle.

gwf crée la structure complète — layouts, pages, Air, Vite optionnel. Le routing, les templates et Vite sont câblés. Le reste — JSON, sessions, auth — reste en stdlib, à vous.

terminal $go install github.com/Florian418/gowebflow/cmd/gwf@latest $gwf new monsite [ --vite ] [ --no-layout ] $cd monsite && go mod tidy && air