Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
Windows Tipps & SecurityTestMu AI Review: How AI is Solving the Quality Engineering Problem(23.09.2026 um 13:18 Uhr)
••
Windows Tipps & SecurityAmazon haut den kabellosen Dyson V8 Stabstaubsauger zum Tiefstpreis raus(24.09.2026 um 09:32 Uhr)
•
Windows Tipps & SecurityUpdates beheben etliche Schwachstellen in Foxit PDF Reader(24.09.2026 um 09:44 Uhr)
••••••
Windows Tipps & Security„Vom Experience Center zum monumentalen Signage-Projekt“(24.09.2026 um 10:30 Uhr)
•
Windows Tipps & SecurityTestMu AI Review: How AI is Solving the Quality Engineering Problem(23.09.2026 um 13:18 Uhr)
••
Windows Tipps & SecurityAmazon haut den kabellosen Dyson V8 Stabstaubsauger zum Tiefstpreis raus(24.09.2026 um 09:32 Uhr)
•
Windows Tipps & SecurityUpdates beheben etliche Schwachstellen in Foxit PDF Reader(24.09.2026 um 09:44 Uhr)
••••••
Windows Tipps & Security„Vom Experience Center zum monumentalen Signage-Projekt“(24.09.2026 um 10:30 Uhr)
•
Intelligence View
⚡ tsecurity.de Intelligence

Building Web Servers from First Principles (Part 3)

In Chapter 2, we built routing with nested switch statements. It worked, but imagine explaining that approach to a frontend developer: "Just add more nested switch cases for every new endpoint." They'd think we were crazy! Today, we'll…

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

In Chapter 2, we built routing with nested switch statements. It worked, but imagine explaining that approach to a frontend developer: "Just add more nested switch cases for every new endpoint." They'd think we were crazy!



Today, we'll solve this by building a proper router - a separate component that handles all the routing logic, just like Express.js does with app.get() and app.post().






What We've Built So Far



From the previous chapters, we have:




  • ✅ A basic HTTP server that listens for requests

  • ✅ Path-based routing using switch statements

  • ❌ Nested switch statements that are hard to maintain

  • ❌ No clean way to register routes dynamically






The Problem with Our Current Approach



Let's first look at where our nested switch approach leads us. Here's what our ServeHTTP method looks like when extended with proper HTTP method support:




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 r.Method {
case http.MethodGet:
GET(path, w)
case http.MethodPost:
POST(path, w)
default:
not_Supported(w)
}
}

func GET(path string, w http.ResponseWriter) {
switch path {
case "/hello":
hello(w)
case "/goodbye":
goodbye(w)
case "/time":
getTime(w)
default:
welcome(w)
}
}

func POST(path string, w http.ResponseWriter) {
switch path {
case "/hello":
post_hello(w)
case "/messages":
messages(w)
case "/time":
post_getTime(w)
default:
post_welcome(w)
}
}






This approach has several problems:





  1. Scattered Logic: Route definitions are spread across multiple functions


  2. Hard to Extend: Adding new HTTP methods requires new functions


  3. No Dynamic Registration: You can't programmatically add routes


  4. Poor Organization: Unlike app.get('/users', handler) in Express






Understanding What Frameworks Do



When you use Express.js, you write:




app.get('/users', getUsersHandler)
app.post('/users', createUserHandler)
app.put('/users/:id', updateUserHandler)






Or with Gin in Go:




r.GET("/users", getUsersHandler)
r.POST("/users", createUserHandler)
r.PUT("/users/:id", updateUserHandler)






What's happening under the hood? The framework stores these routes in a data structure and matches incoming requests against them. Let's build our own version.






Designing Our Router



We need a router that can:





  1. Register routes with method + path + handler


  2. Match incoming requests to the right handler


  3. Execute the matched handler or return 404



Let's start by designing the data structure. We need to store routes by HTTP method and path:




routes = {
"GET": {
"/hello": helloHandler,
"/users": getUsersHandler
},
"POST": {
"/users": createUserHandler,
"/messages": messagesHandler
}
}









Building the Router Component



Create a new file router.go:




package main

import (
"fmt"
"log"
"net/http"
)

type HandlerFunc func(w http.ResponseWriter, r *http.Request)

type Router struct {
routes map[string]map[string]HandlerFunc
}

func NewRouter() *Router {
return &Router{
routes: make(map[string]map[string]HandlerFunc),
}
}






Key Design Decisions:





  1. HandlerFunc type: This matches the signature that handlers need - access to both response and request


  2. Nested maps: map[method]map[path]handler gives us fast O(1) lookup


  3. Pointer receiver: We'll modify the router's state when adding routes






Adding Route Registration Methods



Now let's add the methods that let us register routes (like Express's app.get()):




func (r *Router) addRoute(method string, path string, handler HandlerFunc) {
if r.routes[method] == nil {
r.routes[method] = make(map[string]HandlerFunc)
}

r.routes[method][path] = handler
}

func (r *Router) GET(path string, handler HandlerFunc) {
r.addRoute(http.MethodGet, path, handler)
}

func (r *Router) POST(path string, handler HandlerFunc) {
r.addRoute(http.MethodPost, path, handler)
}

func (r *Router) PUT(path string, handler HandlerFunc) {
r.addRoute(http.MethodPut, path, handler)
}

func (r *Router) PATCH(path string, handler HandlerFunc) {
r.addRoute(http.MethodPatch, path, handler)
}

func (r *Router) DELETE(path string, handler HandlerFunc) {
r.addRoute(http.MethodDelete, path, handler)
}






Now we can register routes just like in frameworks:




router.GET("/hello", helloHandler)
router.POST("/users", createUserHandler)









Implementing Route Resolution



The router needs to match incoming requests to handlers:




func (r *Router) resolveRoute(req *http.Request) (HandlerFunc, error) {
method := req.Method
path := req.URL.Path

log.Printf("%s %s", method, path)

methodRoutes, ok := r.routes[method]
if !ok {
return nil, fmt.Errorf("method not supported")
}

handler, ok := methodRoutes[path]
if !ok {
return nil, fmt.Errorf("path does not exist")
}

return handler, nil
}









Making the Router Handle HTTP Requests



Our router needs to implement the http.Handler interface so it can handle requests:




func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
handler, err := r.resolveRoute(req)

if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("route not found"))
return
}

handler(w, req)
}






This is beautiful - our router finds the right handler and calls it, or returns 404 if no match is found.






Updating Our Server to Use the Router



Now we need to integrate the router into our server. Update server.go:




package main

import (
"log"
"net/http"
)

type Server struct {
Addr string
Router *Router
server *http.Server
}

func NewServer(addr string) *Server {
router := NewRouter()

server := &Server{
Addr: addr,
Router: router,
}

return server
}

func (s *Server) Start() {
s.server = &http.Server{
Addr: s.Addr,
Handler: s,
}
log.Println("Server starting at", s.Addr)
err := s.server.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.Router.ServeHTTP(w, r)
}






What changed?




  • Server now has a Router field


  • NewServer creates a router instance


  • ServeHTTP delegates to the router instead of handling routing itself






Creating Handler Functions



We need to update our handler functions to match our new HandlerFunc signature:




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

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

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

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

func post_hello(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello via POST!"))
}

func messages(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("You posted a new message"))
}

func post_getTime(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("POST request received on /time"))
}

func post_welcome(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Welcome to our Go Webserver from POST!"))
}






Note: We added the *http.Request parameter to each handler. Now our handlers have access to the full request information.






Registering Routes



Update main.go to register our routes using the new router API:




package main

import (
"fmt"
"net/http"
"time"
)

func main() {
server := NewServer(":3000")
setupRoutes(server)

server.Start()
}

func setupRoutes(s *Server) {
s.Router.GET("/", welcome)
s.Router.GET("/hello", hello)
s.Router.GET("/goodbye", goodbye)
s.Router.GET("/time", getTime)
s.Router.POST("/", post_welcome)
s.Router.POST("/hello", post_hello)
s.Router.POST("/messages", messages)
s.Router.POST("/time", post_getTime)
}






Look how clean this is! It reads just like Express or Gin route definitions.






Testing Our New Router



Let's test our router-based server:




go run .






Test different routes and methods:




# GET routes
curl http://localhost:3000/
curl http://localhost:3000/hello
curl http://localhost:3000/goodbye
curl http://localhost:3000/time

# POST routes
curl -X POST http://localhost:3000/
curl -X POST http://localhost:3000/hello
curl -X POST http://localhost:3000/messages

# Test 404s
curl http://localhost:3000/nonexistent
curl -X DELETE http://localhost:3000/hello






Expected behavior:




  • GET and POST routes work as expected

  • Unknown paths return "route not found"

  • Unsupported methods return "route not found"






What We've Accomplished





We now have:




  • ✅ Clean route registration (like Express/Gin)

  • ✅ Separation of concerns (routing logic separated from server logic)

  • ✅ HTTP method awareness (GET vs POST behave differently)

  • ✅ Proper error handling (404 for unknown routes)

  • ✅ Scalable architecture (easy to add new routes)






Current Limitations



Our router is much better, but still has some limitations:






1. No Dynamic Routes



We can't handle /users/123 or /products/456 - each route must be exactly defined.






2. No Middleware Support



Real APIs need logging, authentication, CORS, etc. We have no way to add these cross-cutting concerns.






3. Basic Error Responses



Our 404 response is just plain text - real APIs return JSON error responses.






What's Next?



In Chapter 4, we'll tackle the biggest limitation - dynamic routes. We'll enable routes like /users/:id and /products/:category/:id, and learn how to extract those parameters in our handlers.



This will bring us much closer to production-ready routing that can handle real API requirements.






Challenge: Try adding some new routes using different HTTP methods. Add a DELETE route for /users and a PUT route for /messages. See how easy it is now compared to our switch statement approach!

SOC Incident Playbook: Vulnerability Remediation & Verification
title: Detect Exploitation - Building Web Servers from First Principles (Part 3)
id: 5a539be9-1154-4f90-84ea-4a6ac55bf562
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-24
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-24"
        description = "YARA Signature for "
    strings:
        $str = "Building Web Servers from Firs" ascii wide
    condition:
        any of them
}
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich Building Web Servers from First Principl.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

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

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-97056 | SigNoz versions from v0.98.0 up to (but not including) v0.143.0, when co…
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 TTP ⏱️ 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