Help us shape the future of Go! Take the 2026 Go Developer Survey

negotiator

package module
v0.0.0-...-b9489ef Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 30, 2014 License: Apache-2.0 Imports: 4 Imported by: 2

README

Negotiator

This is a simple golang content negotiation library that was built as a Martini middleware/handler but can be used standalone as well. The ContentNegotiator object will read the Accepts header from the net/http request and encode the given data appropriately or fallback to a default encoding if the Accepts header is not recognized.

Supported Content-Types

  • application/json
  • application/xml

NOTE: The above encoders are included in this repo and will automatically be setup if you use the NewJsonXmlContentNegotiator function but support for any mime type can be added dynamically.

Usage

To use the built in JSON and XML encoders use the NewJsonXmlContentNegotiator function to create the ContentNegotiator.

If you dont want JSON and XML support use the NewContentNegotiator function to create a base ContentNegotiator. This negotiator will need at least one Encoder to function. You can add encoders to this using the AddEncoder function as seen in the examples below.

General

For general usage, i.e. non-martini use, simply import the package, create a ContentNegotiator object, and call Negotiate:

package main

import (
	"github.com/divideandconquer/negotiator"
	"net/http"
	"log"
)

func main() {
	...
	
	output := ... //some struct of data

	// This creates a content negotiator can handle JSON and XML, defaults to json, and doesn't pretty print
	fallbackEncoder := negotiator.JsonEncoder{false}
	cn := negotiator.NewJsonXmlContentNegotiator(fallbackEncoder, responseWriter, false)
	// To add your own mime types and encoders use the AddEncoder function:
	//cn.AddEncoder("text/html", htmlEncoder)
	log.Println(cn.Negotiate(request, output))
}

If you don't want to support XML you can use NewContentNegotiator instead:

// Don't want to support XML? Use the following lines:
cn := negotiator.NewContentNegotiator(defaultEncoder, responseWriter)
cn.AddEncoder("application/json", negotiator.JsonEncoder{true})
Martini

For use with the Martini framework add the content negotiator to the list of middlewares to use:

//Martini initialization
m = martini.New()

// add middleware
m.Use(martini.Recovery())
m.Use(martini.Logger())

// setup content negotiation
m.Use(func(c martini.Context, w http.ResponseWriter) {
	// This creates a content negotiator can handle JSON and XML, defaults to json, and doesn't pretty print
	fallbackEncoder := negotiator.JsonEncoder{false}
	cn := negotiator.NewJsonXmlContentNegotiator(fallbackEncoder, w, false)

	// To add your own mime types and encoders use the AddEncoder function:
	//cn.AddEncoder("text/html", htmlEncoder)
	
	c.MapTo(cn, (*negotiator.Negotiator)(nil))
})

// setup router
router := martini.NewRouter()
router.Get("/", func(r *http.Request, neg negotiator.Negotiator) (int, []byte) {
	data := ... //setup whatever data you want to return
	return http.StatusOK, negotiator.Must(neg.Negotiate(r, data)))
}
Creating Encoders

If you want to add support for additional mime types simple create a struct that implements the Encoder interface. Use the skeleton below as a starting point.

package main

type FooEncoder struct {}

func (foo FooEncoder) Encode(data interface{}) ([]byte, error) {
	// encode the data and return a byte array
}

// ContentType returns the string that will be used
// for the Content-Type header on the response
func (js JsonEncoder) ContentType() string {
	//return the appropriate Content-Type header string
	//return "application/foo; charset=utf-8"
}

Once you have an encoder add it to the content negotiator with the AddEncoder function:

cn := negotiator.NewContentNegotiator(defaultEncoder, responseWriter)
// Pass in the Accepts header string to respond to and the encoder itself
cn.AddEncoder("application/foo", FooEncoder{})

Now if the client sends an Accepts header of application/foo the FooEncoder will be used to encode the response.

License

This module is licensed using the Apache-2.0 License:

Copyright (c) 2014, Kyle Boorky

Documentation

Index

Constants

View Source
const MimeJSON = "application/json"
View Source
const MimeXML = "application/xml"

Variables

This section is empty.

Functions

func Must

func Must(data []byte, err error) []byte

Check for an error and panic

Types

type ContentNegotiator

type ContentNegotiator struct {
	DefaultEncoder Encoder
	ResponseWriter http.ResponseWriter
	// contains filtered or unexported fields
}

ContentNegotiator is a Neotiator that supports a fallback/default encoder as well as dynamically adding encoders

func NewContentNegotiator

func NewContentNegotiator(defaultEncoder Encoder, responseWriter http.ResponseWriter) *ContentNegotiator

NewContentNegotiator creates a basic ContentNegotiator with out any attached encoders

func NewJsonXmlContentNegotiator

func NewJsonXmlContentNegotiator(defaultEncoder Encoder, responseWriter http.ResponseWriter, prettyPrint bool) *ContentNegotiator

NewJsonXmlContentNegotiator creates a basic ContentNegotiator and attaches a JSON and an XML encoder to it.

func (*ContentNegotiator) AddEncoder

func (cn *ContentNegotiator) AddEncoder(mimeType string, enc Encoder)

AddEncoder registers a mimetype and its encoder to be used if a client requests that mimetype

func (*ContentNegotiator) Negotiate

func (cn *ContentNegotiator) Negotiate(req *http.Request, data interface{}) ([]byte, error)

Negotiate inspects the request for the accept header and encodes the response appropriately.

type Encoder

type Encoder interface {
	Encode(data interface{}) ([]byte, error)
	ContentType() string
}

Encoder is an interface for a struct that can encode data into []byte

type JsonEncoder

type JsonEncoder struct {
	PrettyPrint bool
}

func (JsonEncoder) ContentType

func (js JsonEncoder) ContentType() string

func (JsonEncoder) Encode

func (je JsonEncoder) Encode(data interface{}) ([]byte, error)

type Negotiator

type Negotiator interface {
	Negotiate(req *http.Request, data interface{}) ([]byte, error)
}

A Negotiator can Negotiate to determine what content type to convert a struct into for client consumption

type XmlEncoder

type XmlEncoder struct {
	PrettyPrint bool
}

func (XmlEncoder) ContentType

func (xe XmlEncoder) ContentType() string

func (XmlEncoder) Encode

func (xe XmlEncoder) Encode(data interface{}) ([]byte, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL