commit e51621c28ebb0bae751a852ffb3f698d0f7ac388 Author: Tommy Parnell Date: Tue Aug 26 13:11:17 2025 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..577f1ce --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +redirect \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..78c6c1c --- /dev/null +++ b/README.md @@ -0,0 +1,57 @@ +# URL Redirect Service + +A minimal Go application for handling URL redirects with the smallest possible memory footprint. + +## Features + +- **Host-based redirects**: Redirects based on the incoming host header +- **Path-based redirects**: Redirects based on the URL path +- **Proxy support**: Handles `X-Forwarded-Host` and `X-Forwarded-Uri` headers from reverse proxies +- **Protocol agnostic**: Works with both HTTP and HTTPS requests +- **Minimal memory usage**: Uses only Go's standard library with no external dependencies + +## Current Redirect Rules + +### Host-based +- `mail.terrible.dev` → `https://mail.tommyparnell.com` + +### Path-based +- `/test` → `https://blog.terrible.dev` + +## Usage + +1. Run the application: + ```bash + go run main.go + ``` + +2. The server will start on port 8080 + +3. Test the redirects: + ```bash + # Test host-based redirect + curl -H "Host: mail.terrible.dev" http://localhost:8080 + + # Test path-based redirect + curl http://localhost:8080/test + + # Test with X-Forwarded headers (simulating a reverse proxy) + curl -H "X-Forwarded-Host: mail.terrible.dev" http://localhost:8080 + curl -H "X-Forwarded-Uri: /test" http://localhost:8080 + ``` + +## Building + +To build a standalone binary: +```bash +go build -o redirect main.go +``` + +## Memory Optimization + +This application is designed for minimal memory usage: +- Uses only Go's standard `net/http` package +- Single handler function for all routes +- Simple map lookups for redirect rules +- No external dependencies or frameworks +- Supports reverse proxy headers without additional overhead diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3115691 --- /dev/null +++ b/go.mod @@ -0,0 +1,19 @@ +module redirect + +go 1.21 + +require github.com/gofiber/fiber/v2 v2.52.5 + +require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/google/uuid v1.5.0 // indirect + github.com/klauspost/compress v1.17.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/sys v0.15.0 // indirect +) diff --git a/main.go b/main.go new file mode 100644 index 0000000..48b1165 --- /dev/null +++ b/main.go @@ -0,0 +1,63 @@ +package main + +import ( + "github.com/gofiber/fiber/v2" +) + +// Hardcoded redirect rules +var ( + // Host-based redirects + hostRedirects = map[string]string{ + "mail.terrible.dev": "https://mail.tommyparnell.com", + } + + // Path-based redirects + pathRedirects = map[string]string{ + "/test": "https://blog.terrible.dev", + } +) + +func redirectHandler(c *fiber.Ctx) error { + // Get the actual host, checking X-Forwarded-Host first + host := c.Get("X-Forwarded-Host") + if host == "" { + host = c.Hostname() + } + + // Check for host-based redirects first + if redirectURL, exists := hostRedirects[host]; exists { + return c.Redirect(redirectURL, fiber.StatusMovedPermanently) + } + + // Get the actual path, checking X-Forwarded-Uri first + path := c.Get("X-Forwarded-Uri") + if path == "" { + path = c.Path() + } + + // Check for path-based redirects + if redirectURL, exists := pathRedirects[path]; exists { + return c.Redirect(redirectURL, fiber.StatusMovedPermanently) + } + + // If no redirect rule matches, return 404 + return c.SendStatus(fiber.StatusNotFound) +} + +func main() { + // Create Fiber app with minimal configuration for lowest memory usage + app := fiber.New(fiber.Config{ + Prefork: false, + DisableKeepalive: false, + ServerHeader: "", + AppName: "redirect", + }) + + // Use a single handler function to minimize memory overhead + app.All("*", redirectHandler) + + // Start server on port 8080 + if err := app.Listen(":8080"); err != nil { + panic(err) + } +}