httpapi

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

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

Go to latest
Published: Aug 29, 2018 License: MIT Imports: 18 Imported by: 0

README

httpapi GoDoc License Build Status Coverage Status GoReportCard

Package httpapi provides support for implementing HTTP servers that expose a JSON API.

Example of a handler that extracts the input from the body of the HTTP request.

func postHandler(w http.ResponseWriter, r *http.Request) {
    // unmarshal input from request
    var input DoSomethingInput
    if err := httpapi.ReadRequest(w, r, &input); err != nil {
        httpapi.WriteError(w, r, err)
        return
    }

    output, err := doSomethingWith(r.Context(), &input)
    if err != nil {
        httpapi.WriteError(w, r, err)
        return
    }

    httpapi.WriteResponse(w, r, output)
}

Example of a handler that extracts the input from the query strings of the HTTP request.

func getHandler(w http.ResponseWriter, r *http.Request) {
    query := httpapi.Query(r)
    input := DoAnotherThingInput {
        Since: query.GetTime("since"),
        Limit: query.GetInt("limit"),
        Offset: query.GetInt("offset"),
    }

    // validate once after all query string parameters have been read
    if err := query.Err(); err != nil {
        httpapi.WriteResponse(w, r, err)
        return
    }

    output, err := doAnotherThingWith(r.Context(), &input)
    if err != nil {
        httpapi.WriteError(w, r, err)
        return
    }

    httpapi.WriteResponse(w, r, output)
}

Read the package documentation for more information.

Documentation

Overview

Package httpapi provides assistance for servers that implement a JSON Web API. It has no pretensions to be a framework: it is intended to work with the standard library HTTP handlers. The goal is to provide simple primitives for reading input from HTTP requests and writing output to the HTTP response writer.

The package supports compressing responses if the client can support it. It also provides non-standard support for clients compressing the body of requests. See the ReadRequest function for more details.

The WriteError function provides a simple, consistent way to send error messages to HTTP clients. It has some sensible defaults for the format and handling of JSON error messages, but can be customized. See the writeerror subdirectory package for details.

Example
package main

import (
	"net/http"

	"github.com/gorilla/mux"
	"github.com/jjeffery/httpapi"
)

func main() {
	r := mux.NewRouter()
	r.Path("/api/something").Methods("POST").HandlerFunc(postHandler)
	r.Path("/api/something").Methods("GET").HandlerFunc(getHandler)
	http.ListenAndServe(":8080", r)
}

// postHandler handles POST requests
func postHandler(w http.ResponseWriter, r *http.Request) {
	// unmarshal input from request
	var input PostSomethingInput
	if err := httpapi.ReadRequest(r, &input); err != nil {
		httpapi.WriteError(w, r, err)
		return
	}

	output, err := postSomething(r.Context(), &input)
	if err != nil {
		httpapi.WriteError(w, r, err)
		return
	}

	httpapi.WriteResponse(w, r, output)
}

// getHandler extracts the input from the query strings of the HTTP request.
func getHandler(w http.ResponseWriter, r *http.Request) {
	query := httpapi.Query(r)
	input := GetSomethingInput{
		Search: query.GetString("q"),
		Since:  query.GetTime("since"),
		Limit:  query.GetInt("limit"),
		Offset: query.GetInt("offset"),
	}

	// validate once after all query string parameters have been read
	if err := query.Err(); err != nil {
		httpapi.WriteResponse(w, r, err)
		return
	}

	output, err := getSomething(r.Context(), &input)
	if err != nil {
		httpapi.WriteError(w, r, err)
		return
	}

	httpapi.WriteResponse(w, r, output)
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ReadRequest

func ReadRequest(r *http.Request, body interface{}) error

ReadRequest reads the request body as JSON, and unmarshals it into the structure pointed to by body.

Although not specified in the HTTP spec, if the request contains a header "Content-Encoding: gzip", then the request body will be decompressed. This is convenient for HTTP clients that PUT or POST large JSON content.

func WriteError

func WriteError(w http.ResponseWriter, r *http.Request, err error)

WriteError writes an error message as a JSON object.

The HTTP status code is retrieved from the error using the errkind package. If no status is associated with the error then a 500 status is returned.

Care is taken to ensure that no implementation details are leaked to the client. If the error implements the `publicer` interface (as defined in the errkind package), then the error's message and HTTP status are considered suitable for returning to the client. Otherwise a more general error message is returned.

If the client is considered a "trusted" client, then full details of the error are returned in an extra details key that is not present for untrusted clients. By default a client is trusted if the request originated on the local host (but does not include requests routed through a local reverse proxy).

The writeerror subdirectory package provides configuration on how errors are marshalled to the client, and how details of the errors are logged and/or traced. The defaults are sensible, so this function can be used with no configuration.

func WriteResponse

func WriteResponse(w http.ResponseWriter, r *http.Request, body interface{})

WriteResponse sends the response as JSON to the HTTP client. The response is compressed if the HTTP client is able to accept compressed responses.

Types

type HandlerFunc

type HandlerFunc func(http.ResponseWriter, *http.Request) error

HandlerFunc is similar to http.HandlerFunc, but it returns an error.

func (HandlerFunc) ServeHTTP

func (fn HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements the http.Handler interface.

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware is a function that filters a request coming into the application and responses going back to the client. Middleware is similar in concept to Rack middleware.

type Stack

type Stack struct {
	// contains filtered or unexported fields
}

A Stack is a stack of middleware functions that are common to one or more HTTP handlers. A middleware function is any function that accepts a Handler as a parameter and returns a Handler.

func Use

func Use(f ...Middleware) *Stack

Use creates a Stack of middleware functions.

func (*Stack) Handler

func (s *Stack) Handler(h http.Handler) http.Handler

Handler creates a http.Handler from a stack of middleware functions and a httpctx.Handler.

func (*Stack) HandlerFunc

func (s *Stack) HandlerFunc(f func(http.ResponseWriter, *http.Request)) http.Handler

HandlerFunc returns a http.Handler (compatible with the standard library http package), which calls the middleware handlers in the stack s, followed by the handler function f.

func (*Stack) Use

func (s *Stack) Use(f ...Middleware) *Stack

Use creates a new stack by appending the middleware functions to the existing stack.

type Values

type Values struct {
	// contains filtered or unexported fields
}

Values provides convenient methods for extracting arguments from the query string.

func Query

func Query(r *http.Request) *Values

Query returns values from the query string part of the request URL.

func (*Values) Err

func (v *Values) Err() error

Err returns nil if no errors have been encountered, otherwise it returns a bad request error that lists the parameter(s) that are not in the correct format.

func (*Values) GetBool

func (v *Values) GetBool(name string) bool

GetBool returns a bool. Returns false if the query value is not present in the query.

func (*Values) GetDate

func (v *Values) GetDate(name string) local.Date

GetDate returns a date. The date should be in ISO8601 format. Returns zero if the date value if not present in the query.

func (*Values) GetInt

func (v *Values) GetInt(name string) int

GetInt returns an int. Returns 0 if the query value is not present in the query.

func (*Values) GetString

func (v *Values) GetString(name string) string

GetString returns a string. Returns "" if the query value is not present in the query.

func (*Values) GetTime

func (v *Values) GetTime(name string) time.Time

GetTime returns a time. The time should be in RFC3339 format. Returns zero if the time value if not present in the query.

func (*Values) LookupBool

func (v *Values) LookupBool(name string) (b bool, ok bool)

LookupBool returns a bool, with an indication of whether the query value was present in the query.

func (*Values) LookupDate

func (v *Values) LookupDate(name string) (d local.Date, ok bool)

LookupDate returns a date. The date should be in ISO8601 format.

func (*Values) LookupInt

func (v *Values) LookupInt(name string) (n int, ok bool)

LookupInt returns an integer, with an indication of whether the query value was present.

func (*Values) LookupString

func (v *Values) LookupString(name string) (s string, ok bool)

LookupString returns a string, with an indication of whether the query value was present in the query.

func (*Values) LookupTime

func (v *Values) LookupTime(name string) (t time.Time, ok bool)

LookupTime returns a time. The time should be in RFC3339 format.

Directories

Path Synopsis
Package writeerror is used to configure how errors are marshalled and logged in calls to httpapi.WriteError.
Package writeerror is used to configure how errors are marshalled and logged in calls to httpapi.WriteError.

Jump to

Keyboard shortcuts

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