Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

routy

routy is a lightweight, composable HTTP router built on top of Go’s standard net/http package. It allows you to register handlers, subroutes, and middlewares with a clean, fluent API.


Installation

go get github.com/skipperoo/routy

Basic Usage

Here's an example project structure:

.
├── main.go
├── internal/
│   ├── handler/
│   │   └── handler1.go
│   ├── middleware/
│   │   ├── auth.go
│   │   └── cors.go
│   └── service/
│       └── func.go
└── go.mod

To create a basic router:

package main

import (
    "fmt"
    "net/http"
    "github.com/skipperoo/routy"
)

func main() {
    router := routy.NewRouter()

    router.AddHandler("/hello", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello, World!")
    })
    router.Finalize()

    http.ListenAndServe(":8080", router)
}

You can also specify methods and use path parameters:

router.
    AddHandler("GET /users", getUsers).
    AddHandler("POST /users", createUser).
    AddHandler("GET /users/{id}", getUserByID)

func getUsers(w http.ResponseWriter, r* http.Request) {
    id := r.PathValue("id")
    // Use id
    fmt.Fprintf(w, "User ID: %s", id)
}

You can add middlewares and combine them with subroutes:

func Auth(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        token := r.Header.Get("Authorization")
        // Validate your token
    })
}

func main() {

    router := routy.NewRouter()

    router.AddHandler("/hello", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello, World!")
    }).
    AddMiddleware(Logging)
    subRouter := routy.NewRouter().
    AddHandler("/supersecret", func(w http.ResponseWriter, r *http.Request){}).
    AddMiddleware(Auth).
    Finalize()

    // Now /hello will be public, while /auth/* will be protected,
    // while both will use the Logging middleware
    router.AddSubroute("/auth/", subRoute)
    router.Finalize()

    http.ListenAndServe(":8080", router)
}

Routy also provides two default configurable middlewares:

  • LoggingMiddleware to log requests. It accepts a function to write the log, which by default is set to log.Printf.
  • RecoverMiddleware to recover from panics while serving a request.
type RecoverFunction func(w http.ResponseWriter, r *http.Request)
recoverMw := routy.NewRecoverMiddleware(nil)

type LoggingFunction func(format string, v ...any)
func logToFile(format string, a ...any) {
    f, err := os.OpenFile(os.Getenv("LOG_FILE"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        return err
    }
    defer f.Close()

    _, err = fmt.Fprintf(f, format, a...)
}
loggingMw := routy.NewLoggingMiddleware(logToFile)

router.
    AddMiddleware(recoverMw.GetMiddleware()).
    AddMiddleware(loggingMw.GetMiddleware()).
    AddHandler("GET /ping", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "pong")
    })

Note on the LoggingMiddleware: v contains [ StatusCode: int, Method: string, UrlPath: string, ReqDurartion: Duration]. This means that you can create custom loggers that change the message format based on the request:

func BasicLogger(fmtStr string, args ...any) {
	prefix := "INFO"
	if statusCode, ok := args[0].(int); ok {
		if statusCode < 400 {
			prefix = "INFO"
		} else if statusCode < 500 {
			prefix = "WARNING"
		} else {
			prefix = "ERROR"
		}
	}
	fmt.Printf("[ %s ] - "+fmtStr+"\n", append([]any{prefix}, args...)...)
}

About

A simple go HTTP router

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages