grape

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 20, 2024 License: MIT Imports: 11 Imported by: 0

README

Grape 🍇

Grape is a modern, zero-dependency HTTP library for Go.

It's a thin wrapper around the standard library, providing helper functions to facilitate faster and easier development. Adding only a single dependency to your projects.

Features

  • Zero-dependency, 100% compatible with the standard library
  • Structured logging with log/slog
  • Using new, improved net/http router
  • Group routes and scope-specific middlewares
  • Read and write json via the encoding/json
  • Highly customizable; bring your own logger and serializer!
  • Helper functions for commonly used HTTP status code responses
  • Featuring a built-in validator package for data validation

Installation

You need Go version 1.22 or higher.

go get -u github.com/hossein1376/grape@latest

Usage

Main usage pattern is to embed Grape into the struct which handlers are a method to it, next to other fields like models, settings, etc.
In this approach, instead of changing handlers' argument to accept a specific context; all the helper methods are available through the receiver.

The following is a simple example. For more, check out the examples directory.

package main

import (
	"net/http"

	"github.com/hossein1376/grape"
)

type handler struct {
	// data/models
	// settings
	grape.Server
}

func main() {
	h := handler{Server: grape.New()} // grape.Server inside a struct
	r := grape.NewRouter()            // grape.Router for routing and starting the server 

	r.Use(h.LoggerMiddleware, h.RecoverMiddleware)
	r.Get("/{id}", h.paramHandler)

	if err := r.Serve(":3000"); err != nil {
		h.Error("failed to start server", "error", err)
		return
	}
}

func (h *handler) paramHandler(w http.ResponseWriter, r *http.Request) {
	h.Info("Param handler!")

	id, err := h.ParamInt(r, "id")
	if err != nil {
		h.NotFoundResponse(w)
		return
	}

	h.OkResponse(w, grape.Map{"id": id})
}

It is possible customize Grape for different use-cases. You can view more inside the examples directory.

Composability

Grape consists of several components independent of each other. Giving developers opt-in choice of features.

grape.Server

Providing methods for logging, interacting with json, common HTTP responses and some other useful utilities. It can be embedded inside a struct, placed as a regular field, instantiate as a global variable, or even being passed around through the context.
An instance of it is created by running grape.New() and its behaviour is customizable by passing grape.Options as an argument.

*grape.Router

Enable routing via methods named after HTTP verbs, with route grouping and scope-specific middlewares. Create a new instance by running grape.NewRouter().
All routes are registered on server's startup and the rest is handled by the standard library, causing zero runtime overhead.

validator package

Presenting wide range of functions for data validation. Start a new instance with validator.New(), then Check each part of your data with as many Cases it's necessary.

Why?

Go standard library is awesome. It's fast, easy to use, and has a great API.
With the addition of log/slog in go 1.21 and improved HTTP router in go 1.22, in most cases there are not many reasons to look any further. Instead of breaking compatibility with net/http, Grape aims to add commonly used functions within the arm's reach of the handlers.

Documentation

Overview

Package grape is a modern, zero-dependency HTTP library for Go. Visit https://github.com/hossein1376/grape for more information.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Logger added in v0.2.0

type Logger interface {
	Debug(msg string, args ...any)
	Info(msg string, args ...any)
	Warn(msg string, args ...any)
	Error(msg string, args ...any)
}

Logger interface exposes methods in different log levels, following the convention of slog.Logger.

type Map

type Map = map[string]any

Map is an alias type and is intended for json response marshalling.

type Options

type Options struct {
	Log            Logger
	Serialize      Serializer
	RequestMaxSize int64
}

Options is used to customize Grape's settings, by passing down an instance of it to grape.New().

Log should implement grape.Logger. Since slog.Logger automatically does, all instances of it can be used. Alongside of any other custom types. Default logger displays text logs to the standard output and in `info` level.

Serialize should implement grape.Serializer. Default serializer uses standard library `encoding/json` package.

RequestMaxSize sets maximum request's body size in bytes. This value will be taken into effect only if Serialize field was not provided. Default size is 1_048_576 bytes (1 mb).

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router provides methods such as Get, Post and Use (among others) for routing.

func NewRouter

func NewRouter() *Router

NewRouter will initialize a new router of type Router. This function is expected to be called only once. Subsequent sub-path Router instance are created by the Group method.

func (*Router) Delete

func (r *Router) Delete(route string, handler http.HandlerFunc)

Delete calls Method with http.MethodDelete.

func (*Router) Get

func (r *Router) Get(route string, handler http.HandlerFunc)

Get calls Method with http.MethodGet.

func (*Router) Group added in v0.2.0

func (r *Router) Group(prefix string) *Router

Group creates a new Router instance from the current one, inheriting scope and middlewares.

func (*Router) Method

func (r *Router) Method(method, route string, handler http.HandlerFunc)

Method accept a http method, route and one handler. As a bonus, if the provided route has a trailing slash, it disables net/http's default catch-all behaviour.

func (*Router) Patch

func (r *Router) Patch(route string, handler http.HandlerFunc)

Patch calls Method with http.MethodPatch.

func (*Router) Post

func (r *Router) Post(route string, handler http.HandlerFunc)

Post calls Method with http.MethodPost.

func (*Router) Put

func (r *Router) Put(route string, handler http.HandlerFunc)

Put calls Method with http.MethodPut.

func (*Router) Serve

func (r *Router) Serve(addr string, server ...*http.Server) error

Serve will start the server on the provided address. It makes no difference on which instance of Router this method is called from.

It takes an optional argument to modify the http.Server's configurations. Note that two fields Addr and Handler are populated by the function and will be ignored if provided.

func (*Router) ServeTLS added in v0.3.0

func (r *Router) ServeTLS(addr string, certFile string, keyFile string, server ...*http.Server) error

ServeTLS will start a TLS server on the provided address. Same as the Serve method, it makes no difference on which instance of Router this method is called from.

Certificate and private key files must be passed as second and third arguments. It takes an optional argument to modify the http.Server's configurations as well. Note that two fields Addr and Handler are populated by the function and will be ignored if provided.

func (*Router) Use

func (r *Router) Use(middlewares ...func(http.Handler) http.Handler)

Use add middlewares to the routes that are defined after it. Note that declared middlewares won't be applied to the previous routes or the default handlers such as NotFound or MethodNotAllowed.

func (*Router) UseAll

func (r *Router) UseAll(middlewares ...func(http.Handler) http.Handler)

UseAll will add declared middleware to all the handlers. No matter defined before or after it; as well as the default handlers such as NotFound or MethodNotAllowed.

These middlewares will take precedence over all other middlewares on the same scope and path.

type Serializer added in v0.2.0

type Serializer interface {
	WriteJson(w http.ResponseWriter, status int, data any, headers http.Header) error
	ReadJson(w http.ResponseWriter, r *http.Request, dst any) error
}

Serializer interface consists of two methods, one for reading json inputs and one for writing json outputs.

type Server

type Server struct {
	Logger
	Serializer
	// contains filtered or unexported fields
}

Server is the main struct of Grape with three embedded types; Logger, Serializer and response. Main usage pattern is to included it in the same struct that your handlers are a method to, so the helper methods are accessible through the receiver.

func New

func New(opts ...Options) Server

New returns a new instance of grape.Server. It optionally accepts grape.Options to customize Grape's settings.

func (Server) BadRequestResponse

func (res Server) BadRequestResponse(w http.ResponseWriter, err ...error)

BadRequestResponse indicates that the request has been deemed unacceptable by server, responding with status code 400. It accepts optional error message. If not provided, generic response message will be used.

func (Server) CreatedResponse

func (res Server) CreatedResponse(w http.ResponseWriter, data any)

CreatedResponse indicates that requested resource(s) have been successfully created, it responses with status code 201.

func (Server) ForbiddenResponse

func (res Server) ForbiddenResponse(w http.ResponseWriter)

ForbiddenResponse indicates that the action is not allowed, returning status code 403.

func (Server) Go added in v0.3.0

func (server Server) Go(f func())

Go spawns a new goroutine and will recover in case of panic; logging the error message in Error level. Using this function ensures that panic in goroutines will not stop the application's execution.

func (Server) InternalServerErrorResponse

func (res Server) InternalServerErrorResponse(w http.ResponseWriter)

InternalServerErrorResponse indicates something has gone wrong unexpectedly, returning status code 500.

func (Server) LoggerMiddleware

func (server Server) LoggerMiddleware(next http.Handler) http.Handler

LoggerMiddleware logs incoming request's method and URI in `info` level.

func (Server) NoContentResponse

func (res Server) NoContentResponse(w http.ResponseWriter)

NoContentResponse means the operation was successful, and server has nothing more to say about it, it will response with status code 204.

func (Server) NotFoundResponse

func (res Server) NotFoundResponse(w http.ResponseWriter, err ...error)

NotFoundResponse will return with classic 404 error message. if an error message is provided, it will return that instead.

func (Server) OkResponse

func (res Server) OkResponse(w http.ResponseWriter, data any)

OkResponse means everything went as expected and responses with status code 200.

func (Server) ParamInt

func (server Server) ParamInt(r *http.Request, name string) (int, error)

ParamInt extracts the parameter by its name from request and converts it to integer. It will return 0 and an error if no parameter was found, or there was an error converting it to int.

func (Server) ParamInt64

func (server Server) ParamInt64(r *http.Request, name string) (int64, error)

ParamInt64 extracts the parameter by its name from request and converts it to 64-bit integer. It will return 0 and an error if no parameter was found, or there was an error converting it to int64.

func (Server) RecoverMiddleware

func (server Server) RecoverMiddleware(next http.Handler) http.Handler

RecoverMiddleware will recover from panics. It'll display a log in `error` level with the error message.

func (Server) Response

func (res Server) Response(w http.ResponseWriter, statusCode int, message any)

Response is a general function which responses with the provided message and status code, it will return 500 in case of failure.

func (Server) UnauthorizedResponse

func (res Server) UnauthorizedResponse(w http.ResponseWriter)

UnauthorizedResponse responds when user is not authorized, returning status code 401.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL