jsh

package module
v0.0.0-...-1f7a8b1 Latest Latest
Warning

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

Go to latest
Published: Dec 4, 2015 License: MIT Imports: 10 Imported by: 0

README

Go JSON API Specification Handler

GoDoc Build Status TestCoverage

An HTTP Client and Server request/response handler for dealing with JSON Specification APIs. Great for Ember.js!

Packages

jsh - JSON Specification Handler

import github.com/derekdowling/go-json-spec-handler

Perfect middleware, or input/output handling for a new, or existing API server.

jsc - JSON Specification Client

import github.com/derekdowling/go-json-spec-handler/client

HTTP Client for interacting with JSON APIs.

Features

Implemented:

- Handles both single object and array based JSON requests and responses
- Input validation with HTTP 422 Status support via [go-validator](https://github.com/go-validator/validator)
- Client request validation with HTTP 406 Status responses
- Links, Relationship, Meta fields
- Prepackaged error responses, easy to use Internal Service Error builder
- Smart responses with correct HTTP Statuses based on Request Method and HTTP Headers
- HTTP Client for GET, POST, DELETE, PATCH

TODO:

- Reserved character checking

Not Implenting:

* These features aren't handled because they are beyond the scope of what
  this library is meant to be. In the future, I might build a framework
  utilizing this library to handle these complex features which require
  Router and ORM compatibility.

- Relationship management
- Sorting
- Pagination
- Filtering

Examples

There are lots of great examples in the tests themselves that show exactly how it works, also check out the godocs as linked above.

Documentation

Overview

Package jsh (JSON API Specification Handler) makes it easy to parse JSON API requests and send responses that match the JSON API Specification: http://jsonapi.org/ from your server.

For a request client, see: jsc: https://godoc.org/github.com/derekdowling/go-json-spec-handler/client

Index

Constants

View Source
const (
	// ContentType is the data encoding of choice for HTTP Request and Response Headers
	ContentType = "application/vnd.api+json"
)
View Source
const JSONAPIVersion = "1.1"

JSONAPIVersion is version of JSON API Spec that is currently compatible: http://jsonapi.org/format/1.1/

Variables

View Source
var DefaultErrorDetail = "Request failed, something went wrong."

DefaultError can be customized in order to provide a more customized error Detail message when an Internal Server Error occurs. Optionally, you can modify a returned jsh.Error before sending it as a response as well.

View Source
var DefaultErrorTitle = "Internal Server Error"

DefaultTitle can be customized to provide a more customized ISE Title

Functions

func CreateReadCloser

func CreateReadCloser(data []byte) io.ReadCloser

CreateReadCloser is a helper function for dealing with creating HTTP requests

func NewObject

func NewObject(id string, objType string, attributes interface{}) (*Object, SendableError)

NewObject prepares a new JSON Object for an API response. Whatever is provided as attributes will be marshalled to JSON.

func ParseList

func ParseList(r *http.Request) (List, SendableError)

ParseList validates the HTTP request and returns a resulting list of objects parsed from the request Body. Use just like ParseObject.

func ParseObject

func ParseObject(r *http.Request) (*Object, SendableError)

ParseObject validates the HTTP request and returns a JSON object for a given io.ReadCloser containing a raw JSON payload. Here's an example of how to use it as part of your full flow.

func Handler(w http.ResponseWriter, r *http.Request) {
	obj, error := jsh.ParseObject(r)
	if error != nil {
		// log your error
		jsh.Send(w, r, error)
		return
	}

	yourType := &YourType{}

	err := object.Unmarshal("yourtype", &yourType)
	if err != nil {
		jsh.Send(w, r, err)
		return
	}

	yourType.ID = obj.ID
	// do business logic

	response, err := jsh.NewObject(yourType.ID, "yourtype", &yourType)
	if err != nil {
		// log error
		err := jsh.Send(w, r, err)
		return
	}

	err := jsh.Send(w, r, response)
}

func Send

func Send(w http.ResponseWriter, r *http.Request, payload Sendable) error

Send will return a JSON payload to the requestor. If the payload response validation fails, it will send an appropriate error to the requestor and will return the error

func SendResponse

func SendResponse(w http.ResponseWriter, r *http.Request, response *Response) error

SendResponse handles sending a fully packaged JSON Response allows API consumers to more manually build their Responses in case they want to send Meta, Links, etc The function will always, send but will return the last error it encountered to help with debugging

Types

type Error

type Error struct {
	Title  string `json:"title"`
	Detail string `json:"detail"`
	Status int    `json:"status"`
	Source struct {
		Pointer string `json:"pointer"`
	} `json:"source"`
	ISE string `json:"-"`
}

Error represents a JSON Specification Error. Error.Source.Pointer is used in 422 status responses to indicate validation errors on a JSON Object attribute.

ISE (internal server error) captures the server error internally to help with logging/troubleshooting, but is never returned in a response.

Once a jsh.Error is returned, and you have logged/handled it accordingly, you can simply return it using jsh.Send():

error := &jsh.Error{
	Title: "Authentication Failure",
	Detail: "Category 4 Username Failure",
	Status: 401
}

jsh.Send(w, r, error)

func ISE

func ISE(err string) *Error

ISE is a convenience function for creating a ready-to-go Internal Service Error response. As previously mentioned, the Error.ISE field is for logging only, and won't be returned to the end user.

func InputError

func InputError(attribute string, detail string) *Error

InputError creates a properly formatted Status 422 error with an appropriate user facing message, and a Status Pointer to the first attribute that

func SpecificationError

func SpecificationError(detail string) *Error

SpecificationError is used whenever the Client violates the JSON API Spec

func (*Error) Error

func (e *Error) Error() string

func (*Error) Prepare

func (e *Error) Prepare(req *http.Request, response bool) (*Response, SendableError)

Prepare returns a response containing a prepared error list since the JSON API specification requires that errors are returned as a list

type ErrorList

type ErrorList struct {
	Errors []*Error
}

ErrorList is just a wrapped error array that implements Sendable

func (*ErrorList) Add

func (e *ErrorList) Add(newError *Error) *Error

Add first validates the error, and then appends it to the ErrorList

func (*ErrorList) Error

func (e *ErrorList) Error() string

Error allows ErrorList to conform to the default Go error interface

func (*ErrorList) Prepare

func (e *ErrorList) Prepare(req *http.Request, response bool) (*Response, SendableError)

Prepare first validates the errors, and then returns an appropriate response

type Link struct {
	HREF string                 `json:"href,omitempty"`
	Meta map[string]interface{} `json:"meta,omitempty"`
}

Link is a JSON format type

type Links struct {
	Self    *Link `json:"self,omitempty"`
	Related *Link `json:"related,omitempty"`
}

Links is a top-level document field

type List

type List []*Object

List is just a wrapper around an object array that implements Sendable

func (List) Prepare

func (list List) Prepare(r *http.Request, response bool) (*Response, SendableError)

Prepare returns a success status response

type Object

type Object struct {
	Type          string             `json:"type" valid:"alpha,required"`
	ID            string             `json:"id"`
	Attributes    json.RawMessage    `json:"attributes,omitempty"`
	Links         map[string]*Link   `json:"links,omitempty"`
	Relationships map[string]*Object `json:"relationships,omitempty"`
}

Object represents the default JSON spec for objects

func (*Object) Prepare

func (o *Object) Prepare(r *http.Request, response bool) (*Response, SendableError)

Prepare creates a new JSON single object response with an appropriate HTTP status to match the request method type.

func (*Object) Unmarshal

func (o *Object) Unmarshal(objType string, target interface{}) (err SendableError)

Unmarshal puts an Object's Attributes into a more useful target type defined by the user. A correct object type specified must also be provided otherwise an error is returned to prevent hard to track down situations.

Optionally, used https://github.com/go-validator/validator for request input validation. Simply define your struct with valid input tags:

struct {
	Username string `json:"username" valid:"required,alphanum"`
}

As the final action, the Unmarshal function will run govalidator on the unmarshal result. If the validator fails, a Sendable error response of HTTP Status 422 will be returned containing each validation error with a populated Error.Source.Pointer specifying each struct attribute that failed. In this case, all you need to do is:

errors := obj.Unmarshal("mytype", &myType)
if errors != nil {
	// log errors via error.ISE
	jsh.Send(w, r, errors)
}

type Parser

type Parser struct {
	Method  string
	Headers http.Header
	Payload io.ReadCloser
}

Parser is an abstraction layer to support parsing JSON payload from many types of sources in order to allow other packages to use this parser

func (*Parser) GetList

func (p *Parser) GetList() (List, SendableError)

GetList returns a JSON data list from the parser

func (*Parser) GetObject

func (p *Parser) GetObject() (*Object, SendableError)

GetObject returns a single JSON data object from the parser

type Response

type Response struct {
	HTTPStatus int         `json:"-"`
	Validated  bool        `json:"-"`
	Data       interface{} `json:"data,omitempty"`
	Errors     interface{} `json:"errors,omitempty"`
	Meta       interface{} `json:"meta,omitempty"`
	Links      *Link       `json:"links,omitempty"`
	Included   *List       `json:"included,omitempty"`
	JSONAPI    struct {
		Version string `json:"version"`
	} `json:"jsonapi"`
}

Response represents the top level json format of incoming requests and outgoing responses

func (*Response) Validate

func (r *Response) Validate() SendableError

Validate checks JSON Spec for the top level JSON document

type Sendable

type Sendable interface {
	Prepare(r *http.Request, response bool) (*Response, SendableError)
}

Sendable implements functions that allows different response types to produce a sendable JSON Response format

type SendableError

type SendableError interface {
	Sendable
	Error() string
}

SendableError conforms to a standard error format for logging, but can also be sent as a JSON response

Directories

Path Synopsis
Package jsc (JSON Specification Client) is an http client that makes sending HTTP requests that match the JSON Specification: http://jsonapi.org/ simple.
Package jsc (JSON Specification Client) is an http client that makes sending HTTP requests that match the JSON Specification: http://jsonapi.org/ simple.

Jump to

Keyboard shortcuts

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