Simple, lightweight and faster response (JSON, JSONP, XML, YAML, HTML, File) rendering package for Go

Overview

Package renderer

Build Status Project status Go Report Card Coverage Status GoDoc License

Simple, lightweight and faster response (JSON, JSONP, XML, YAML, HTML, File) rendering package for Go

Installation

Install the package using

$ go get github.com/thedevsaddam/renderer/...

Usage

To use the package import it in your *.go code

import "github.com/thedevsaddam/renderer"

Example

package main

import (
	"io"
	"log"
	"net/http"
	"os"

	"github.com/thedevsaddam/renderer"
)

func main() {
	rnd := renderer.New()

	mux := http.NewServeMux()

	usr := struct {
		Name string
		Age  int
	}{"John Doe", 30}

	// serving String as text/plain
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		rnd.String(w, http.StatusOK, "Welcome to renderer")
	})

	// serving success but no content
	mux.HandleFunc("/no-content", func(w http.ResponseWriter, r *http.Request) {
		rnd.NoContent(w)
	})

	// serving string as html
	mux.HandleFunc("/html-string", func(w http.ResponseWriter, r *http.Request) {
		rnd.HTMLString(w, http.StatusOK, "<h1>Hello Renderer!</h1>")
	})

	// serving JSON
	mux.HandleFunc("/json", func(w http.ResponseWriter, r *http.Request) {
		rnd.JSON(w, http.StatusOK, usr)
	})

	// serving JSONP
	mux.HandleFunc("/jsonp", func(w http.ResponseWriter, r *http.Request) {
		rnd.JSONP(w, http.StatusOK, "callback", usr)
	})

	// serving XML
	mux.HandleFunc("/xml", func(w http.ResponseWriter, r *http.Request) {
		rnd.XML(w, http.StatusOK, usr)
	})

	// serving YAML
	mux.HandleFunc("/yaml", func(w http.ResponseWriter, r *http.Request) {
		rnd.YAML(w, http.StatusOK, usr)
	})

	// serving File as arbitary binary data
	mux.HandleFunc("/binary", func(w http.ResponseWriter, r *http.Request) {
		var reader io.Reader
		reader, _ = os.Open("../README.md")
		rnd.Binary(w, http.StatusOK, reader, "readme.md", true)
	})

	// serving File as inline
	mux.HandleFunc("/file-inline", func(w http.ResponseWriter, r *http.Request) {
		rnd.FileView(w, http.StatusOK, "../README.md", "readme.md")
	})

	// serving File as attachment
	mux.HandleFunc("/file-download", func(w http.ResponseWriter, r *http.Request) {
		rnd.FileDownload(w, http.StatusOK, "../README.md", "readme.md")
	})

	// serving File from reader as inline
	mux.HandleFunc("/file-reader", func(w http.ResponseWriter, r *http.Request) {
		var reader io.Reader
		reader, _ = os.Open("../README.md")
		rnd.File(w, http.StatusOK, reader, "readme.md", true)
	})

	// serving custom response using render and chaining methods
	mux.HandleFunc("/render", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set(renderer.ContentType, renderer.ContentText)
		rnd.Render(w, http.StatusOK, []byte("Send the message as text response"))
	})

	port := ":9000"
	log.Println("Listening on port", port)
	http.ListenAndServe(port, mux)
}

How to render html template?

Well, you can parse html template using HTML, View, Template any of these method. These are based on html/template package.

When using Template method you can simply pass the base layouts, templates path as a slice of string.

Template example

You can parse template on the fly using Template method. You can set delimiter, inject FuncMap easily.

template/layout.tmpl

<html>
  <head>
    <title>{{ template "title" . }}</title>
  </head>
  <body>
    {{ template "content" . }}
  </body>
  {{ block "sidebar" .}}{{end}}
</html>

template/index.tmpl

{{ define "title" }}Home{{ end }}

{{ define "content" }}
  <h1>Hello, {{ .Name | toUpper }}</h1>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
{{ end }}

template/partial.tmpl

{{define "sidebar"}}
  simple sidebar code
{{end}}

template.go

package main

import (
	"html/template"
	"log"
	"net/http"
	"strings"

	"github.com/thedevsaddam/renderer"
)

var rnd *renderer.Render

func init() {
	rnd = renderer.New()
}

func toUpper(s string) string {
	return strings.ToUpper(s)
}

func handler(w http.ResponseWriter, r *http.Request) {
	usr := struct {
		Name string
		Age  int
	}{"john doe", 30}

	tpls := []string{"template/layout.tmpl", "template/index.tmpl", "template/partial.tmpl"}
	rnd.FuncMap(template.FuncMap{
		"toUpper": toUpper,
	})
	err := rnd.Template(w, http.StatusOK, tpls, usr)
	if err != nil {
		log.Fatal(err) //respond with error page or message
	}
}

func main() {
	http.HandleFunc("/", handler)
	log.Println("Listening port: 9000")
	http.ListenAndServe(":9000", nil)
}

HTML example

When using HTML you can parse a template directory using pattern and call the template by their name. See the example code below:

html/index.html

{{define "indexPage"}}
    <html>
    {{template "header"}}
    <body>
        <h3>Index</h3>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
    </body>
    {{template "footer"}}
    </html>
{{end}}

html/header.html

{{define "header"}}
     <head>
         <title>Header</title>
         <h1>Header section</h1>
     </head>
{{end}}

html/footer.html

{{define "footer"}}
     <footer>Copyright &copy; 2020</footer>
{{end}}

html.go

package main

import (
	"log"
	"net/http"

	"github.com/thedevsaddam/renderer"
)

var rnd *renderer.Render

func init() {
	rnd = renderer.New(
		renderer.Options{
			ParseGlobPattern: "html/*.html",
		},
	)
}

func handler(w http.ResponseWriter, r *http.Request) {
	err := rnd.HTML(w, http.StatusOK, "indexPage", nil)
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	http.HandleFunc("/", handler)
	log.Println("Listening port: 9000")
	http.ListenAndServe(":9000", nil)
}

View example

When using View for parsing template you can pass multiple layout and templates. Here template name will be the file name. See the example to get the idea.

view/base.lout

<html>
  <head>
     <title>{{block "title" .}} {{end}}</title>
  </head>
  <body>
    {{ template "content" . }}
  </body>
</html>

view/home.tpl

{{define "title"}}Home{{end}}
{{define "content"}}
<h3>Home page</h3>
    <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/about">About Me</a></li>
    </ul>
    <p>
    Lorem ipsum dolor sit amet</p>
{{end}}

view/about.tpl

{{define "title"}}About Me{{end}}
{{define "content"}}
<h2>This is About me page.</h2>
<ul>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit,
</ul>
<p><a href="/">Home</a></p>
{{end}}

view.go

package main

import (
	"log"
	"net/http"

	"github.com/thedevsaddam/renderer"
)

var rnd *renderer.Render

func init() {
	rnd = renderer.New(renderer.Options{
		TemplateDir: "view",
	})
}

func home(w http.ResponseWriter, r *http.Request) {
	err := rnd.View(w, http.StatusOK, "home", nil)
	if err != nil {
		log.Fatal(err)
	}
}

func about(w http.ResponseWriter, r *http.Request) {
	err := rnd.View(w, http.StatusOK, "about", nil)
	if err != nil {
		log.Fatal(err)
	}
}

func main() {
	http.HandleFunc("/", home)
	http.HandleFunc("/about", about)
	log.Println("Listening port: 9000\n / is root \n /about is about page")
	http.ListenAndServe(":9000", nil)
}

Note: This is a wrapper on top of go built-in packages to provide syntactic sugar.

Contribution

Your suggestions will be more than appreciated. Read the contribution guide here

See all contributors

Read API doc to know about Available options and Methods

License

The renderer is an open-source software licensed under the MIT License.

Comments
  • I want to create html text and save it to a variable and send it to template...but i can't

    I want to create html text and save it to a variable and send it to template...but i can't

    I want to create html text

    for example:

    data1 := <h1>hello</h1>

    and save it to a variable->data1 and send it to template...but i can't

    what can I do? noescape is removed from html/template

    what should we do???

    opened by sadegh-shahbazi 2
  • How do i pass values to an extended template?

    How do i pass values to an extended template?

    while following your example, I have few issues i described in comments. can you please advise?

    package main
    
    import (
    	"log"
    	"net/http"
    
    	"github.com/thedevsaddam/renderer"
    )
    
    var rnd *renderer.Render
    
    func init() {
    	rnd = renderer.New(
    		renderer.Options{
    			ParseGlobPattern: "html/*.html",
    		},
    	)
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
    
           # **i was able to declare a struct here.** 
    
            usr := struct {
    		Name string
    		Age  int
    	}{"john doe", 30}
            
            ## passed in `usr`  here
    	err := rnd.HTML(w, http.StatusOK, "indexPage", usr)
    	if err != nil {
    		log.Fatal(err)
    	}
    }
    
    func main() {
    	http.HandleFunc("/", handler)
    	log.Println("Listening port: 9000")
    	http.ListenAndServe(":9000", nil)
    }
    
    # html/index.html
    
    {{define "indexPage"}}
        <html>
        {{template "header"}}
        <body>
            <h3>Index</h3>
    **## this works**
    <h1>Hello, {{ .Name }}</h1>
            <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
        </body>
        {{template "footer"}}
        </html>
    {{end}}
    
    html/header.html
    
    {{define "header"}}
         <head>
             <title>Header</title>
    ## this, no; not even `usr.Name`
    <h1>Hello, {{ .Name }}</h1>
             <h1>Header section</h1>
         </head>
    {{end}}
    

    can you please advise on how do i pass values on extended template?

    opened by afidegnum 1
  • Replaced deprecated res.HeaderMap with res.Header()

    Replaced deprecated res.HeaderMap with res.Header()

    As described in #5, accessing response headers with ResponseRecorder.HeaderMap is currently deprecated. This PR replaces ResponseRecorder.HeaderMap with ResponseRecorder.Header() across the tests. Closes #5

    opened by eloyekunle 1
  • FuncMap in Templates gives undefined error

    FuncMap in Templates gives undefined error

    Right now when I try to use a function in Templates, the FuncMap doesn't load before it tries to parse the template.

    So as a result, I get an undefined error for the function I'm trying to use.

    It looks like there was some work to do this in: https://github.com/thedevsaddam/renderer/blob/master/renderer.go#L550-L555

    Is this something that'll be finished :)?

    Also thanks for your work on this!

    opened by coreyhickson 1
  • Tests still using deprecated 'HeaderMap'

    Tests still using deprecated 'HeaderMap'

    Currently in renderer_test.go, verifying response headers still make use of the deprecated ResponseRecorder.HeaderMap, while we can get the headers from ResponseRecorder.Header(), which is recommended.

    opened by eloyekunle 0
Releases(v1.2.0)
Owner
Saddam H
Sr. Software Engineer @ Pathao Inc | Open Source Enthusiast | Love to write elegant code | Golang | Distributed Systems
Saddam H
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 101 Oct 31, 2022
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 586 Dec 10, 2022
Lightweight Middleware for net/http

MuxChain MuxChain is a small package designed to complement net/http for specifying chains of handlers. With it, you can succinctly compose layers of

Stephen Searles 209 Dec 10, 2022
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 34 Dec 29, 2022
A Concurrent HTTP Static file server using golang .

A Concurrent HTTP static server using Golang. Serve Static files like HTML,CSS,Js,Images,Videos ,ect. using HTTP. It is Concurrent and Highly Scalable.Try now!

sambath kumar B 4 Dec 19, 2021
Efficient token-bucket-based rate limiter package.

ratelimit -- import "github.com/juju/ratelimit" The ratelimit package provides an efficient token bucket implementation. See http://en.wikipedia.org/w

Juju 2.5k Dec 29, 2022
Go package for rate limiter collection

rlc A rate limiter collection for Go. Pick up one of the rate limiters to throttle requests and control quota. RLC Slider TokenBucket RLC RLC is a rat

Alex Xu 15 Jul 6, 2021
Simple middleware to rate-limit HTTP requests.

Tollbooth This is a generic middleware to rate-limit HTTP requests. NOTE 1: This library is considered finished. NOTE 2: Major version changes are bac

Didip Kerabat 2.3k Dec 28, 2022
Simple, thread-safe Go rate-limiter

RateLimit Simple, thread-safe Go rate-limiter. Inspired by Antti Huima's algorithm on http://stackoverflow.com/a/668327 Example package main import (

Black Square Media 71 Oct 16, 2022
A dead simple, stupid, http service.

A dead simple, stupid, http service implemented in a complicated way just for the sake of following Go design patterns and scalability. Useful for learning and testing basic kubernetes networking. Made on an insomniac night.

Rudraksh Pareek 2 Sep 2, 2022
An efficient and feature complete Hystrix like Go implementation of the circuit breaker pattern.

Circuit Circuit is an efficient and feature complete Hystrix like Go implementation of the circuit breaker pattern. Learn more about the problems Hyst

Jack Lindamood 681 Dec 28, 2022
A http service to verify request and bounce them according to decisions made by CrowdSec.

traefik-crowdsec-bouncer A http service to verify request and bounce them according to decisions made by CrowdSec. Description This repository aim to

Fabien Bonalair 168 Dec 21, 2022
Prometheus Common Data Exporter can parse JSON, XML, yaml or other format data from various sources (such as HTTP response message, local file, TCP response message and UDP response message) into Prometheus metric data.

Prometheus Common Data Exporter Prometheus Common Data Exporter 用于将多种来源(如http响应报文、本地文件、TCP响应报文、UDP响应报文)的Json、xml、yaml或其它格式的数据,解析为Prometheus metric数据。

null 7 May 18, 2022
Go package for easily rendering JSON, XML, binary data, and HTML templates responses.

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

Cory Jacobsen 1.7k Jan 8, 2023
converts text-formats from one to another, it is very useful if you want to re-format a json file to yaml, toml to yaml, csv to yaml, ... etc

re-txt reformates a text file from a structure to another, i.e: convert from json to yaml, toml to json, ... etc Supported Source Formats json yaml hc

Mohammed Al Ashaal 65 Sep 23, 2022
Simple system for writing HTML/XML as Go code. Better-performing replacement for html/template and text/template

Simple system for writing HTML as Go code. Use normal Go conditionals, loops and functions. Benefit from typing and code analysis. Better performance than templating. Tiny and dependency-free.

Nelo Mitranim 5 Dec 5, 2022
A simple Go package to Query over JSON/YAML/XML/CSV Data

A simple Go package to Query over JSON Data. It provides simple, elegant and fast ODM like API to access, query JSON document Installation Install the

Saddam H 2k Jan 8, 2023
A simple Go package to Query over JSON/YAML/XML/CSV Data

A simple Go package to Query over JSON Data. It provides simple, elegant and fast ODM like API to access, query JSON document Installation Install the

Saddam H 2k Dec 27, 2022
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 101 Oct 31, 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

LAZPbanahaker 2 Feb 9, 2022