Go package for easily rendering JSON, XML, binary data, and HTML templates responses.

Overview

Render GoDoc Test

Render is a package that provides functionality for easily rendering JSON, XML, text, binary data, and HTML templates. This package is based on the Martini render work.

Block Deprecation Notice

Go 1.6 introduces a new block action. This conflicts with Render's included block template function. To provide an easy migration path, a new function was created called partial. It is a duplicate of the old block function. It is advised that all users of the block function update their code to avoid any issues in the future. Previous to Go 1.6, Render's block functionality will continue to work but a message will be logged urging you to migrate to the new partial function.

Usage

Render can be used with pretty much any web framework providing you can access the http.ResponseWriter from your handler. The rendering functions simply wraps Go's existing functionality for marshaling and rendering data.

  • HTML: Uses the html/template package to render HTML templates.
  • JSON: Uses the encoding/json package to marshal data into a JSON-encoded response.
  • XML: Uses the encoding/xml package to marshal data into an XML-encoded response.
  • Binary data: Passes the incoming data straight through to the http.ResponseWriter.
  • Text: Passes the incoming string straight through to the http.ResponseWriter.
// main.go
package main

import (
    "encoding/xml"
    "net/http"

    "github.com/unrolled/render"  // or "gopkg.in/unrolled/render.v1"
)

type ExampleXml struct {
    XMLName xml.Name `xml:"example"`
    One     string   `xml:"one,attr"`
    Two     string   `xml:"two,attr"`
}

func main() {
    r := render.New()
    mux := http.NewServeMux()

    mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        w.Write([]byte("Welcome, visit sub pages now."))
    })

    mux.HandleFunc("/data", func(w http.ResponseWriter, req *http.Request) {
        r.Data(w, http.StatusOK, []byte("Some binary data here."))
    })

    mux.HandleFunc("/text", func(w http.ResponseWriter, req *http.Request) {
        r.Text(w, http.StatusOK, "Plain text here")
    })

    mux.HandleFunc("/json", func(w http.ResponseWriter, req *http.Request) {
        r.JSON(w, http.StatusOK, map[string]string{"hello": "json"})
    })

    mux.HandleFunc("/jsonp", func(w http.ResponseWriter, req *http.Request) {
        r.JSONP(w, http.StatusOK, "callbackName", map[string]string{"hello": "jsonp"})
    })

    mux.HandleFunc("/xml", func(w http.ResponseWriter, req *http.Request) {
        r.XML(w, http.StatusOK, ExampleXml{One: "hello", Two: "xml"})
    })

    mux.HandleFunc("/html", func(w http.ResponseWriter, req *http.Request) {
        // Assumes you have a template in ./templates called "example.tmpl"
        // $ mkdir -p templates && echo "<h1>Hello {{.}}.</h1>" > templates/example.tmpl
        r.HTML(w, http.StatusOK, "example", "World")
    })

    http.ListenAndServe("127.0.0.1:3000", mux)
}
<!-- templates/example.tmpl -->
<h1>Hello {{.}}.</h1>

Available Options

Render comes with a variety of configuration options (Note: these are not the default option values. See the defaults below.):

// ...
r := render.New(render.Options{
    Directory: "templates", // Specify what path to load the templates from.
    FileSystem: &LocalFileSystem{}, // Specify filesystem from where files are loaded.
    Asset: func(name string) ([]byte, error) { // Load from an Asset function instead of file.
      return []byte("template content"), nil
    },
    AssetNames: func() []string { // Return a list of asset names for the Asset function
      return []string{"filename.tmpl"}
    },
    Layout: "layout", // Specify a layout template. Layouts can call {{ yield }} to render the current template or {{ partial "css" }} to render a partial from the current template.
    Extensions: []string{".tmpl", ".html"}, // Specify extensions to load for templates.
    Funcs: []template.FuncMap{AppHelpers}, // Specify helper function maps for templates to access.
    Delims: render.Delims{"{[{", "}]}"}, // Sets delimiters to the specified strings.
    Charset: "UTF-8", // Sets encoding for content-types. Default is "UTF-8".
    DisableCharset: true, // Prevents the charset from being appended to the content type header.
    IndentJSON: true, // Output human readable JSON.
    IndentXML: true, // Output human readable XML.
    PrefixJSON: []byte(")]}',\n"), // Prefixes JSON responses with the given bytes.
    PrefixXML: []byte("<?xml version='1.0' encoding='UTF-8'?>"), // Prefixes XML responses with the given bytes.
    HTMLContentType: "application/xhtml+xml", // Output XHTML content type instead of default "text/html".
    IsDevelopment: true, // Render will now recompile the templates on every HTML response.
    UnEscapeHTML: true, // Replace ensure '&<>' are output correctly (JSON only).
    StreamingJSON: true, // Streams the JSON response via json.Encoder.
    RequirePartials: true, // Return an error if a template is missing a partial used in a layout.
    DisableHTTPErrorRendering: true, // Disables automatic rendering of http.StatusInternalServerError when an error occurs.
})
// ...

Default Options

These are the preset options for Render:

r := render.New()

// Is the same as the default configuration options:

r := render.New(render.Options{
    Directory: "templates",
    FileSystem: &LocalFileSystem{},
    Asset: nil,
    AssetNames: nil,
    Layout: "",
    Extensions: []string{".tmpl"},
    Funcs: []template.FuncMap{},
    Delims: render.Delims{"{{", "}}"},
    Charset: "UTF-8",
    DisableCharset: false,
    IndentJSON: false,
    IndentXML: false,
    PrefixJSON: []byte(""),
    PrefixXML: []byte(""),
    BinaryContentType: "application/octet-stream",
    HTMLContentType: "text/html",
    JSONContentType: "application/json",
    JSONPContentType: "application/javascript",
    TextContentType: "text/plain",
    XMLContentType: "application/xhtml+xml",
    IsDevelopment: false,
    UnEscapeHTML: false,
    StreamingJSON: false,
    RequirePartials: false,
    DisableHTTPErrorRendering: false,
})

JSON vs Streaming JSON

By default, Render does not stream JSON to the http.ResponseWriter. It instead marshalls your object into a byte array, and if no errors occurred, writes that byte array to the http.ResponseWriter. If you would like to use the built it in streaming functionality (json.Encoder), you can set the StreamingJSON setting to true. This will stream the output directly to the http.ResponseWriter. Also note that streaming is only implemented in render.JSON and not render.JSONP, and the UnEscapeHTML and Indent options are ignored when streaming.

Loading Templates

By default Render will attempt to load templates with a '.tmpl' extension from the "templates" directory. Templates are found by traversing the templates directory and are named by path and basename. For instance, the following directory structure:

templates/
  |
  |__ admin/
  |      |
  |      |__ index.tmpl
  |      |
  |      |__ edit.tmpl
  |
  |__ home.tmpl

Will provide the following templates:

admin/index
admin/edit
home

You can also load templates from memory by providing the Asset and AssetNames options, e.g. when generating an asset file using go-bindata.

Layouts

Render provides yield and partial functions for layouts to access:

// ...
r := render.New(render.Options{
    Layout: "layout",
})
// ...
<!-- templates/layout.tmpl -->
<html>
  <head>
    <title>My Layout</title>
    <!-- Render the partial template called `css-$current_template` here -->
    {{ partial "css" }}
  </head>
  <body>
    <!-- render the partial template called `header-$current_template` here -->
    {{ partial "header" }}
    <!-- Render the current template here -->
    {{ yield }}
    <!-- render the partial template called `footer-$current_template` here -->
    {{ partial "footer" }}
  </body>
</html>

current can also be called to get the current template being rendered.

<!-- templates/layout.tmpl -->
<html>
  <head>
    <title>My Layout</title>
  </head>
  <body>
    This is the {{ current }} page.
  </body>
</html>

Partials are defined by individual templates as seen below. The partial template's name needs to be defined as "{partial name}-{template name}".

<!-- templates/home.tmpl -->
{{ define "header-home" }}
<h1>Home</h1>
{{ end }}

{{ define "footer-home"}}
<p>The End</p>
{{ end }}

By default, the template is not required to define all partials referenced in the layout. If you want an error to be returned when a template does not define a partial, set Options.RequirePartials = true.

Character Encodings

Render will automatically set the proper Content-Type header based on which function you call. See below for an example of what the default settings would output (note that UTF-8 is the default, and binary data does not output the charset):

// main.go
package main

import (
    "encoding/xml"
    "net/http"

    "github.com/unrolled/render"  // or "gopkg.in/unrolled/render.v1"
)

type ExampleXml struct {
    XMLName xml.Name `xml:"example"`
    One     string   `xml:"one,attr"`
    Two     string   `xml:"two,attr"`
}

func main() {
    r := render.New(render.Options{})
    mux := http.NewServeMux()

    // This will set the Content-Type header to "application/octet-stream".
    // Note that this does not receive a charset value.
    mux.HandleFunc("/data", func(w http.ResponseWriter, req *http.Request) {
        r.Data(w, http.StatusOK, []byte("Some binary data here."))
    })

    // This will set the Content-Type header to "application/json; charset=UTF-8".
    mux.HandleFunc("/json", func(w http.ResponseWriter, req *http.Request) {
        r.JSON(w, http.StatusOK, map[string]string{"hello": "json"})
    })

    // This will set the Content-Type header to "text/xml; charset=UTF-8".
    mux.HandleFunc("/xml", func(w http.ResponseWriter, req *http.Request) {
        r.XML(w, http.StatusOK, ExampleXml{One: "hello", Two: "xml"})
    })

    // This will set the Content-Type header to "text/plain; charset=UTF-8".
    mux.HandleFunc("/text", func(w http.ResponseWriter, req *http.Request) {
        r.Text(w, http.StatusOK, "Plain text here")
    })

    // This will set the Content-Type header to "text/html; charset=UTF-8".
    mux.HandleFunc("/html", func(w http.ResponseWriter, req *http.Request) {
        // Assumes you have a template in ./templates called "example.tmpl"
        // $ mkdir -p templates && echo "<h1>Hello {{.}}.</h1>" > templates/example.tmpl
        r.HTML(w, http.StatusOK, "example", "World")
    })

    http.ListenAndServe("127.0.0.1:3000", mux)
}

In order to change the charset, you can set the Charset within the render.Options to your encoding value:

// main.go
package main

import (
    "encoding/xml"
    "net/http"

    "github.com/unrolled/render"  // or "gopkg.in/unrolled/render.v1"
)

type ExampleXml struct {
    XMLName xml.Name `xml:"example"`
    One     string   `xml:"one,attr"`
    Two     string   `xml:"two,attr"`
}

func main() {
    r := render.New(render.Options{
        Charset: "ISO-8859-1",
    })
    mux := http.NewServeMux()

    // This will set the Content-Type header to "application/octet-stream".
    // Note that this does not receive a charset value.
    mux.HandleFunc("/data", func(w http.ResponseWriter, req *http.Request) {
        r.Data(w, http.StatusOK, []byte("Some binary data here."))
    })

    // This will set the Content-Type header to "application/json; charset=ISO-8859-1".
    mux.HandleFunc("/json", func(w http.ResponseWriter, req *http.Request) {
        r.JSON(w, http.StatusOK, map[string]string{"hello": "json"})
    })

    // This will set the Content-Type header to "text/xml; charset=ISO-8859-1".
    mux.HandleFunc("/xml", func(w http.ResponseWriter, req *http.Request) {
        r.XML(w, http.StatusOK, ExampleXml{One: "hello", Two: "xml"})
    })

    // This will set the Content-Type header to "text/plain; charset=ISO-8859-1".
    mux.HandleFunc("/text", func(w http.ResponseWriter, req *http.Request) {
        r.Text(w, http.StatusOK, "Plain text here")
    })

    // This will set the Content-Type header to "text/html; charset=ISO-8859-1".
    mux.HandleFunc("/html", func(w http.ResponseWriter, req *http.Request) {
        // Assumes you have a template in ./templates called "example.tmpl"
        // $ mkdir -p templates && echo "<h1>Hello {{.}}.</h1>" > templates/example.tmpl
        r.HTML(w, http.StatusOK, "example", "World")
    })

    http.ListenAndServe("127.0.0.1:3000", mux)
}

Error Handling

The rendering functions return any errors from the rendering engine. By default, they will also write the error to the HTTP response and set the status code to 500. You can disable this behavior so that you can handle errors yourself by setting Options.DisableHTTPErrorRendering: true.

r := render.New(render.Options{
  DisableHTTPErrorRendering: true,
})

//...

err := r.HTML(w, http.StatusOK, "example", "World")
if err != nil{
  http.Redirect(w, r, "/my-custom-500", http.StatusFound)
}

Integration Examples

Echo

// main.go
package main

import (
    "io"
    "net/http"

    "github.com/labstack/echo"
    "github.com/unrolled/render"  // or "gopkg.in/unrolled/render.v1"
)

type RenderWrapper struct { // We need to wrap the renderer because we need a different signature for echo.
    rnd *render.Render
}

func (r *RenderWrapper) Render(w io.Writer, name string, data interface{},c echo.Context) error {
    return r.rnd.HTML(w, 0, name, data) // The zero status code is overwritten by echo.
}

func main() {
    r := &RenderWrapper{render.New()}

    e := echo.New()

    e.Renderer = r

    e.GET("/", func(c echo.Context) error {
        return c.Render(http.StatusOK, "TemplateName", "TemplateData")
    })

    e.Logger.Fatal(e.Start(":1323"))
}

Gin

// main.go
package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/unrolled/render"  // or "gopkg.in/unrolled/render.v1"
)

func main() {
    r := render.New(render.Options{
        IndentJSON: true,
    })

    router := gin.Default()

    router.GET("/", func(c *gin.Context) {
        r.JSON(c.Writer, http.StatusOK, map[string]string{"welcome": "This is rendered JSON!"})
    })

    router.Run(":3000")
}

Goji

// main.go
package main

import (
    "net/http"

    "github.com/zenazn/goji"
    "github.com/zenazn/goji/web"
    "github.com/unrolled/render"  // or "gopkg.in/unrolled/render.v1"
)

func main() {
    r := render.New(render.Options{
        IndentJSON: true,
    })

    goji.Get("/", func(c web.C, w http.ResponseWriter, req *http.Request) {
        r.JSON(w, http.StatusOK, map[string]string{"welcome": "This is rendered JSON!"})
    })
    goji.Serve()  // Defaults to ":8000".
}

Negroni

// main.go
package main

import (
    "net/http"

    "github.com/urfave/negroni"
    "github.com/unrolled/render"  // or "gopkg.in/unrolled/render.v1"
)

func main() {
    r := render.New(render.Options{
        IndentJSON: true,
    })
    mux := http.NewServeMux()

    mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        r.JSON(w, http.StatusOK, map[string]string{"welcome": "This is rendered JSON!"})
    })

    n := negroni.Classic()
    n.UseHandler(mux)
    n.Run(":3000")
}

Traffic

// main.go
package main

import (
    "net/http"

    "github.com/pilu/traffic"
    "github.com/unrolled/render"  // or "gopkg.in/unrolled/render.v1"
)

func main() {
    r := render.New(render.Options{
        IndentJSON: true,
    })

    router := traffic.New()
    router.Get("/", func(w traffic.ResponseWriter, req *traffic.Request) {
        r.JSON(w, http.StatusOK, map[string]string{"welcome": "This is rendered JSON!"})
    })

    router.Run()
}
Issues
  • Add a example using render as a global variable to README

    Add a example using render as a global variable to README

    It would be great if you could add a example on using the render package as a global variable i.e. outside of main. Before I discovered this, I had faced a lot of issues in trying to get Render to work when my handlers are not in main.

    opened by Immortalin 14
  • How best to use render in negroni middleware?

    How best to use render in negroni middleware?

    First off, thanks for sharing the code, it's a really helpful module.

    We're using negroni and implementing a couple of our own handlers, primarily for authentication. If the authentication call fails, we want to return an error in JSON as well as the status code. Any advice on the most idiomatic / elegant way to achieve this?

    My first thought was to pass the render.Render to my custom middleware when I instantiate it. That is working, but I'm not sure if it's the best approach.

    opened by chmac 11
  • Render templates from `embed.FS`

    Render templates from `embed.FS`

    Implements #88

    opened by dominik-lekse 10
  • How can I generate JSON from a template

    How can I generate JSON from a template

    I want to generate JSON from a template but I can't see how this is done. Do I need to read i the template file first and then return output? The HTML method seems easy why would the JSON be any different?

    rd.JSON(w, http.StatusOK, "test")

    opened by logicminds 8
  • Rendering the HTML of a string

    Rendering the HTML of a string

    Hey,

    I'm sure there's a way to do it but I cant seem to find it anywhere in the docs.

    is there a way to pump for example: <//a href="link">link

    and not have the renderer escape the html and properly display a link?

    I was using beego and they had a str2html that did this and it seems like a pretty common feature that Im probably just being dense and not seeing.

    Thanks! -Ozzadar

    opened by Ozzadar 8
  • Introduce an interface RWLock to implement lock free in production mode

    Introduce an interface RWLock to implement lock free in production mode

    Improvement after #90 #92

    goos: darwin
    goarch: amd64
    pkg: github.com/unrolled/render
    cpu: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
    (Before)BenchmarkHTML-8          1341072               892.2 ns/op
    (After)   BenchmarkHTML-8          1374212               855.5 ns/op
    PASS
    
    opened by lunny 7
  • Custom Error Handlers on Rendering Errors

    Custom Error Handlers on Rendering Errors

    When an error is encountered as part of the rendering pipeline http.Error is called and displays the simple plain-text error page:

    func (r *Render) Render(w http.ResponseWriter, e Engine, data interface{}) {
        err := e.Render(w, data)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        }
    }
    

    It would be great if there was the ability to pass your own error handler. A potential implementation would be:

    • Add an ErrorHandler http.Handler field to the render.Options struct
    • In prepareOptions call if r.opt.ErrorHandler == nil { r.opt.ErrorHandler = defaultErrorHandler }
    • Add a defaultErrorHandler http.HandlerFunc that wraps http.Error(w, http.StatusText(500), 500)
    • Package users can supply their own handler to render "pretty" error pages or otherwise handle rendering errors. (my personal use case would be to call a static 500.html page with in-lined CSS that's a little friendlier than the plain text one from net/http)

    Happy to provide a PR for this but wanted to run this by you first.

    opened by elithrar 7
  • error calling partial: html/template:

    error calling partial: html/template: "css-home/home" is undefined

    When I use template with sub folder, I found follow error in partial rendering. "error calling partial: html/template: "css-home/home" is undefined"

    My template folder structure is

    /views/layout/layout.tmpl /views/home/home.tmpl

    Sample Code!

    ###Layout
    <html>
      <head>
        <title>My Layout</title>
        <!-- Render the partial template called `css-$current_template` here -->
        {{ partial "css" }}
      </head>
      <body>
        <!-- render the partial template called `header-$current_template` here -->
        {{ partial "header" }}
        This is the {{ current }} page.
        <!-- Render the current template here -->
        {{ yield }}
        <!-- render the partial template called `footer-$current_template` here -->
        {{ partial "footer" }}
      </body>
    </html>
    
    
    ### Template
    
    {{ define "css-home" }}
    <h1>Home</h1>
    {{ end }}
    
    {{ define "header-home" }}
    <h1>Home</h1>
    {{ end }}
    
    <h1>Hello {{.}}.</h1>
    
    {{ define "footer-home"}}
    <p>The E qnd</p>
    {{ end }}
    
    
    ### Controller
    r = render.New(render.Options{
            Directory: "app/views", // Specify what path to load the templates from.
            Layout: "layout/layout", // Specify a layout template. Layouts can call {{ yield }} to render the       current template or {{ partial "css" }} to render a partial from the current template.
            Extensions: []string{".tmpl", ".html"}, // Specify extensions to load for templates.
            Charset: "UTF-8", // Sets encoding for json and html content-types. Default is "UTF-8".
            UnEscapeHTML: true, // Replace ensure '&<>' are output correctly (JSON only).
            RequirePartials: true, // Return an error if a template is missing a partial used in a layout.
        })
    
    r.HTML(res, http.StatusOK, "home/home", "World")
    
    
    opened by kyawmyintthein 7
  • adding a

    adding a "block" func to the template's FuncMap

    allows multiple yield statements in a layout.

    a sample layout.tmpl:

    <html>
    <head>
    {{yield "title"}}
    {{yield "css"}}
    </head>
    <body>
    {{yield "body"}}
    </body>
    </html>
    

    a sample page.html:

    {{define "title-page"}}<title>hello world!</title>{{end}}
    {{define "css-page"}}<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"/>{{end}}
    {{define "js-page}}<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>{{end}}
    

    added tests but many others are failing also

    opened by arschles 6
  • Return errors from rendering methods

    Return errors from rendering methods

    Errors are now returned from rendering methods. Existing applications using this package still compile and behave the same. I added a new option, DisableHTTPErrorRendering, which, when set to true, will not render the error and http.StatusInternalServerError. This option is false by default.

    resolves #26

    opened by blachniet 6
  • FR: Support templates for JSON renderer

    FR: Support templates for JSON renderer

    Currently, only HTML supports template rendering. We want to render JSON from a template, but using HTML() causes issues because of HTML escaping.

    opened by noerw 2
Releases(v1.4.0)
Owner
Cory Jacobsen
Cory Jacobsen
Simple, lightweight and faster response (JSON, JSONP, XML, YAML, HTML, File) rendering package for Go

Package renderer Simple, lightweight and faster response (JSON, JSONP, XML, YAML, HTML, File) rendering package for Go Installation Install the packag

Saddam H 224 Jul 16, 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

Gorilla Web Toolkit 676 Jul 19, 2021
Go package that handles HTML, JSON, XML and etc. responses

gores http response utility library for Go this package is very small and lightweight, useful for RESTful APIs. installation go get github.com/alioygu

Ali OYGUR 96 Jul 3, 2021
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

null 7k Jul 23, 2021
A collection of useful middleware for Go HTTP services & web applications 🛃

gorilla/handlers Package handlers is a collection of handlers (aka "HTTP middleware") for use with Go's net/http package (or any framework supporting

Gorilla Web Toolkit 1.2k Jul 25, 2021
gin panic 拦截中间件, 基于插件的实现方式, 同时多种自定义回调通知(企业微信,钉钉,邮件, ES, MongoDB, MySQL 等等方式)

gin panic 拦截中间件 编程中有效的实践 go 程序 panic 是什么 ❓ 程序 panic 主要程序异常,程序不能继续向下推进时向调用者抛出的一个异常的机制,如果用户没有执行错误拦截,那么程序会一直往上抛出错误信息, 直到用户拦截,亦或是没有拦截会打印输出错误信息, 然后 exit(2)

我的我的 3 Jun 16, 2021
A Go middleware that stores various information about your web application (response time, status code count, etc.)

Go stats handler stats is a net/http handler in golang reporting various metrics about your web application. This middleware has been developed and re

Florent Messa 579 Jul 1, 2021
A tiny http middleware for Golang with added handlers for common needs.

rye A simple library to support http services. Currently, rye provides a middleware handler which can be used to chain http handlers together while pr

InVision 97 Jun 6, 2021
Mahi is an all-in-one HTTP service for file uploading, processing, serving, and storage.

Mahi is an all-in-one HTTP service for file uploading, processing, serving, and storage. Mahi supports chunked, resumable, and concurrent uploads. Mahi uses Libvips behind the scenes making it extremely fast and memory efficient.

Rodrigo Lessa 30 Jul 7, 2021
A HTTP mole service

httpmole provides a HTTP mock server that will act as a mole among your services, telling you everything http clients send to it and responding them whatever you want it to respond. Just like an actual mole.

José Carlos Chávez 131 Jun 13, 2021
Add interceptors to GO http.Client

mediary Add interceptors to http.Client and you will be able to Dump request and/or response to a Log Alter your requests before they are sent or resp

Here Mobility SDK 73 Jul 15, 2021
Minimalist net/http middleware for golang

interpose Interpose is a minimalist net/http middleware framework for golang. It uses http.Handler as its core unit of functionality, minimizing compl

James Pirruccello 290 Jun 21, 2021
Sentinel Go version (Reliability & Resilience)

Sentinel: The Sentinel of Your Microservices Introduction As distributed systems become increasingly popular, the reliability between services is beco

Alibaba 1.6k Jul 20, 2021
echo-http - Echo http service

echo-http - Echo http service Responds with json-formatted echo of the incoming request and with a predefined message. Can be install directly (go get

Umputun 7 Jun 6, 2021