middleware helmet changes.
router check and panic message change. README enhancement
This commit is contained in:
234
README.md
234
README.md
@@ -1,115 +1,153 @@
|
||||
# Mux
|
||||
# Mux - A Lightweight HTTP Router for Go
|
||||
|
||||
Tiny wrapper around Go's builtin http.ServeMux with easy routing methods.
|
||||
Mux is a simple, lightweight HTTP router for Go that wraps around the standard `http.ServeMux` to provide additional functionality and a more ergonomic API.
|
||||
|
||||
## Example
|
||||
## Features
|
||||
|
||||
- HTTP method-specific routing (GET, POST, PUT, DELETE, etc.)
|
||||
- Middleware support with flexible stacking
|
||||
- Route grouping for organization and shared middleware
|
||||
- RESTful resource routing
|
||||
- URL parameter extraction
|
||||
- Graceful shutdown support
|
||||
- Minimal dependencies (only uses Go standard library)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get code.patial.tech/go/mux
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"gitserver.in/patialtech/mux"
|
||||
"code.patial.tech/go/mux"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// create a new router
|
||||
r := mux.NewRouter()
|
||||
// Create a new router
|
||||
router := mux.NewRouter()
|
||||
|
||||
// you can use any middleware that is: "func(http.Handler) http.Handler"
|
||||
// so you can use any of it
|
||||
// - https://github.com/gorilla/handlers
|
||||
// - https://github.com/go-chi/chi/tree/master/middleware
|
||||
|
||||
// add some root level middlewares, these will apply to all routes after it
|
||||
r.Use(middleware1, middleware2)
|
||||
|
||||
// let's add a route
|
||||
r.GET("/hello", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("i am route /hello"))
|
||||
})
|
||||
// r.Post(pattern string, h http.HandlerFunc)
|
||||
// r.Put(pattern string, h http.HandlerFunc)
|
||||
// ...
|
||||
|
||||
// you can inline middleware(s) to a route
|
||||
r.
|
||||
With(mwInline).
|
||||
GET("/hello-2", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("i am route /hello-2 with my own middleware"))
|
||||
})
|
||||
|
||||
// define a resource
|
||||
r.Resource("/photos", func(resource *mux.Resource) {
|
||||
// rails style resource routes
|
||||
// GET /photos
|
||||
// GET /photos/new
|
||||
// POST /photos
|
||||
// GET /photos/:id
|
||||
// GET /photos/:id/edit
|
||||
// PUT /photos/:id
|
||||
// PATCH /photos/:id
|
||||
// DELETE /photos/:id
|
||||
resource.Index(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("all photos"))
|
||||
})
|
||||
|
||||
resource.New(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("upload a new pohoto"))
|
||||
})
|
||||
// Define a simple route
|
||||
router.GET("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, "Hello, World!")
|
||||
})
|
||||
|
||||
// create a group of few routes with their own middlewares
|
||||
r.Group(func(grp *mux.Router) {
|
||||
grp.Use(mwGroup)
|
||||
grp.GET("/group", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("i am route /group"))
|
||||
})
|
||||
})
|
||||
|
||||
// catches all
|
||||
r.GET("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("hello there"))
|
||||
})
|
||||
|
||||
// Serve allows graceful shutdown, you can use it
|
||||
r.Serve(func(srv *http.Server) error {
|
||||
srv.Addr = ":3001"
|
||||
// srv.ReadTimeout = time.Minute
|
||||
// srv.WriteTimeout = time.Minute
|
||||
|
||||
slog.Info("listening on http://localhost" + srv.Addr)
|
||||
return srv.ListenAndServe()
|
||||
})
|
||||
}
|
||||
|
||||
func middleware1(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
slog.Info("i am middleware 1")
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func middleware2(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
slog.Info("i am middleware 2")
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func mwInline(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
slog.Info("i am inline middleware")
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func mwGroup(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
slog.Info("i am group middleware")
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
// Start the server
|
||||
http.ListenAndServe(":8080", router)
|
||||
}
|
||||
```
|
||||
|
||||
## Routing
|
||||
|
||||
Mux supports all HTTP methods defined in the Go standard library:
|
||||
|
||||
```go
|
||||
router.GET("/users", listUsers)
|
||||
router.POST("/users", createUser)
|
||||
router.PUT("/users/{id}", updateUser)
|
||||
router.DELETE("/users/{id}", deleteUser)
|
||||
router.PATCH("/users/{id}", partialUpdateUser)
|
||||
router.HEAD("/users", headUsers)
|
||||
router.OPTIONS("/users", optionsUsers)
|
||||
router.TRACE("/users", traceUsers)
|
||||
router.CONNECT("/users", connectUsers)
|
||||
```
|
||||
|
||||
## URL Parameters
|
||||
|
||||
Mux supports URL parameters using curly braces:
|
||||
|
||||
```go
|
||||
router.GET("/users/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
fmt.Fprintf(w, "User ID: %s", id)
|
||||
})
|
||||
```
|
||||
|
||||
## Middleware
|
||||
|
||||
Middleware functions take an `http.Handler` and return an `http.Handler`. You can add global middleware to all routes:
|
||||
|
||||
```go
|
||||
// Logging middleware
|
||||
func loggingMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Printf("[%s] %s\n", r.Method, r.URL.Path)
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// Add middleware to all routes
|
||||
router.Use(loggingMiddleware)
|
||||
```
|
||||
|
||||
## Route Groups
|
||||
|
||||
Group related routes and apply middleware to specific groups:
|
||||
|
||||
```go
|
||||
// API routes group
|
||||
router.Group(func(api *mux.Router) {
|
||||
// Middleware only for API routes
|
||||
api.Use(authMiddleware)
|
||||
|
||||
// API routes
|
||||
api.GET("/api/users", listUsers)
|
||||
api.POST("/api/users", createUser)
|
||||
})
|
||||
```
|
||||
|
||||
## RESTful Resources
|
||||
|
||||
Easily define RESTful resources:
|
||||
|
||||
```go
|
||||
router.Resource("/posts", func(r *mux.Resource) {
|
||||
r.Index(listPosts) // GET /posts
|
||||
r.Show(showPost) // GET /posts/{id}
|
||||
r.Create(createPost) // POST /posts
|
||||
r.Update(updatePost) // PUT /posts/{id}
|
||||
r.Destroy(deletePost) // DELETE /posts/{id}
|
||||
r.New(newPostForm) // GET /posts/new
|
||||
})
|
||||
```
|
||||
|
||||
## Graceful Shutdown
|
||||
|
||||
Use the built-in graceful shutdown functionality:
|
||||
|
||||
```go
|
||||
router.Serve(func(srv *http.Server) error {
|
||||
srv.Addr = ":8080"
|
||||
return srv.ListenAndServe()
|
||||
})
|
||||
```
|
||||
|
||||
## Custom 404 Handler
|
||||
|
||||
can be tried like this
|
||||
|
||||
```go
|
||||
router.GET("/", func(writer http.ResponseWriter, request *http.Request) {
|
||||
if request.URL.Path != "/" {
|
||||
writer.WriteHeader(404)
|
||||
writer.Write([]byte(`not found, da xiong dei !!!`))
|
||||
return
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Full Example
|
||||
|
||||
See the [examples directory](./example) for complete working examples.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
|
||||
|
Reference in New Issue
Block a user