go
29 lines · 5 steps
How a www-to-apex redirect middleware works in Gin
A Gin middleware that permanently redirects www hostnames to their apex domain while preserving scheme and path.
Explained by
highlit
1package middleware
2
3import (
4 "net/http"
5 "strings"
6
7 "github.com/gin-gonic/gin"
8)
9
10func RedirectWWW() gin.HandlerFunc {
11 return func(c *gin.Context) {
12 host := c.Request.Host
13 if !strings.HasPrefix(host, "www.") {
14 c.Next()
15 return
16 }
17
18 apex := strings.TrimPrefix(host, "www.")
19
20 scheme := "http"
21 if c.Request.TLS != nil || c.GetHeader("X-Forwarded-Proto") == "https" {
22 scheme = "https"
23 }
24
25 target := scheme + "://" + apex + c.Request.URL.RequestURI()
26 c.Redirect(http.StatusMovedPermanently, target)
27 c.Abort()
28 }
29}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Returning a closure that captures nothing lets a middleware factory produce a reusable handler.
- 2Detecting HTTPS behind a proxy means checking X-Forwarded-Proto, not just the raw TLS connection.
- 3A 301 with the original RequestURI keeps the visitor's path and query intact across the redirect.
Related explainers
go
package theme import ( "fmt"
Per-tenant HTML templates with Gin's renderer
multi-tenancy
concurrency
html-templates
Advanced
8 steps
go
package auth import ( "net/http"
Setting and reading secure session cookies in Go
cookies
session-management
security
Intermediate
6 steps
php
<?php namespace App\Http\Middleware;
Idempotent requests with Laravel middleware
idempotency
middleware
caching
Advanced
8 steps
typescript
type ResizeCallback = (size: { width: number; height: number }) => void; export function observeResize(callback: ResizeCallback, delay = 150) { let timeoutId: ReturnType<typeof setTimeout> | undefined;
Debouncing window resize in TypeScript
debounce
closures
event-listeners
Intermediate
6 steps
go
package middleware import ( "net/http"
A maintenance-mode gate in Gin
middleware
atomic-flag
concurrency
Intermediate
8 steps
rust
use axum::{ extract::State, routing::{get, post, MethodRouter}, Json, Router,
Self-documenting routes in Axum
builder-pattern
closures
shared-state
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/how-a-www-to-apex-redirect-middleware-works-in-gin-explained-go-b2f2/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.