ggicci / httpin

🍑 HTTP Input for Go - HTTP Request from/to Go Struct (Bi-directional Data Binding between Go Struct and http.Request)
https://ggicci.github.io/httpin/
MIT License
315 stars 23 forks source link
data-binding go go-api go-http go-http-middleware go-http-requests go-rest-api http-request-params-reader

httpin logo

httpin - HTTP Input for Go

HTTP Request from/to Go Struct

[![Go](https://github.com/ggicci/httpin/actions/workflows/go.yml/badge.svg?branch=main)](https://github.com/ggicci/httpin/actions/workflows/go.yml) [![documentation](https://github.com/ggicci/httpin/actions/workflows/documentation.yml/badge.svg?branch=documentation)](https://github.com/ggicci/httpin/actions/workflows/documentation.yml) [![codecov](https://codecov.io/gh/ggicci/httpin/branch/main/graph/badge.svg?token=RT61L9ngHj)](https://codecov.io/gh/ggicci/httpin) [![Go Report Card](https://goreportcard.com/badge/github.com/ggicci/httpin)](https://goreportcard.com/report/github.com/ggicci/httpin) [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go) [![Go Reference](https://pkg.go.dev/badge/github.com/ggicci/httpin.svg)](https://pkg.go.dev/github.com/ggicci/httpin)
Documentation

Core Features

httpin helps you easily decode data from an HTTP request, including:

You only need to define a struct to receive/bind data from an HTTP request, without writing any parsing stuff code by yourself.

Since v0.15.0, httpin also supports creating an HTTP request (http.Request) from a Go struct instance.

httpin is:

Add Httpin Directives by Tagging the Struct Fields with in

type ListUsersInput struct {
    Token    string  `in:"query=access_token;header=x-access-token"`
    Page     int     `in:"query=page;default=1"`
    PerPage  int     `in:"query=per_page;default=20"`
    IsMember bool    `in:"query=is_member"`
    Search   *string `in:"query=search;omitempty"`
}

How to decode an HTTP request to Go struct?

func ListUsers(rw http.ResponseWriter, r *http.Request) {
    input := r.Context().Value(httpin.Input).(*ListUsersInput)

    if input.IsMember {
        // Do sth.
    }
    // Do sth.
}

How to encode a Go struct to HTTP request?

func SDKListUsers() {
    payload := &ListUsersInput{
        Token:    os.Getenv("MY_APP_ACCESS_TOKEN"),
        Page:     2,
        IsMember: true,
    }

    // Easy to remember, http.NewRequest -> httpin.NewRequest
    req, err := httpin.NewRequest("GET", "/users", payload)
    // ...
}

Why this package?

Compared with using net/http package

func ListUsers(rw http.ResponseWriter, r *http.Request) {
    page, err := strconv.ParseInt(r.FormValue("page"), 10, 64)
    if err != nil {
        // Invalid parameter: page.
        return
    }
    perPage, err := strconv.ParseInt(r.FormValue("per_page"), 10, 64)
    if err != nil {
        // Invalid parameter: per_page.
        return
    }
    isMember, err := strconv.ParseBool(r.FormValue("is_member"))
    if err != nil {
        // Invalid parameter: is_member.
        return
    }

    // Do sth.
}
Benefits Before (use net/http package) After (use ggicci/httpin package)
βŒ›οΈ Developer Time 😫 Expensive (too much parsing stuff code) πŸš€ Faster (define the struct for receiving input data and leave the parsing job to httpin)
♻️ Code Repetition Rate 😞 High 😍 Lower
πŸ“– Code Readability 😟 Poor 🀩 Highly readable
πŸ”¨ Maintainability 😑 Poor πŸ₯° Highly maintainable

Alternatives and Similars