Go http middleware handler for request coalescing

HTTP Coala

NOTE: a new and improved implementation is available at https://github.com/go-chi/stampede

Just a little bit of performance enhancing middleware -- HTTP Coala (aka Coalescer).

HTTP Coala is a middleware handler that routes multiple requests for the same URI (and routed methods) to be processed as a single request. I don't recommend it for every web service or handler chain, but for the computationally expensive handlers that always yield the same response, HTTP Coala will give you a speed boost.

It's common among HTTP reverse proxy cache servers such as nginx, Squid or Varnish - they all call it something else but works similarly.

Usage

Example with goji

// from _example/main.go ....
func main() {
	r := chi.NewRouter()

	r.Use(middleware.Logger)
	r.Use(httpcoala.Route("HEAD", "GET")) // or, Route("*")
	// r.Use(otherMiddleware)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		time.Sleep(100 * time.Millisecond) // expensive op
		w.WriteHeader(200)
		w.Write([]byte("hi"))
	})

	http.ListenAndServe(":1111", r)
}

as well, look at httpcoala_test.go

Benchmarks

For a naive benchmark on my local Macbook pro, I used wrk with -c 100 and -t 100 on a web service that downloads an image and returns a resized version.

Without httpcoala middleware, Requests/sec:   7081.09
   With httpcoala middleware, Requests/sec:  18373.87

TODO

  • Allow a request key to be passed that determines when to coalesce requests. It would allow for more control such as grouping by a query param or header.

License

Brought to you by the Pressly Go team - www.pressly.com / https://github.com/pressly

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Similar Resources

Timeout handler for http request in Gin framework

Middleware to Handle Request Timeout in Gin Installation Installation go get github.com/s-wijaya/gin-timeout Import it in your code: import ( // o

Dec 14, 2021

Gin middleware/handler to enable CORS support.

wcors Gin middleware/handler to enable CORS support. Usage Start using it Download and install it: go get github.com/wyy-go/wcors Import it in your co

Jan 8, 2022

Request: a HTTP request library for Go with interfaces and mocks for unit tests

Requester Request is a HTTP request library for Go with interfaces and mocks for

Jan 10, 2022

Goget will send a http request, and show the request time, status, response, and save response to a file

Goget will send a http request, and show the request time, status, response, and save response to a file

Feb 9, 2022

Muxie is a modern, fast and light HTTP multiplexer for Go. Fully compatible with the http.Handler interface. Written for everyone.

Muxie is a modern, fast and light HTTP multiplexer for Go. Fully compatible with the http.Handler interface. Written for everyone.

Muxie ๐Ÿš‚ ๐Ÿš‹ ๐Ÿš‹ ๐Ÿš‹ ๐Ÿš‹ ๐Ÿš‹ Fast trie implementation designed from scratch specifically for HTTP A small and light router for creating sturdy backend Go a

Dec 8, 2022

Validate Golang request data with simple rules. Highly inspired by Laravel's request validation.

Validate Golang request data with simple rules. Highly inspired by Laravel's request validation.

Validate golang request data with simple rules. Highly inspired by Laravel's request validation. Installation Install the package using $ go get githu

Dec 29, 2022

github-actions-merger is github actions that merges pull request with commit message including pull request labels.

github-actions-merger github-actions-merger is github actions that merges pull request with commit message including pull request labels. Usage Write

Dec 7, 2022

Add request id to a request's context

RequestID ๐Ÿ”Ž This is a very simple piece of middleware for adding request/correlation IDs to the context of a http request. By default, this module wi

Dec 4, 2021

gorilla/csrf provides Cross Site Request Forgery (CSRF) prevention middleware for Go web applications & services ๐Ÿ”’

gorilla/csrf gorilla/csrf is a HTTP middleware library that provides cross-site request forgery (CSRF) protection. It includes: The csrf.Protect middl

Dec 26, 2022

Go middleware for monetizing your API on a per-request basis with Bitcoin and Lightning โšก๏ธ

ln-paywall Go middleware for monetizing your API on a per-request basis with Bitcoin and Lightning โšก๏ธ Middlewares for: net/http HandlerFunc net/http H

Jan 6, 2023

gorilla/csrf provides Cross Site Request Forgery (CSRF) prevention middleware for Go web applications & services ๐Ÿ”’

gorilla/csrf gorilla/csrf is a HTTP middleware library that provides cross-site request forgery (CSRF) protection. It includes: The csrf.Protect middl

Jan 9, 2023

Header Block is a middleware plugin for Traefik to block request and response headers which regex matched by their name and/or value

Header Block is a middleware plugin for Traefik to block request and response headers which regex matched by their name and/or value Conf

May 24, 2022

Just a playground with some interesting concepts like pipelines aka middleware, handleFuncs, request validations etc. Check it out.

Pipeline a.k.a middleware in Go Just a playground with some interesting concepts like pipelines aka middleware, handleFuncs, request validations etc.

Dec 9, 2021

Gin-errorhandling - Gin Error Handling Middleware is a middleware for the popular Gin framework

Gin Error Handling Middleware Gin Error Handling Middleware is a middleware for

Sep 19, 2022

Go net/http configurable handler to handle CORS requests

Go CORS handler CORS is a net/http handler implementing Cross Origin Resource Sharing W3 specification in Golang. Getting Started After installing Go

Jan 7, 2023

Go net/http handler to transparently manage posted JSON

Go JSON handler FormJSON is a net/http handler implementing content negotiation for posted data in order to transparently expose posted JSON as if it

Sep 27, 2022

Composable chains of nested http.Handler instances.

chain go get github.com/codemodus/chain Package chain aids the composition of nested http.Handler instances. Nesting functions is a simple concept. I

Sep 27, 2022

A net.http.Handler similar to FileServer that serves gzipped content

net.http.handler.gzip: a FileServer that serves gzipped content. Usage: import "net/http/handler/gzip" base := "/path/to/website/static/files" http

Mar 14, 2022
Comments
  • batchWriter creates buffers as required, without any constraint

    batchWriter creates buffers as required, without any constraint

    Consider the following program that creates 500 concurrent requests to slightly different URLs:

    package main
    
    import (
            "crypto/rand"
            "errors"
            "fmt"
            //"github.com/goware/httpcoala"
            "github.com/pressly/chi"
            "github.com/pressly/chi/middleware"
            "log"
            "net/http"
            "sync"
            "time"
    )
    
    var mockData []byte
    
    func init() {
            mockData = make([]byte, 1024*1024*20)
            rand.Read(mockData)
    }
    
    func doRequest(i int) error {
            res, err := http.Get(fmt.Sprintf("http://127.0.0.1:1111/?_=%d", i))
            if err != nil {
                    return err
            }
            defer res.Body.Close()
    
            if res.StatusCode != 200 {
                    return errors.New("Expecting 200 OK.")
            }
    
            return err
    }
    
    func main() {
    
            r := chi.NewRouter()
    
            r.Use(middleware.Logger)
            //r.Use(httpcoala.Route("HEAD", "GET")) // or, Route("*")
    
            r.Get("/", func(w http.ResponseWriter, r *http.Request) {
                    time.Sleep(time.Second * 2) // expensive op
                    w.WriteHeader(200)
                    w.Write(mockData)
            })
    
            go http.ListenAndServe(":1111", r)
    
            time.Sleep(time.Second * 1)
    
            var wg sync.WaitGroup
    
            for i := 0; i < 500; i++ {
                    wg.Add(1)
                    go func(i int) {
                            if err := doRequest(i); err != nil {
                                    log.Fatal("doRequest: ", err)
                            }
                            wg.Done()
                    }(i)
            }
    
            wg.Wait()
    }
    

    If you run this program on a 2G vm nothing interesting happens, but if you remove the commented out lines to use httpcoala and run the program again you'll see something like this:

    screen shot 2015-12-07 at 2 45 16 pm

    You'll probably have to ^C it to prevent the vm from crashing.

    I think the problem is that httpcoala tries to allocate as many buffers as possible, without imposing any hard limit.

Idiomatic HTTP Middleware for Golang

Negroni Notice: This is the library formerly known as github.com/codegangsta/negroni -- Github will automatically redirect requests to this repository

Dec 31, 2022
Dead simple rate limit middleware for Go.

Limiter Dead simple rate limit middleware for Go. Simple API "Store" approach for backend Redis support (but not tied too) Middlewares: HTTP, FastHTTP

Jan 1, 2023
A lightweight and fast http router from outer space

Alien Alien is a lightweight http router( multiplexer) for Go( Golang ), made for humans who don't like magic. Documentation docs Features fast ( see

Nov 13, 2022
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

Gin Web Framework Gin is a web framework written in Go (Golang). It features a martini-like API with performance that is up to 40 times faster thanks

Jan 2, 2023
Simple HTTP and REST client library for Go

Resty Simple HTTP and REST client library for Go (inspired by Ruby rest-client) Features section describes in detail about Resty capabilities Resty Co

Jan 9, 2023
Go HTTP router

violetear Go HTTP router http://violetear.org Design Goals Keep it simple and small, avoiding extra complexity at all cost. KISS Support for static an

Dec 10, 2022
Custom generic HTTP handler providing automatic JSON decoding/encoding of HTTP request/response to your concrete types

gap Custom generic HTTP handler providing automatic JSON decoding/encoding of HTTP request/response to your concrete types. gap.Wrap allows to use the

Aug 28, 2022
A minimal framework to build web apps; with handler chaining, middleware support; and most of all standard library compliant HTTP handlers(i.e. http.HandlerFunc).
A minimal framework to build web apps; with handler chaining, middleware support; and most of all standard library compliant HTTP handlers(i.e. http.HandlerFunc).

WebGo v4.1.3 WebGo is a minimalistic framework for Go to build web applications (server side) with zero 3rd party dependencies. Unlike full-fledged fr

Jan 1, 2023
Timeout wraps a handler and aborts the process of the handler if the timeout is reached.

Timeout Timeout wraps a handler and aborts the process of the handler if the timeout is reached. Example package main import ( "context" "fmt" "gi

Jan 8, 2022