Giter Club home page Giter Club logo

httpw's Introduction

httpw

godoc Licence Latest version

Build Status Code quality Code coverage

Idiomatic HTTP handler signature that requires no magic.

Motivation

On one hand, I hate when people are creating libraries that require to change the signature of a http handler (http.HandlerFunc) without any usage-related reasons (hi gin). There is nearly nothing impossible to do with the actual net/http handler signature. On another hand, I have few problems related to the actual net/http handler signature:

  • there is no return argument, so when I call rw.WriteHeader on any condition I always forget to call return after ; I find this so not go idiomatic to require multiple lines to handle simple things
  • there is no simple way to ensure the same response and error format, the same way of handling them, on all handlers when multiple people write multiple handlers
  • tests require httptest.NewRecorder because nothing is returned, IMO it's boring

So I started thinking on removing the possibility of using directly the http.ResponseWriter and returning an argument that will fill it instead.

I also wanted to still be fully net/http compliant as I really don't want to create yet another framework that handle and force too much things like routing, handlers, tests, ...

The solution I found and iterate on for multiple weeks is the following: func(r *http.Request) (*httpw.Response, error). With the following signature any handlers can handle the request as they would normally do, yet does not handle how response is wrote nor how errors are handled. This is leave to a callback that write the response, and another callback to handle the error, if any (for example adding fields in a logger, set a tracing span to any status, ...).

Usage and example

All httpw.Handler handlers can be used as normal net/http handlers with httpw.Wrap method.

// doSomething will return 200 if everything succeeds
// or 500 if something went wrong
func doSomething(r *http.Request) (*httpw.R, error) {
    var userID = getUserID(r)

    if err := doSomething(r.Context(), userID); err != nil {
        return nil, errors.Wrapf(err, "unable to do something with user %s", userID)
    }

    return &httpw.R{Status: http.StatusOK}
}
func doSomething(r *http.Request) (*httpw.R, error) {
    var userID = getUserID(r)

    user, err := getSomething(r.Context(), userID)
    if err != nil {
        var e httpw.E
        if nfErr, ok := err.(NotFoundError); ok && nfErr() {
            e.Status = http.Status
        }
        return nil, e
    }

    return &httpw.R{
        Status: http.StatusOK,
        Data:   user,
    }
}

By default, if a standard error is returned, the request status will be set to http.StatusInternalServerError. This behaviour can be change by passing options to the wrapper. Here are all the differents options:

func setupRoutes() {
    var wrapper = httpw.New(
        httpw.WithDefaultErrorStatus(http.StatusServiceUnavailable),
        httpw.WithOnErrorCallback(logOnError),
        httpw.WithDataMarshaler(json.Marshal),
    )

    router.Get("/something", wrapper.Wrap(doSomething))
}

One last things: there are two aliases, httpw.R for httpw.Response and httpw.E for httpw.Error

License

This project is under the MIT licence, please see the LICENCE file.

httpw's People

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.