NetLife Guru

Open source Go packages for fast, maintainable web systems. Built with a documentation-first approach.

Product
OverviewGolang packagesNews
Documentation
DocumentationGo LoggerGo RouterGo DB Form
Company
OverviewContactNewsGitHub
Community / Support
Supportinfo@netlife.guru
© 2026 NetLife Guru. All rights reserved.
GitHubinfo@netlife.guru
NetLife GuruNetLife GuruNetLife Guru
NetLife GuruNetLife GuruNetLife Guru
OverviewDocumentationNewsSupportContact

Golang packages

About
Route HandlersParameterized RoutesWildcard RoutesRoute GroupsMiddlewareGroup MiddlewareMounting Standard HandlersRequest Context
RouterCore Concepts

Route Handlers

Register HTTP route handlers using generic method registration, REST-style shortcuts, and standard HTTP methods.

Route handlers define how the router responds to incoming HTTP requests.

The router supports two styles of handler registration:

  • generic registration with HandleFunc
  • method-specific shortcuts such as GET, POST, PUT, and DELETE

All router-native handlers use the same signature:

func(w http.ResponseWriter, req *http.Request, ctx *router.Context)

The additional *router.Context gives handlers access to route parameters and request-scoped storage.


Handler Registration Methods

MethodPurpose
HandleFunc(path, methods, handler)Registers a handler for one or more HTTP methods
GET(path, handler)Registers a GET route
POST(path, handler)Registers a POST route
PUT(path, handler)Registers a PUT route
PATCH(path, handler)Registers a PATCH route
DELETE(path, handler)Registers a DELETE route
HEAD(path, handler)Registers a HEAD route
OPTIONS(path, handler)Registers an OPTIONS route
TRACE(path, handler)Registers a TRACE route
CONNECT(path, handler)Registers a CONNECT route

Generic Handler Registration

Use HandleFunc when a route should accept multiple HTTP methods.

r.HandleFunc("/documents", "GET POST", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
	if req.Method == http.MethodGet {
		w.Write([]byte(`{"action": "Reading document list"}`))
		return
	}

	if req.Method == http.MethodPost {
		w.WriteHeader(http.StatusCreated)
		w.Write([]byte(`{"action": "Creating a new document"}`))
		return
	}
})

Methods are passed as a space-separated string.

r.HandleFunc("/documents", "GET POST", handler)

Use ANY to allow all supported methods.

r.HandleFunc("/any", "ANY", handler)

Method Shortcuts

Use method-specific helpers for common REST-style APIs.

r.GET("/users/{id}", handler)
r.POST("/users", handler)
r.PUT("/users/{id}", handler)
r.PATCH("/users/{id}", handler)
r.DELETE("/users/{id}", handler)

These shortcuts make route definitions easier to scan and keep API code explicit.


Example

package main

import (
	"fmt"
	"log/slog"
	"net/http"
	"os"

	"github.com/netlifeguru/router"
)

func main() {
	r := router.New()

	r.UseDefaults()

	r.HandleFunc("/any", "ANY", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		w.Header().Set("Content-Type", "application/json")
		fmt.Fprintf(w, `{"message": "This catches anything!", "used_method": "%s"}`, req.Method)
	})

	r.HandleFunc("/documents", "GET POST", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		w.Header().Set("Content-Type", "application/json")

		if req.Method == http.MethodGet {
			w.Write([]byte(`{"action": "Reading document list"}`))
			return
		}

		if req.Method == http.MethodPost {
			w.WriteHeader(http.StatusCreated)
			w.Write([]byte(`{"action": "Creating a new document"}`))
			return
		}
	})

	r.GET("/users/{id}", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		id := ctx.Param("id")

		w.Header().Set("Content-Type", "application/json")
		fmt.Fprintf(w, `{"id": "%s", "name": "Alice"}`, id)
	})

	r.POST("/users", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusCreated)
		w.Write([]byte(`{"message": "User successfully created", "id": 3}`))
	})

	r.PUT("/users/{id:isDigits}", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		userID := ctx.Param("id")

		w.Header().Set("Content-Type", "application/json")
		fmt.Fprintf(w, `{"message": "User %s has been completely updated"}`, userID)
	})

	r.PATCH("/users/{id:isDigits}", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		userID := ctx.Param("id")

		w.Header().Set("Content-Type", "application/json")
		fmt.Fprintf(w, `{"message": "User %s has been partially updated"}`, userID)
	})

	r.DELETE("/users/{id:isDigits}", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		userID := ctx.Param("id")

		w.Header().Set("Content-Type", "application/json")
		fmt.Fprintf(w, `{"message": "User %s has been deleted"}`, userID)
	})

	r.HEAD("/ping", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		w.Header().Set("X-System-Status", "Online")
		w.Header().Set("Content-Length", "0")
		w.WriteHeader(http.StatusOK)
	})

	r.OPTIONS("/api", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		w.Header().Set("Allow", "OPTIONS, GET, POST, PUT, DELETE")
		w.WriteHeader(http.StatusNoContent)
	})

	r.TRACE("/echo", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		w.Header().Set("Content-Type", "message/http")
		w.WriteHeader(http.StatusOK)

		fmt.Fprintf(w, "%s %s %s\n", req.Method, req.URL.RequestURI(), req.Proto)

		for name, headers := range req.Header {
			for _, value := range headers {
				fmt.Fprintf(w, "%s: %s\n", name, value)
			}
		}
	})

	r.CONNECT("/tunnel", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("Tunnel connection established"))
	})

	if err := r.ListenAndServe(":8000"); err != nil {
		slog.Error("failed to start server", "error", err)
		os.Exit(1)
	}
}

HTTP Method Usage

MethodCommon Use
GETRetrieve a resource
POSTCreate a new resource or submit data
PUTReplace an existing resource
PATCHPartially update an existing resource
DELETERemove a resource
HEADRetrieve headers without a response body
OPTIONSDiscover supported methods or handle CORS preflight
TRACEDiagnostic request echoing
CONNECTEstablish a tunnel, commonly used by proxies
ANYAccept all supported HTTP methods

Route Parameters

Handlers can access route parameters through ctx.Param.

r.GET("/users/{id}", func(w http.ResponseWriter, req *http.Request, ctx *router.Context) {
	id := ctx.Param("id")

	w.Write([]byte(id))
})

Parameters can also be validated using route patterns:

r.GET("/users/{id:isDigits}", handler)

Pattern-based routing is covered in the dedicated route patterns section.


Notes

Use HandleFunc when one route should support multiple methods.

Use method-specific helpers when each HTTP method has its own behavior.

For standard net/http handlers without *router.Context, use Mount or MountFunc.

Getting Started

Learn how to create your first HTTP server with the NLG Router package using static routes, parameterized routes, and middleware-ready handlers.

Parameterized Routes

Use route parameters, prepared pattern matchers, and custom regex constraints to validate URL segments before requests reach handlers.

On this page

Handler Registration MethodsGeneric Handler RegistrationMethod ShortcutsExampleHTTP Method UsageRoute ParametersNotes