Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
YouTube Security VideosMicrosoft Mechanics: A Copilot Agent Writes the Status Report(23.09.2026 um 03:30 Uhr)
Sichere ProgrammierungOpenTelemetry in the GitHub Copilot app(23.09.2026 um 04:14 Uhr)
Sichere ProgrammierungMy Introduction:(23.09.2026 um 03:53 Uhr)
Sichere ProgrammierungAgentWallex: Content Day (Articles going live)(23.09.2026 um 04:00 Uhr)
Sichere ProgrammierungYour Low-Code Platform Is Fast Until a Customer Builds One Real Table(23.09.2026 um 04:11 Uhr)
YouTube Security VideosMicrosoft Mechanics: A Copilot Agent Writes the Status Report(23.09.2026 um 03:30 Uhr)
Sichere ProgrammierungOpenTelemetry in the GitHub Copilot app(23.09.2026 um 04:14 Uhr)
Sichere ProgrammierungMy Introduction:(23.09.2026 um 03:53 Uhr)
Sichere ProgrammierungAgentWallex: Content Day (Articles going live)(23.09.2026 um 04:00 Uhr)
Sichere ProgrammierungYour Low-Code Platform Is Fast Until a Customer Builds One Real Table(23.09.2026 um 04:11 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Building Web Servers from First Principles (Part 2)

In Chapter 1, we built a server that responded with "hello world" to every request. That's like having an API that returns the same response whether your frontend calls /api/users, /api/products, or /api/login. Not very useful! Today,…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

In Chapter 1, we built a server that responded with "hello world" to every request. That's like having an API that returns the same response whether your frontend calls /api/users, /api/products, or /api/login. Not very useful!



Today, we'll fix this by making our server route-aware - different paths will return different responses, just like a real API.






What We've Built So Far



From Chapter 1, we have a basic server that:




  • ✅ Listens on port 3000

  • ✅ Responds to HTTP requests

  • ❌ Returns the same response for every path






The Problem Frontend Developers Face



When you write JavaScript like this:




// Different endpoints, different data expected
const users = await fetch('/api/users').then(r => r.json())
const products = await fetch('/api/products').then(r => r.json())
const profile = await fetch('/api/profile').then(r => r.json())






You expect different responses from each endpoint. Our current server can't handle this - it would return "hello world" for all three calls.






Inspecting the Request Path



The solution starts with examining what the client is actually requesting. Let's modify our ServeHTTP method to look at the request path:




func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
log.Printf("%s %s", r.Method, path)

// For now, let's just echo back what was requested
message := fmt.Sprintf("You requested: %s", path)
w.WriteHeader(http.StatusOK)
w.Write([]byte(message))
}






Let's test this incremental change:




go run .






In another terminal, try different paths:




curl http://localhost:3000/users
curl http://localhost:3000/products
curl http://localhost:3000/api/login






Expected Responses:




You requested: /users
You requested: /products
You requested: /api/login






Great! Now our server knows what path was requested. But we still need to return different content for different paths.






Building Route Logic with Switch Statements



Here's where most tutorials jump straight to a routing library. But let's first understand why those libraries exist by building routing logic ourselves.



The most straightforward approach is a switch statement:




func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
log.Printf("%s %s", r.Method, path)

w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusOK)

switch path {
case "/hello":
hello(w)
case "/goodbye":
goodbye(w)
case "/time":
getTime(w)
default:
welcome(w)
}
}






Now we need to create those handler functions. Let's add them to our server.go:




func welcome(w http.ResponseWriter) {
w.Write([]byte("Welcome to our Go Webserver!"))
}

func hello(w http.ResponseWriter) {
w.Write([]byte("Hello, World!"))
}

func goodbye(w http.ResponseWriter) {
w.Write([]byte("Goodbye, see you later!"))
}

func getTime(w http.ResponseWriter) {
message := fmt.Sprintf("Current Time: %s", time.Now().Format("2006-01-02 15:04:05"))
w.Write([]byte(message))
}






Don't forget to import the time package at the top of your file:




import (
"fmt"
"log"
"net/http"
"time" // Add this line
)









Testing Our Route-Aware Server



Let's test our newly route-aware server:




go run .






Try these different endpoints:




curl http://localhost:3000/hello
curl http://localhost:3000/goodbye
curl http://localhost:3000/time
curl http://localhost:3000/
curl http://localhost:3000/unknown-path






Expected Responses:




Hello, World!
Goodbye, see you later!
Current Time: 2024-09-14 15:30:45
Welcome to our Go Webserver!
Welcome to our Go Webserver!






Perfect! Our server now behaves like a real API - different paths return different responses.






What We've Accomplished





We now have:




  • ✅ Path-aware routing (different responses for different URLs)

  • ✅ Clean handler separation (each route has its own function)

  • ✅ Default route handling (catch-all for unknown paths)

  • ✅ Request logging (see what's being requested)






The Problems We're Creating



While our switch statement approach works, it's already showing some issues that will become painful as we scale:






1. Method Blindness



Our server doesn't distinguish between HTTP methods. Try this:




curl -X POST http://localhost:3000/hello
curl -X DELETE http://localhost:3000/hello
curl -X PUT http://localhost:3000/hello






All return the same response! In a real API, GET /users and POST /users should do very different things.






2. Growing Switch Statement



Imagine adding 20 more routes:




switch path {
case "/hello":
hello(w)
case "/goodbye":
goodbye(w)
case "/time":
getTime(w)
case "/users":
getUsers(w)
case "/products":
getProducts(w)
case "/orders":
getOrders(w)
// ... 15 more cases
default:
welcome(w)
}






This becomes unwieldy quickly - like having one massive if-else chain in your frontend code.






3. No Dynamic Paths



What if your frontend needs to call /users/123 or /products/456? We'd need a case for every possible ID, which is impossible.






4. Handler Signatures



Our handler functions only take a ResponseWriter. Real APIs need access to the full Request to read query parameters, headers, and request bodies.






Quick Fix: Adding HTTP Method Support



Before we move on, let's quickly add basic HTTP method support to see how the complexity grows:




func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
method := r.Method
log.Printf("%s %s", method, path)

w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusOK)

// Now we need to check BOTH path AND method
switch method {
case "GET":
s.handleGET(w, r, path)
case "POST":
s.handlePOST(w, r, path)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}

func (s *Server) handleGET(w http.ResponseWriter, r *http.Request, path string) {
switch path {
case "/hello":
hello(w)
case "/goodbye":
goodbye(w)
case "/time":
getTime(w)
default:
welcome(w)
}
}

func (s *Server) handlePOST(w http.ResponseWriter, r *http.Request, path string) {
switch path {
case "/hello":
w.Write([]byte("Hello via POST!"))
default:
http.Error(w, "Not found", http.StatusNotFound)
}
}






Test the different methods:




curl -X GET http://localhost:3000/hello   # Returns: Hello, World!
curl -X POST http://localhost:3000/hello # Returns: Hello via POST!
curl -X PUT http://localhost:3000/hello # Returns: Method not allowed






See how quickly this is getting complex? We're already at nested switch statements, and we only have a few routes!






What's Next?



In Chapter 3, we'll solve these growing pains by building a proper router - a separate component responsible for matching paths and methods to handlers. This will give us:




  • Clean separation of concerns (routing logic separate from business logic)

  • Support for different HTTP methods

  • A foundation for dynamic routes like /users/:id

  • Better organization as our API grows



Think of it like moving from one giant JavaScript file to a properly structured application with separate modules.






Challenge: Before Chapter 3, try adding a few more routes to see how unwieldy the switch statement becomes. Add routes like /api/users, /api/products, and /api/orders for both GET and POST methods.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Building Web Servers from First Principles (Part 2)

Thematisch verwandte Begriffe: Building, Servers, from, First · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-17636 | IBM Financial Transaction Manager (FTM) for RedHat OpenShift could allow…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick