httprouter icon indicating copy to clipboard operation
httprouter copied to clipboard

Handle sub routing to separate http request

Open dzpt opened this issue 7 years ago • 1 comments

I want to execute code for two big routes like: /admin and /

Any route begins with /admin will be execute functions like load json for admin, load template for admin ... and other route '/' will load different resources for avoiding load both frontend and backend.

How i do it with httprouter?

dzpt avatar Jan 16 '18 04:01 dzpt


package main

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/julienschmidt/httprouter"
)

// AdminResource simulates admin-specific resources (e.g., JSON, template)
type AdminResource struct {
	JSONData    string
	TemplateData string
}

// FrontendResource simulates frontend-specific resources (e.g., JSON, template)
type FrontendResource struct {
	JSONData    string
	TemplateData string
}

// loadAdminJSON simulates loading admin JSON data
func loadAdminJSON() string {
	return `{"admin": "config"}` // Mock JSON
}

// loadAdminTemplate simulates loading an admin template
func loadAdminTemplate() string {
	return "admin_template.html" // Mock template
}

// loadFrontendJSON simulates loading frontend JSON data
func loadFrontendJSON() string {
	return `{"frontend": "config"}` // Mock JSON
}

// loadFrontendTemplate simulates loading a frontend template
func loadFrontendTemplate() string {
	return "frontend_template.html" // Mock template
}

// adminMiddleware loads admin-specific resources and attaches them to the request
func adminMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		// Load admin resources
		adminRes := AdminResource{
			JSONData:    loadAdminJSON(),
			TemplateData: loadAdminTemplate(),
		}
		fmt.Printf("Admin middleware: Loaded JSON=%s, Template=%s\n", adminRes.JSONData, adminRes.TemplateData)

		// In a real app, store resources in request context or pass to handler
		// For simplicity, we just call the next handler
		next(w, r, ps)
	}
}

// frontendMiddleware loads frontend-specific resources and attaches them to the request
func frontendMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		// Load frontend resources
		frontendRes := FrontendResource{
			JSONData:    loadFrontendJSON(),
			TemplateData: loadFrontendTemplate(),
		}
		fmt.Printf("Frontend middleware: Loaded JSON=%s, Template=%s\n", frontendRes.JSONData, frontendRes.TemplateData)

		// Call the next handler
		next(w, r, ps)
	}
}

// wrapHandler converts a standard http.HandlerFunc to an httprouter handler
func wrapHandler(h http.HandlerFunc, middleware func(http.HandlerFunc) http.HandlerFunc) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		middleware(h)(w, r, ps)
	}
}

// adminHandler handles specific admin routes
func adminHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	path := ps.ByName("path")
	if path == "" {
		path = "admin root"
	}
	fmt.Fprintf(w, "Admin route: /admin/%s\n", path)
}

// frontendHandler handles specific frontend routes
func frontendHandler(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	path := ps.ByName("path")
	if path == "" {
		path = "root"
	}
	fmt.Fprintf(w, "Frontend route: /%s\n", path)
}

func main() {
	// Create a new httprouter instance
	router := httprouter.New()

	// Admin routes: /admin/*path
	// All routes under /admin use adminMiddleware
	router.GET("/admin/*path", wrapHandler(adminHandler, adminMiddleware))
	
	// Specific admin routes (optional, to demonstrate exact matches)
	router.GET("/admin", wrapHandler(adminHandler, adminMiddleware))
	router.GET("/admin/users", wrapHandler(adminHandler, adminMiddleware))
	
	// Frontend routes: /*path
	// All other routes use frontendMiddleware
	router.GET("/*path", wrapHandler(frontendHandler, frontendMiddleware))
	
	// Specific frontend routes (optional, to demonstrate exact matches)
	router.GET("/", wrapHandler(frontendHandler, frontendMiddleware))
	router.GET("/about", wrapHandler(frontendHandler, frontendMiddleware))

	// Start the server
	fmt.Println("Server listening on :8080")
	if err := http.ListenAndServe(":8080", router); err != nil {
		fmt.Printf("Server error: %v\n", err)
	}
}

ljluestc avatar May 20 '25 02:05 ljluestc