README

Go-Relax GoDoc Project progress

Build fast and complete RESTful APIs in Go

Go-Relax aims to provide the tools to help developers build RESTful web services, and information needed to abide by REST architectural constraints using correct HTTP semantics.

Quick Start

Install using "go get":

go get github.com/codehack/go-relax

Then import from your source:

import "github.com/codehack/go-relax"

View example_test.go for an extended example of basic usage and features.

Also, check the wiki for Howto's and recipes.

Features

  • Helps build API's that follow the REST concept using ROA principles.
  • Built-in support of HATEOAS constraint with Link header (and soon JSON-LD).
  • Follows REST "best practices", with inspiration from Heroku and GitHub.
  • Works fine along with http.ServeMux or independently as http.Handler
  • Supports different media types, and mixed for requests and responses.
  • It uses JSON media type by default, but also includes XML (needs import).
  • The default routing engine uses trie with regexp matching for speed and flexibility.
  • Comes with a complete set of filters to build a working API. "Batteries included"
  • Uses sync.pool to efficiently use resources when under heavy load.
Included filters
  • Content - handles mixed request/response encodings, language preference, and versioning.
  • Basic authentication - to protect any resource with passwords.
  • CORS - Cross-Origin Resource Sharing, for remote client-server setups.
  • ETag - entity tagging with conditional requests for efficient caching.
  • GZip - Dynamic gzip content data compression, with ETag support.
  • Logging - custom logging with pre- and post- request event support.
  • Method override - GET/POST method override via HTTP header and query string.
  • Security - Various security practices for request handling.
  • Limits - request throttler, token-based rate limiter, and memory limits.
  • RestCop (Constraints Output Profiler) - it warns you when your responses are not RESTful.
  • Status - system status.

Documentation

The full code documentation is located at GoDoc:

http://godoc.org/github.com/codehack/go-relax

The source code is thoroughly commented, have a look.

Hello World

This minimal example creates a new Relax service that handles a Hello resource.

package main

import (
   "github.com/codehack/go-relax"
)

type Hello string

func (h *Hello) Index(ctx *relax.Context) {
   ctx.Respond(h)
}

func main() {
   h := Hello("hello world!")
   svc := relax.NewService("http://api.company.com/")
   svc.Resource(&h)
   svc.Run()
}

$ curl -i -X GET http://api.company.com/hello

Response:

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
Link: </hello>; rel="self"
Link: </hello>; rel="index"
Request-Id: 61d430de-7bb6-4ff8-84da-aff6fe81c0d2
Server: Go-Relax/0.5.0
Date: Thu, 14 Aug 2014 06:20:48 GMT
Content-Length: 14

"hello world!"

Credits

Go-Relax is Copyright (c) 2014 Codehack. Published under MIT License

Expand ▾ Collapse ▴

Documentation

Overview

    Package relax is a framework of pluggable components to build RESTful API's. It provides a thin layer over “net/http“ to serve resources, without imposing a rigid structure. It is meant to be used along “http.ServeMux“, but will work as a replacement as it implements “http.Handler“.

    The framework is divided into components: Encoding, Filters, Routing, Hypermedia and, Resources. These are the parts of a complete REST Service. All the components are designed to be pluggable (replaced) through interfaces by external packages. Relax provides enough built-in functionality to assemble a complete REST API.

    The system is based on Resource Oriented Architecture (ROA), and had some inspiration from Heroku's REST API.

    Example (Basic)

      Example_basic creates a new service under path "/v1" and serves requests for the users resource.

      Output:
      
      

      Index

      Examples

      Constants

      View Source
      const (
      	// ContentMediaType is the vendor extended media type used by this framework.
      	ContentMediaType = "application/vnd.relax"
      
      	// ContentDefaultVersion is the default version value when no content version is requested.
      	ContentDefaultVersion = "current"
      
      	// ContentDefaultLanguage is the default langauge value when no content language is requested.
      	ContentDefaultLanguage = "en-US"
      )
      View Source
      const (
      	StatusPreconditionRequired          = 428
      	StatusTooManyRequests               = 429
      	StatusRequestHeaderFieldsTooLarge   = 431
      	StatusNetworkAuthenticationRequired = 511
      )

        These status codes are inaccessible in net/http but they work with http.StatusText(). They are included here as they might be useful. See also, https://tools.ietf.org/html/rfc6585

        View Source
        const (
        	// LogFormatRelax is the default Relax post-event format
        	LogFormatRelax = "%C [%-.8[1]L] \"%#[1]r\" => \"%#[1]s\" done in %.6[1]Ds"
        
        	// LogFormatCommon is similar to Apache HTTP's Common Log Format (CLF)
        	LogFormatCommon = "%h %[1]l %[1]u %[1]t \"%[1]r\" %#[1]s %[1]b"
        
        	// LogFormatExtended is similar to NCSA extended/combined log format
        	LogFormatExtended = LogFormatCommon + " \"%[1]R\" \"%[1]A\""
        
        	// LogFormatReferer is similar to Apache HTTP's Referer log format
        	LogFormatReferer = "%R -> %[1]U"
        )

          Pre-made log formats. Most are based on Apache HTTP's. Note: the [n] notation will index an specific argument from Sprintf list.

          View Source
          const Version = "0.5.2"

            Version is the version of this package.

            Variables

            View Source
            var (
            	// ErrAuthInvalidRequest is returned when the auth request don't match the expected
            	// challenge.
            	ErrAuthInvalidRequest = errors.New("auth: Invalid authorization request")
            
            	// ErrAuthInvalidSyntax is returned when the syntax of the credentials is not what is
            	// expected.
            	ErrAuthInvalidSyntax = errors.New("auth: Invalid credentials syntax")
            )

              Errors returned by FilterAuthBasic that are general and could be reused.

              View Source
              var (
              	// ErrRouteNotFound is returned when the path searched didn't reach a resource handler.
              	ErrRouteNotFound = &StatusError{http.StatusNotFound, "That route was not found.", nil}
              
              	// ErrRouteBadMethod is returned when the path did not match a given HTTP method.
              	ErrRouteBadMethod = &StatusError{http.StatusMethodNotAllowed, "That method is not supported", nil}
              )

                These are errors returned by the default routing engine. You are encouraged to reuse them with your own routing engine.

                View Source
                var ErrBodyTooLarge = errors.New("encoder: Body too large")

                  ErrBodyTooLarge is returned by Encoder.Decode when the read length exceeds the maximum size set for payload.

                  Functions

                  func InternalServerError

                  func InternalServerError(w http.ResponseWriter, r *http.Request)

                    InternalServerError responds with HTTP status code 500-"Internal Server Error". This function is the default service recovery handler.

                    func LinkHeader

                    func LinkHeader(uri string, param ...string) (string, string)

                      LinkHeader returns a complete Link: header value that can be plugged into http.Header().Add(). Use this when you don't need a Link object for your relation, just a header. uri is the URI of target. param is one or more name=value pairs for link values. if nil, will default to rel="alternate" (as per RFC 4287). Returns two strings: "Link","Link header spec"

                      func MustAuthenticate

                      func MustAuthenticate(w http.ResponseWriter, challenge string)

                        MustAuthenticate is a helper function used to send the WWW-Authenticate HTTP header. challenge is the auth scheme and the realm, as specified in section 2 of RFC 2617.

                        func NewRequestID

                        func NewRequestID(id string) string

                          NewRequestID returns a new request ID value based on UUID; or checks an id specified if it's valid for use as a request ID. If the id is not valid then it returns a new ID.

                          A valid ID must be between 20 and 200 chars in length, and URL-encoded.

                          func ParsePreferences

                          func ParsePreferences(values string) (map[string]float32, error)

                            ParsePreferences is a very naive and simple parser for header value preferences. Returns a map of preference=quality values for each preference with a quality value. If a preference doesn't specify quality, then a value of 1.0 is assumed (bad!). If the quality float value can't be parsed from string, an error is returned.

                            func PathExt

                            func PathExt(path string) string

                              PathExt returns the media subtype extension in an URL path. The extension begins from the last dot:

                              /api/v1/tickets.xml => ".xml"
                              

                              Returns the extension with dot, or empty string "" if not found.

                              Types

                              type CRUD

                              type CRUD interface {
                              	// Create may allow the creation of new resource items via methods POST/PUT.
                              	Create(*Context)
                              
                              	// Read may display a specific resource item given an ID or name via method GET.
                              	Read(*Context)
                              
                              	// Update may allow updating resource items via methods PATCH/PUT.
                              	Update(*Context)
                              
                              	// Delete may allow removing items from a resource via method DELETE.
                              	Delete(*Context)
                              }

                                The CRUD interface is for Resourcer objects that provide create, read, update and delete operations, also known as CRUD.

                                type Context

                                type Context struct {
                                	// ResponseWriter is the response object passed from “net/http“.
                                	http.ResponseWriter
                                
                                	// Buffer points to a buffered context, started with Context.Capture.
                                	// If not capturing, Buffer is nil.
                                	// See also: ResponseBuffer
                                	Buffer *ResponseBuffer
                                
                                	// Request points to the http.Request information for this request.
                                	Request *http.Request
                                
                                	// PathValues contains the values matched in PSEs by the router. It is a
                                	// name=values map (map[string][]string).
                                	// Examples:
                                	//		ctx.PathValues.Get("username") // returns the first value for "username"
                                	//		ctx.PathValues.Get("_2")       // values are also accessible by index
                                	//		ctx.PathValues["colors"]       // if more than one color value.
                                	//
                                	// See also: Router, url.Values
                                	PathValues url.Values
                                
                                	// Info contains information passed down from processed filters.
                                	// To print all values to stdout use:
                                	//		ctx.Info.Print()
                                	//
                                	// For usage, see http://github.com/codehack/go-environ
                                	Info *environ.Env
                                
                                	// Encode is the media encoding function requested by the client.
                                	// To see the media type use:
                                	//		ctx.Info.Get("content.encoding")
                                	//
                                	// See also: Encoder.Encode
                                	Encode func(io.Writer, interface{}) error
                                
                                	// Decode is the decoding function when this request was made. It expects an
                                	// object that implements io.Reader, usually Request.Body. Then it will decode
                                	// the data and try to save it into a variable interface.
                                	// To see the media type use:
                                	//		ctx.Info.Get("content.decoding")
                                	//
                                	// See also: Encoder.Decode
                                	Decode func(io.Reader, interface{}) error
                                	// contains filtered or unexported fields
                                }

                                  Context has information about the request and filters. It implements http.ResponseWriter.

                                  func NewContext

                                  func NewContext(w http.ResponseWriter, r *http.Request) *Context

                                    NewContext returns a new Context object. This function will alter Request.URL, adding scheme and host:port as provided by the client.

                                    func (*Context) Bytes

                                    func (ctx *Context) Bytes() int

                                      Bytes returns the number of bytes written in the response.

                                      func (*Context) Capture

                                      func (ctx *Context) Capture() *Context

                                        Capture starts a buffered context. All writes are diverted to a ResponseBuffer. Capture expects a call to Context.Release to end capturing. Returns a new buffered Context. See also: NewResponseBuffer, Context.Release

                                        func (*Context) Clone

                                        func (ctx *Context) Clone(w http.ResponseWriter) *Context

                                          Clone returns a shallow cloned context using 'w', an http.ResponseWriter object. If 'w' is nil, the ResponseWriter value can be assigned after cloning.

                                          func (*Context) Error

                                          func (ctx *Context) Error(code int, message string, details ...interface{})

                                            Error sends an error response, with appropiate encoding. It basically calls Respond using a status code and wrapping the message in a StatusError object.

                                            'code' is the HTTP status code of the error. 'message' is the actual error message or reason. 'details' are additional details about this error (optional).

                                            type RouteDetails struct {
                                            	Method string `json:"method"`
                                            	Path   string `json:"path"`
                                            }
                                            ctx.Error(http.StatusNotImplemented, "That route is not implemented", &RouteDetails{"PATCH", "/v1/tickets/{id}"})
                                            

                                            See also: Respond, StatusError

                                            func (*Context) Format

                                            func (ctx *Context) Format(f fmt.State, c rune)

                                              Format implements the fmt.Formatter interface, based on Apache HTTP's CustomLog directive. This allows a Context object to have Sprintf verbs for its values. See: https://httpd.apache.org/docs/2.4/mod/mod_log_config.html#formats

                                              Verb	Description
                                              ----	---------------------------------------------------
                                              
                                              %%  	Percent sign
                                              %a  	Client remote address
                                              %b  	Size of reponse in bytes, excluding headers. Or '-' if zero.
                                              %#a 	Proxy client address, or unknown.
                                              %h  	Remote hostname. Will perform lookup.
                                              %l  	Remote ident, will write '-' (only for Apache log support).
                                              %m  	Request method
                                              %q  	Request query string.
                                              %r  	Request line.
                                              %#r 	Request line without protocol.
                                              %s  	Response status code.
                                              %#s 	Response status code and text.
                                              %t  	Request time, as string.
                                              %u  	Remote user, if any.
                                              %v  	Request host name.
                                              %A  	User agent.
                                              %B  	Size of reponse in bytes, excluding headers.
                                              %C  	Colorized status code. For console, using ANSI escape codes.
                                              %D  	Time lapsed to serve request, in seconds.
                                              %H  	Request protocol.
                                              %I  	Bytes received.
                                              %L  	Request ID.
                                              %P  	Server port used.
                                              %R  	Referer.
                                              %U  	Request path.
                                              

                                              Example:

                                              // Print request line and remote address.
                                              // Index [1] needed to reuse ctx argument.
                                              fmt.Printf("\"%r\" %[1]a", ctx)
                                              // Output:
                                              // "GET /v1/" 192.168.1.10
                                              

                                              func (*Context) Free

                                              func (ctx *Context) Free()

                                                Free frees a Context object back to the usage pool for later, to conserve system resources.

                                                func (*Context) Header

                                                func (ctx *Context) Header() http.Header

                                                  Header implements ResponseWriter.Header

                                                  func (*Context) IsSSL

                                                  func (ctx *Context) IsSSL() bool

                                                    IsSSL returns true if the context request is done via SSL/TLS. SSL status is guessed from value of Request.TLS. It also checks the value of the X-Forwarded-Proto header, in case the request is proxied.

                                                    func (*Context) ProxyClient

                                                    func (ctx *Context) ProxyClient() string

                                                      ProxyClient returns the client address if the request is proxied. This is a best-guess based on the headers sent. The function will check the following headers, in order, to find a proxied client: Forwarded, X-Forwarded-For and X-Real-IP. Returns the client address or "unknown".

                                                      func (*Context) Release

                                                      func (ctx *Context) Release()

                                                        Release ends capturing within the context. Every Capture call needs a Release, otherwise the buffer will over-extend and the response will fail. You may or not defer this call after Capture, it depends on your state.

                                                        func (*Context) Respond

                                                        func (ctx *Context) Respond(v interface{}, code ...int) error

                                                          Respond writes a response back to the client. A complete RESTful response should be contained within a structure.

                                                          'v' is the object value to be encoded. 'code' is an optional HTTP status code.

                                                          If at any point the response fails (due to encoding or system issues), an error is returned but not written back to the client.

                                                          type Message struct {
                                                          	Status int    `json:"status"`
                                                          	Text   string `json:"text"`
                                                          }
                                                          
                                                          ctx.Respond(&Message{Status: 201, Text: "Ticket created"}, http.StatusCreated)
                                                          

                                                          See also: Context.Encode, WriteHeader

                                                          func (*Context) Status

                                                          func (ctx *Context) Status() int

                                                            Status returns the current known HTTP status code, or http.StatusOK if unknown.

                                                            func (*Context) Write

                                                            func (ctx *Context) Write(b []byte) (int, error)

                                                              Write implements ResponseWriter.Write

                                                              func (*Context) WriteHeader

                                                              func (ctx *Context) WriteHeader(code int)

                                                                WriteHeader will force a status code header, if one hasn't been set. If no call to WriteHeader is done within this context, it defaults to http.StatusOK (200), which is sent by net/http.

                                                                type Encoder

                                                                type Encoder interface {
                                                                	// Accept returns the media type used in HTTP Accept header.
                                                                	Accept() string
                                                                
                                                                	// ContentType returns the media type, and optionally character set,
                                                                	// for decoding used in Content-Type header.
                                                                	ContentType() string
                                                                
                                                                	// Encode function encodes the value of an interface and writes it to an
                                                                	// io.Writer stream (usually an http.ResponseWriter object).
                                                                	Encode(io.Writer, interface{}) error
                                                                
                                                                	// Decode function decodes input from an io.Reader (usually Request.Body) and
                                                                	// tries to save it to an interface variable.
                                                                	Decode(io.Reader, interface{}) error
                                                                }

                                                                  Encoder objects provide new data encoding formats.

                                                                  Once a request enters service context, all responses are encoded according to the assigned encoder. Relax includes support for JSON encoding. Other types of encoding can be added by implementing the Encoder interface.

                                                                  type EncoderJSON

                                                                  type EncoderJSON struct {
                                                                  	// MaxBodySize is the maximum size (in bytes) of JSON payload to read.
                                                                  	// Defaults to 2097152 (2MB)
                                                                  	MaxBodySize int64
                                                                  
                                                                  	// Indented indicates whether or not to output indented JSON.
                                                                  	// Note: indented JSON is slower to encode.
                                                                  	// Defaults to false
                                                                  	Indented bool
                                                                  
                                                                  	// AcceptHeader is the media type used in Accept HTTP header.
                                                                  	// Defaults to "application/json"
                                                                  	AcceptHeader string
                                                                  
                                                                  	// ContentTypeHeader is the media type used in Content-Type HTTP header
                                                                  	// Defaults to "application/json;charset=utf-8"
                                                                  	ContentTypeHeader string
                                                                  }

                                                                    EncoderJSON implements the Encoder interface. It encode/decodes JSON data.

                                                                    func NewEncoderJSON

                                                                    func NewEncoderJSON() *EncoderJSON

                                                                      NewEncoderJSON returns an EncoderJSON object. This function will initiallize the object with sane defaults, for use with Service.encoders. Returns the new EncoderJSON object.

                                                                      func (*EncoderJSON) Accept

                                                                      func (e *EncoderJSON) Accept() string

                                                                        Accept returns the media type for JSON content, used in Accept header.

                                                                        func (*EncoderJSON) ContentType

                                                                        func (e *EncoderJSON) ContentType() string

                                                                          ContentType returns the media type for JSON content, used in the Content-Type header.

                                                                          func (*EncoderJSON) Decode

                                                                          func (e *EncoderJSON) Decode(reader io.Reader, v interface{}) error

                                                                            Decode reads a JSON payload (usually from Request.Body) and tries to save it to a variable v. If the payload is too large, with maximum EncoderJSON.MaxBodySize, it will fail with error ErrBodyTooLarge Returns nil on success and error on failure.

                                                                            func (*EncoderJSON) Encode

                                                                            func (e *EncoderJSON) Encode(writer io.Writer, v interface{}) error

                                                                              Encode will try to encode the value of v into JSON. If EncoderJSON.Indented is true, then the JSON will be indented with tabs. Returns nil on success, error on failure.

                                                                              type Filter

                                                                              type Filter interface {
                                                                              	// Run executes the current filter in a chain.
                                                                              	// It takes a HandlerFunc function argument, which is executed within the
                                                                              	// closure returned.
                                                                              	Run(HandlerFunc) HandlerFunc
                                                                              }

                                                                                Filter is a function closure that is chained in FILO (First-In Last-Out) order. Filters pre and post process all requests. At any time, a filter can stop a request by returning before the next chained filter is called. The final link points to the resource handler.

                                                                                Filters are run at different times during a request, and in order: Service, Resource and, Route. Service filters are run before resource filters, and resource filters before route filters. This allows some granularity to filters.

                                                                                Relax comes with filters that provide basic functionality needed by most REST API's. Some included filters: CORS, method override, security, basic auth and content negotiation. Adding filters is a matter of creating new objects that implement the Filter interface. The position of the “next()“ handler function is important to the effect of the particular filter execution.

                                                                                type FilterAuthBasic

                                                                                type FilterAuthBasic struct {
                                                                                	// Realm is the authentication realm.
                                                                                	// This defaults to "Authorization Required"
                                                                                	Realm string
                                                                                
                                                                                	// Authenticate is a function that will perform the actual authentication
                                                                                	// check.
                                                                                	// It should expect a username and password, then return true if those
                                                                                	// credentials are accepted; false otherwise.
                                                                                	// If no function is assigned, it defaults to a function that denies all
                                                                                	// (false).
                                                                                	Authenticate func(string, string) bool
                                                                                }

                                                                                  FilterAuthBasic is a Filter that implements HTTP Basic Authentication as described in http://www.ietf.org/rfc/rfc2617.txt

                                                                                  func (*FilterAuthBasic) Run

                                                                                    Run runs the filter and passes down the following Info:

                                                                                    ctx.Info.Get("auth.user") // auth user
                                                                                    ctx.Info.Get("auth.type") // auth scheme type. e.g., "basic"
                                                                                    

                                                                                    type FilterCORS

                                                                                    type FilterCORS struct {
                                                                                    	// AllowOrigin is the list of URI patterns that are allowed to use the resource.
                                                                                    	// The patterns consist of text with zero or more wildcards '*' '?' '+'.
                                                                                    	//
                                                                                    	// '*' matches zero or more characters.
                                                                                    	// '?' matches exactly one character.
                                                                                    	// '_' matches zero or one character.
                                                                                    	// '+' matches at least one character.
                                                                                    	//
                                                                                    	// Note that a single pattern of '*' will match all origins, if that's what you need
                                                                                    	// then use AllowAnyOrigin=true instead. If AllowOrigin is empty and AllowAnyOrigin=false,
                                                                                    	// then all CORS requests (simple and preflight) will fail with an HTTP error response.
                                                                                    	//
                                                                                    	// Examples:
                                                                                    	// 	http://*example.com - matches example.com and all its subdomains.
                                                                                    	// 	http_://+.example.com - matches SSL and non-SSL, and subdomains of example.com, but not example.com
                                                                                    	// 	http://foo??.example.com - matches subdomains fooXX.example.com where X can be any character.
                                                                                    	//		chrome-extension://* - good for testing from Chrome.
                                                                                    	//
                                                                                    	// Default: empty
                                                                                    	AllowOrigin []string
                                                                                    
                                                                                    	// AllowAnyOrigin if set to true, it will allow all origin requests.
                                                                                    	// This is effectively "Access-Control-Allow-Origin: *" as in the CORS specification.
                                                                                    	//
                                                                                    	// Default: false
                                                                                    	AllowAnyOrigin bool
                                                                                    
                                                                                    	// AllowMethods is the list of HTTP methods that can be used in a request. If AllowMethods
                                                                                    	// is empty, all permission requests (preflight) will fail with an HTTP error response.
                                                                                    	//
                                                                                    	// Default: "GET", "POST", "PATCH", "PUT", "DELETE"
                                                                                    	AllowMethods []string
                                                                                    
                                                                                    	// AllowHeaders is the list of HTTP headers that can be used in a request. If AllowHeaders
                                                                                    	// is empty, then only simple common HTTP headers are allowed.
                                                                                    	//
                                                                                    	// Default: "Authorization", "Content-Type", "If-Match", "If-Modified-Since", "If-None-Match", "If-Unmodified-Since", "X-Requested-With"
                                                                                    	AllowHeaders []string
                                                                                    
                                                                                    	// AllowCredentials whether or not to allow user credendials to propagate through a request.
                                                                                    	// If AllowCredentials is false, then all authentication and cookies are disabled.
                                                                                    	//
                                                                                    	// Default: false
                                                                                    	AllowCredentials bool
                                                                                    
                                                                                    	// ExposeHeaders is a list of HTTP headers that can be exposed to the API. This list should
                                                                                    	// include any custom headers that are needed to complete the response.
                                                                                    	//
                                                                                    	// Default: "Etag", "Link", "RateLimit-Limit", "RateLimit-Remaining", "RateLimit-Reset", "X-Poll-Interval"
                                                                                    	ExposeHeaders []string
                                                                                    
                                                                                    	// MaxAge is a number of seconds the permission request (preflight) results should be cached.
                                                                                    	// This number should be large enough to complete all request from a client, but short enough to
                                                                                    	// keep the API secure. Set to -1 to disable caching.
                                                                                    	//
                                                                                    	// Default: 86400
                                                                                    	MaxAge int
                                                                                    
                                                                                    	// Strict specifies whether or not to adhere strictly to the W3C CORS recommendation. If
                                                                                    	// Strict=false then the focus is performance instead of correctness. Also, Strict=true
                                                                                    	// will add more security checks to permission requests (preflight) and other security decisions.
                                                                                    	//
                                                                                    	// Default: false
                                                                                    	Strict bool
                                                                                    }

                                                                                      FilterCORS implements the Cross-Origin Resource Sharing (CORS) recommendation, as described in http://www.w3.org/TR/cors/ (W3C).

                                                                                      func (*FilterCORS) Run

                                                                                      func (f *FilterCORS) Run(next HandlerFunc) HandlerFunc

                                                                                        Run runs the filter and passes down the following Info:

                                                                                        ctx.Info.Get("cors.request") // boolean, whether or not this was a CORS request.
                                                                                        ctx.Info.Get("cors.origin")  // Origin of the request, if it's a CORS request.
                                                                                        

                                                                                        type FilterETag

                                                                                        type FilterETag struct {
                                                                                        	// DisableConditionals will make this filter ignore the values from the headers
                                                                                        	// If-None-Match and If-Match and not do conditional entity tests. An ETag will
                                                                                        	// still be generated, if possible.
                                                                                        	// Defaults to false
                                                                                        	DisableConditionals bool
                                                                                        }

                                                                                          FilterETag generates an entity-tag header "ETag" for body content of a response. It will use pre-generated etags from the underlying filters or handlers, if availble. Optionally, it will also handle the conditional response based on If-Match and If-None-Match checks on specific entity-tag values. This implementation follows the recommendation in http://tools.ietf.org/html/rfc7232

                                                                                          func (*FilterETag) Run

                                                                                          func (f *FilterETag) Run(next HandlerFunc) HandlerFunc

                                                                                            Run runs the filter and passes down the following Info:

                                                                                            ctx.Info.Get("etag.enabled") // boolean; true if etag is enabled (always)
                                                                                            

                                                                                            type FilterGzip

                                                                                            type FilterGzip struct {
                                                                                            	// CompressionLevel specifies the level of compression used for gzip.
                                                                                            	// Value must be between -1 (gzip.DefaultCompression) to 9 (gzip.BestCompression)
                                                                                            	// A value of 0 (gzip.DisableCompression) will disable compression.
                                                                                            	// Defaults to “gzip.BestSpeed“
                                                                                            	CompressionLevel int
                                                                                            
                                                                                            	// MinLength is the minimum content length, in bytes, required to do compression.
                                                                                            	// Defaults to 100
                                                                                            	MinLength int
                                                                                            }

                                                                                              FilterGzip compresses the response with gzip encoding, if the client indicates support for it.

                                                                                              func (*FilterGzip) Run

                                                                                              func (f *FilterGzip) Run(next HandlerFunc) HandlerFunc

                                                                                                Run runs the filter and passes down the following Info:

                                                                                                ctx.Info.Get("content.gzip") // boolean; whether gzip actually happened.
                                                                                                

                                                                                                The info passed is used by ETag to generate distinct entity-tags for gzip'ed content.

                                                                                                type FilterLog

                                                                                                type FilterLog struct {
                                                                                                	// Logger is an interface that is based on Go's log package. Any logging
                                                                                                	// system that implements Logger can be used.
                                                                                                	// Defaults to the stdlog in 'log' package.
                                                                                                	Logger
                                                                                                
                                                                                                	// PreLogFormat is the format for the pre-request log entry.
                                                                                                	// Leave empty if no log even is needed.
                                                                                                	// Default to empty (no pre-log)
                                                                                                	PreLogFormat string
                                                                                                
                                                                                                	// PostLogFormat is the format for the post-request log entry.
                                                                                                	// Defaults to the value of LogFormatRelax
                                                                                                	PostLogFormat string
                                                                                                }

                                                                                                  FilterLog provides pre- and post-request event logs. It uses a custom log format similar to the one used for Apache HTTP CustomLog directive.

                                                                                                  myservice.Use(logrus.New())
                                                                                                  log := &FilterLog{Logger: myservice.Logger(), PreLogFormat: LogFormatReferer}
                                                                                                  log.Println("FilterLog implements Logger.")
                                                                                                  
                                                                                                  // Context-specific format verbs (see Context.Format)
                                                                                                  log.Panicf("%C bad status", ctx)
                                                                                                  

                                                                                                  func (*FilterLog) Run

                                                                                                  func (f *FilterLog) Run(next HandlerFunc) HandlerFunc

                                                                                                    Run processes the filter. No info is passed.

                                                                                                    type FilterOverride

                                                                                                    type FilterOverride struct {
                                                                                                    	// Header expected for HTTP Method override
                                                                                                    	// Default: "X-HTTP-Method-Override"
                                                                                                    	Header string
                                                                                                    
                                                                                                    	// QueryVar is used if header can't be set
                                                                                                    	// Default: "_method"
                                                                                                    	QueryVar string
                                                                                                    
                                                                                                    	// Methods specifies the methods can be overriden.
                                                                                                    	// Format is Methods["method"] = "override".
                                                                                                    	// Default methods:
                                                                                                    	//		f.Methods = map[string]string{
                                                                                                    	//			"DELETE":  "POST",
                                                                                                    	//			"OPTIONS": "GET",
                                                                                                    	//			"PATCH":   "POST",
                                                                                                    	//			"PUT":     "POST",
                                                                                                    	//		}
                                                                                                    	Methods map[string]string
                                                                                                    }

                                                                                                      FilterOverride changes the Request.Method if the client specifies override via HTTP header or query. This allows clients with limited HTTP verbs to send REST requests through GET/POST.

                                                                                                      func (*FilterOverride) Run

                                                                                                      func (f *FilterOverride) Run(next HandlerFunc) HandlerFunc

                                                                                                        Run runs the filter and passes down the following Info:

                                                                                                        ctx.Info.Get("override.method") // method replaced. e.g., "DELETE"
                                                                                                        

                                                                                                        type FilterSecurity

                                                                                                        type FilterSecurity struct {
                                                                                                        	// UACheckDisable if false, a check is done to see if the client sent a valid non-emtpy
                                                                                                        	// User-Agent header with the request.
                                                                                                        	// Defaults to false.
                                                                                                        	UACheckDisable bool
                                                                                                        
                                                                                                        	// UACheckErrMsg is the response body sent when a client fails User-Agent check.
                                                                                                        	// Defaults to (taken from Heroku's UA check message):
                                                                                                        	// 	"Request forbidden by security rules.\n" +
                                                                                                        	// 	"Please make sure your request has an User-Agent header."
                                                                                                        	UACheckErrMsg string
                                                                                                        
                                                                                                        	// XFrameDisable if false, will send a X-Frame-Options header with the response,
                                                                                                        	// using the value in XFrameOptions. X-Frame-Options provides clickjacking protection.
                                                                                                        	// For details see https://www.owasp.org/index.php/Clickjacking
                                                                                                        	// https://www.rfc-editor.org/rfc/rfc7034.txt
                                                                                                        	// http://tools.ietf.org/html/draft-ietf-websec-x-frame-options-12
                                                                                                        	// Defaults to false.
                                                                                                        	XFrameDisable bool
                                                                                                        
                                                                                                        	// XFrameOptions expected values are:
                                                                                                        	//		"DENY"                // no rendering within a frame
                                                                                                        	//		"SAMEORIGIN"          // no rendering if origin mismatch
                                                                                                        	//		"ALLOW-FROM {origin}" // allow rendering if framed by frame loaded from {origin};
                                                                                                        	//			              // where {origin} is a top-level URL. ie., http//codehack.com
                                                                                                        	// Only one value can be used at a time.
                                                                                                        	// Defaults to "SAMEORIGIN"
                                                                                                        	XFrameOptions string
                                                                                                        
                                                                                                        	// XCTODisable if false, will send a X-Content-Type-Options header with the response
                                                                                                        	// using the value "nosniff". This prevents Internet Explorer and Google Chrome from
                                                                                                        	// MIME-sniffing and ignoring the value set in Content-Type.
                                                                                                        	// Defaults to false.
                                                                                                        	XCTODisable bool
                                                                                                        
                                                                                                        	// HSTSDisable if false, will send a Strict-Transport-Security (HSTS) header
                                                                                                        	// with the respose, using the value in HSTSOptions. HSTS enforces secure
                                                                                                        	// connections to the server. http://tools.ietf.org/html/rfc6797
                                                                                                        	// If the server is not on a secure HTTPS/TLS connection, it will temporarily
                                                                                                        	// change to true.
                                                                                                        	// Defaults to false.
                                                                                                        	HSTSDisable bool
                                                                                                        
                                                                                                        	// HSTSOptions are the values sent in an HSTS header.
                                                                                                        	// Expected values are one or both of:
                                                                                                        	//		"max-age=delta"     // delta in seconds, the time this host is a known HSTS host
                                                                                                        	//		"includeSubDomains" // HSTS policy applies to this domain and all subdomains.
                                                                                                        	// Defaults to "max-age=31536000; includeSubDomains"
                                                                                                        	HSTSOptions string
                                                                                                        
                                                                                                        	// CacheDisable if false, will send a Cache-Control header with the response,
                                                                                                        	// using the value in CacheOptions. If this value is true, it will also
                                                                                                        	// disable Pragma header (see below).
                                                                                                        	// Defaults to false.
                                                                                                        	CacheDisable bool
                                                                                                        
                                                                                                        	// CacheOptions are the value sent in an Cache-Control header.
                                                                                                        	// For details, see http://tools.ietf.org/html/rfc7234#section-5.2
                                                                                                        	// Defaults to "no-store, must-revalidate"
                                                                                                        	CacheOptions string
                                                                                                        
                                                                                                        	// PragmaDisable if false and CacheDisable is false, will send a Pragma header
                                                                                                        	// with the response, using the value "no-cache".
                                                                                                        	// For details see http://tools.ietf.org/html/rfc7234#section-5.4
                                                                                                        	// Defaults to false.
                                                                                                        	PragmaDisable bool
                                                                                                        }

                                                                                                          FilterSecurity is a Filter that provides some security options and checks. Most of the options are HTTP headers sent back so that web clients can adjust their configuration. See https://www.owasp.org/index.php/List_of_useful_HTTP_headers

                                                                                                          func (*FilterSecurity) Run

                                                                                                          func (f *FilterSecurity) Run(next HandlerFunc) HandlerFunc

                                                                                                            Run runs the filter and passes down the following Info:

                                                                                                            ctx.Info.Get("security.sts") // boolean; whether STS was enabled.
                                                                                                            

                                                                                                            type HandlerFunc

                                                                                                            type HandlerFunc func(*Context)

                                                                                                              HandlerFunc is simply a version of http.HandlerFunc that uses Context. All filters must return and accept this type.

                                                                                                              type Link struct {
                                                                                                              	URI      string `json:"href"`
                                                                                                              	Rel      string `json:"rel"`
                                                                                                              	Anchor   string `json:"anchor,omitempty"`
                                                                                                              	Rev      string `json:"rev,omitempty"`
                                                                                                              	HrefLang string `json:"hreflang,omitempty"`
                                                                                                              	Media    string `json:"media,omitempty"`
                                                                                                              	Title    string `json:"title,omitempty"`
                                                                                                              	Type     string `json:"type,omitempty"`
                                                                                                              }

                                                                                                                Link represents a hypertext relation link. It implements HTTP web links between resources that are not format specific. For details see also, Web Linking: :https://tools.ietf.org/html/rfc5988 URI Template: http://tools.ietf.org/html/rfc6570

                                                                                                                func (*Link) String

                                                                                                                func (l *Link) String() string

                                                                                                                  String returns a string representation of a Link object. Suitable for use in Link: headers.

                                                                                                                  type Logger

                                                                                                                  type Logger interface {
                                                                                                                  	Print(...interface{})
                                                                                                                  	Printf(string, ...interface{})
                                                                                                                  	Println(...interface{})
                                                                                                                  }

                                                                                                                    Logger interface is based on Go's “log“ package. Objects that implement this interface can provide logging to Relax resources.

                                                                                                                    type Resource

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

                                                                                                                      Resource is an object that implements Resourcer; serves requests for a resource.

                                                                                                                      func (*Resource) CRUD

                                                                                                                      func (r *Resource) CRUD(pse string) *Resource

                                                                                                                        CRUD adds Create/Read/Update/Delete routes using the handlers in CRUD interface, if the object implements it. A typical resource will implement one or all of the handlers, but those that aren't implemented should respond with "Method Not Allowed" or "Not Implemented".

                                                                                                                        pse is a route path segment expression (PSE) - see Router for details. If pse is empty string "", then CRUD() will guess a value or use "{item}".

                                                                                                                        type Jobs struct{}
                                                                                                                        
                                                                                                                        // functions needed for Jobs to implement CRUD.
                                                                                                                        func (l *Jobs) Create (ctx *Context) {}
                                                                                                                        func (l *Jobs) Read (ctx *Context) {}
                                                                                                                        func (l *Jobs) Update (ctx *Context) {}
                                                                                                                        func (l *Jobs) Delete (ctx *Context) {}
                                                                                                                        
                                                                                                                        // CRUD() will add routes handled using "{uint:ticketid}" as PSE.
                                                                                                                        myservice.Resource(&Jobs{}).CRUD("{uint:ticketid}")
                                                                                                                        

                                                                                                                        The following routes are added:

                                                                                                                        GET /api/jobs/{uint:ticketid}     => use handler jobs.Read()
                                                                                                                        POST /api/jobs                    => use handler jobs.Create()
                                                                                                                        PUT /api/jobs                     => Status: 405 Method not allowed
                                                                                                                        PUT /api/jobs/{uint:ticketid}     => use handler jobs.Update()
                                                                                                                        DELETE /api/jobs                  => Status: 405 Method not allowed
                                                                                                                        DELETE /api/jobs/{uint:ticketid}  => use handler jobs.Delete()
                                                                                                                        

                                                                                                                        Specific uses of PUT/PATCH/DELETE are dependent on the application, so CRUD() won't make any assumptions for those.

                                                                                                                        func (*Resource) DELETE

                                                                                                                        func (r *Resource) DELETE(path string, h HandlerFunc, filters ...Filter) *Resource

                                                                                                                          DELETE is a convenient alias to Route using DELETE as method

                                                                                                                          func (*Resource) GET

                                                                                                                          func (r *Resource) GET(path string, h HandlerFunc, filters ...Filter) *Resource

                                                                                                                            GET is a convenient alias to Route using GET as method

                                                                                                                            func (*Resource) MethodNotAllowed

                                                                                                                            func (r *Resource) MethodNotAllowed(ctx *Context)

                                                                                                                              MethodNotAllowed is a handler used to send a response when a method is not allowed.

                                                                                                                              // Route "PATCH /users/profile" => 405 Method Not Allowed
                                                                                                                              users.PATCH("profile", users.MethodNotAllowed)
                                                                                                                              

                                                                                                                              func (*Resource) NotImplemented

                                                                                                                              func (r *Resource) NotImplemented(ctx *Context)

                                                                                                                                NotImplemented is a handler used to send a response when a resource route is not yet implemented.

                                                                                                                                // Route "GET /myresource/apikey" => 501 Not Implemented
                                                                                                                                myresource.GET("apikey", myresource.NotImplemented)
                                                                                                                                

                                                                                                                                func (*Resource) OPTIONS

                                                                                                                                func (r *Resource) OPTIONS(path string, h HandlerFunc, filters ...Filter) *Resource

                                                                                                                                  OPTIONS is a convenient alias to Route using OPTIONS as method

                                                                                                                                  func (*Resource) PATCH

                                                                                                                                  func (r *Resource) PATCH(path string, h HandlerFunc, filters ...Filter) *Resource

                                                                                                                                    PATCH is a convenient alias to Route using PATCH as method

                                                                                                                                    func (*Resource) POST

                                                                                                                                    func (r *Resource) POST(path string, h HandlerFunc, filters ...Filter) *Resource

                                                                                                                                      POST is a convenient alias to Route using POST as method

                                                                                                                                      func (*Resource) PUT

                                                                                                                                      func (r *Resource) PUT(path string, h HandlerFunc, filters ...Filter) *Resource

                                                                                                                                        PUT is a convenient alias to Route using PUT as method

                                                                                                                                        func (*Resource) Route

                                                                                                                                        func (r *Resource) Route(method, path string, h HandlerFunc, filters ...Filter) *Resource

                                                                                                                                          Route adds a resource route (method + path) and its handler to the router.

                                                                                                                                          'method' is the HTTP method verb (GET, POST, ...). 'path' is the URI path and optional path matching expressions (PSE). 'h' is the handler function with signature HandlerFunc. 'filters' are route-level filters run before the handler. If the resource has its own filters, those are prepended to the filters list; resource-level filters will run before route-level filters.

                                                                                                                                          Returns the resource itself for chaining.

                                                                                                                                          type Resourcer

                                                                                                                                          type Resourcer interface {
                                                                                                                                          	// Index may serve the entry GET request to a resource. Such as the listing
                                                                                                                                          	// of a collection.
                                                                                                                                          	Index(*Context)
                                                                                                                                          }

                                                                                                                                            Resourcer is any object that implements the this interface. A resource is a namespace where all operations for that resource happen.

                                                                                                                                            type Locations struct{
                                                                                                                                            	City string
                                                                                                                                            	Country string
                                                                                                                                            }
                                                                                                                                            
                                                                                                                                            // This function is needed for Locations to implement Resourcer
                                                                                                                                            func (l *Locations) Index (ctx *Context) { ctx.Respond(l) }
                                                                                                                                            
                                                                                                                                            loc := &Locations{City: "Scottsdale", Country: "US"}
                                                                                                                                            myresource := service.Resource(loc)
                                                                                                                                            

                                                                                                                                            type ResponseBuffer

                                                                                                                                            type ResponseBuffer struct {
                                                                                                                                            	bytes.Buffer
                                                                                                                                            	// contains filtered or unexported fields
                                                                                                                                            }

                                                                                                                                              ResponseBuffer implements http.ResponseWriter, but redirects all writes and headers to a buffer. This allows to inspect the response before sending it. When a response is buffered, it needs an explicit call to Flush or WriteTo to send it.

                                                                                                                                              ResponseBuffer also implements io.WriteTo to write data to any object that implements io.Writer.

                                                                                                                                              func NewResponseBuffer

                                                                                                                                              func NewResponseBuffer(w http.ResponseWriter) *ResponseBuffer

                                                                                                                                                NewResponseBuffer returns a ResponseBuffer object initialized with the headers of 'w', an object that implements “http.ResponseWriter“. Objects returned using this function are pooled to save resources. See also: ResponseBuffer.Free

                                                                                                                                                func (*ResponseBuffer) Flush

                                                                                                                                                func (rb *ResponseBuffer) Flush(w http.ResponseWriter) (int64, error)

                                                                                                                                                  Flush sends the headers, status and buffered content to 'w', an http.ResponseWriter object. The ResponseBuffer object is freed after this call. Returns the number of bytes written to 'w' or error on failure. See also: ResponseBuffer.Free, ResponseBuffer.FlushHeader, ResponseBuffer.WriteTo

                                                                                                                                                  func (*ResponseBuffer) FlushHeader

                                                                                                                                                  func (rb *ResponseBuffer) FlushHeader(w http.ResponseWriter)

                                                                                                                                                    FlushHeader sends the buffered headers and status, but not the content, to 'w' an object that implements http.ResponseWriter. This function won't free the buffer or reset the headers but it will send the status using ResponseWriter.WriterHeader, if status was saved before. See also: ResponseBuffer.Flush, ResponseBuffer.WriteHeader

                                                                                                                                                    func (*ResponseBuffer) Free

                                                                                                                                                    func (rb *ResponseBuffer) Free()

                                                                                                                                                      Free frees a ResponseBuffer object returning it back to the usage pool. Use with “defer“ after calling NewResponseBuffer if WriteTo or Flush arent used. The values of the ResponseBuffer are reset and must be re-initialized.

                                                                                                                                                      func (*ResponseBuffer) Header

                                                                                                                                                      func (rb *ResponseBuffer) Header() http.Header

                                                                                                                                                        Header returns the buffered header map.

                                                                                                                                                        func (*ResponseBuffer) Status

                                                                                                                                                        func (rb *ResponseBuffer) Status() int

                                                                                                                                                          Status returns the last known status code saved. If no status has been set, it returns http.StatusOK which is the default in “net/http“.

                                                                                                                                                          func (*ResponseBuffer) Write

                                                                                                                                                          func (rb *ResponseBuffer) Write(b []byte) (int, error)

                                                                                                                                                            Write writes the data to the buffer. Returns the number of bytes written or error on failure.

                                                                                                                                                            func (*ResponseBuffer) WriteHeader

                                                                                                                                                            func (rb *ResponseBuffer) WriteHeader(code int)

                                                                                                                                                              WriteHeader stores the value of status code.

                                                                                                                                                              func (*ResponseBuffer) WriteTo

                                                                                                                                                              func (rb *ResponseBuffer) WriteTo(w io.Writer) (int64, error)

                                                                                                                                                                WriteTo implements io.WriterTo. It sends the buffer, except headers, to any object that implements io.Writer. The buffer will be empty after this call. Returns the number of bytes written or error on failure.

                                                                                                                                                                type Router

                                                                                                                                                                type Router interface {
                                                                                                                                                                	// FindHandler should match request parameters to an existing resource handler and
                                                                                                                                                                	// return it. If no match is found, it should return an StatusError error which will
                                                                                                                                                                	// be sent to the requester. The default errors ErrRouteNotFound and
                                                                                                                                                                	// ErrRouteBadMethod cover the default cases.
                                                                                                                                                                	FindHandler(*Context) (HandlerFunc, error)
                                                                                                                                                                
                                                                                                                                                                	// AddRoute is used to create new routes to resources. It expects the HTTP method
                                                                                                                                                                	// (GET, POST, ...) followed by the resource path and the handler function.
                                                                                                                                                                	AddRoute(string, string, HandlerFunc)
                                                                                                                                                                
                                                                                                                                                                	// PathMethods returns a comma-separated list of HTTP methods that are matched
                                                                                                                                                                	// to a path. It will do PSE expansion.
                                                                                                                                                                	PathMethods(string) string
                                                                                                                                                                }

                                                                                                                                                                  Router defines the routing system. Objects that implement it have functions that add routes, find a handle to resources and provide information about routes.

                                                                                                                                                                  Relax's default router is trieRegexpRouter. It takes full routes, with HTTP method and path, and inserts them in a trie that can use regular expressions to match individual path segments.

                                                                                                                                                                  PSE: trieRegexpRouter's path segment expressions (PSE) are match strings that are pre-compiled as regular expressions. PSE's provide a simple layer of security when accepting values from the path. Each PSE is made out of a {type:varname} format, where type is the expected type for a value and varname is the name to give the variable that matches the value.

                                                                                                                                                                  "{word:varname}" // matches any word; alphanumeric and underscore.
                                                                                                                                                                  
                                                                                                                                                                  "{uint:varname}" // matches an unsigned integer.
                                                                                                                                                                  
                                                                                                                                                                  "{int:varname}" // matches a signed integer.
                                                                                                                                                                  
                                                                                                                                                                  "{float:varname}" // matches a floating-point number in decimal notation.
                                                                                                                                                                  
                                                                                                                                                                  "{date:varname}" // matches a date in ISO 8601 format.
                                                                                                                                                                  
                                                                                                                                                                  "{geo:varname}" // matches a geo location as described in RFC 5870
                                                                                                                                                                  
                                                                                                                                                                  "{hex:varname}" // matches a hex number, with optional "0x" prefix.
                                                                                                                                                                  
                                                                                                                                                                  "{varname}" // catch-all; matches anything. it may overlap other matches.
                                                                                                                                                                  
                                                                                                                                                                  "*" // translated into "{wild}"
                                                                                                                                                                  
                                                                                                                                                                  "{re:pattern}" // custom regexp pattern.
                                                                                                                                                                  

                                                                                                                                                                  Some sample routes supported by trieRegexpRouter:

                                                                                                                                                                  GET /api/users/@{word:name}
                                                                                                                                                                  
                                                                                                                                                                  GET /api/users/{uint:id}/*
                                                                                                                                                                  
                                                                                                                                                                  POST /api/users/{uint:id}/profile
                                                                                                                                                                  
                                                                                                                                                                  DELETE /api/users/{date:from}/to/{date:to}
                                                                                                                                                                  
                                                                                                                                                                  GET /api/cities/{geo:location}
                                                                                                                                                                  
                                                                                                                                                                  PUT /api/investments/\${float:dollars}/fund
                                                                                                                                                                  
                                                                                                                                                                  GET /api/todos/month/{re:([0][1-9]|[1][0-2])}
                                                                                                                                                                  

                                                                                                                                                                  Since PSE's are compiled to regexp, care must be taken to escape characters that might break the compilation.

                                                                                                                                                                  type Service

                                                                                                                                                                  type Service struct {
                                                                                                                                                                  	// URI is the full reference URI to the service.
                                                                                                                                                                  	URI *url.URL
                                                                                                                                                                  
                                                                                                                                                                  	// Recovery is a handler function used to intervene after panic occur.
                                                                                                                                                                  	Recovery http.HandlerFunc
                                                                                                                                                                  	// contains filtered or unexported fields
                                                                                                                                                                  }

                                                                                                                                                                    Service contains all the information about the service and resources handled. Specifically, the routing, encoding and service filters.

                                                                                                                                                                    func NewService

                                                                                                                                                                    func NewService(uri string, entities ...interface{}) *Service

                                                                                                                                                                      NewService returns a new Service that can serve resources.

                                                                                                                                                                      'uri' is the URI to this service, it should be an absolute URI but not required. If an existing path is specified, the last path is used. 'entities' is an optional value that contains a list of Filter, Encoder, Router objects that are assigned at the service-level; the same as Service.Use().

                                                                                                                                                                      myservice := NewService("https://api.codehack.com/v1", &FilterETag{})
                                                                                                                                                                      

                                                                                                                                                                      This function will panic if it can't parse 'uri'.

                                                                                                                                                                      func (*Service) Adapter

                                                                                                                                                                      func (svc *Service) Adapter() http.HandlerFunc

                                                                                                                                                                        Adapter creates a new request context, sets default HTTP headers, creates the link-chain of service filters, then passes the request to content negotiation. Also, it uses a recovery function for panics, that responds with HTTP status 500-"Internal Server Error" and logs the event.

                                                                                                                                                                        Info passed down by the adapter:

                                                                                                                                                                        ctx.Info.Get("context.start_time")  // Time when request started, as string time.Time.
                                                                                                                                                                        ctx.Info.Get("context.request_id")  // Unique or user-supplied request ID.
                                                                                                                                                                        

                                                                                                                                                                        Returns an http.HandlerFunc function that can be used with http.Handle.

                                                                                                                                                                        func (*Service) Content

                                                                                                                                                                        func (svc *Service) Content(next HandlerFunc) HandlerFunc

                                                                                                                                                                          Content does content negotiation to select the supported representations for the request and response. The default representation uses media type "application/json". If new media types are available to the service, a client can request it via the Accept header. The format of the Accept header uses the following vendor extension:

                                                                                                                                                                          Accept: application/vnd.relax+{subtype}; version=XX; lang=YY
                                                                                                                                                                          

                                                                                                                                                                          The values for {subtype}, {version} and {lang} are optional. They correspond in order; to media subtype, content version and, language. If any value is missing or unsupported the default values are used. If a request Accept header is not using the vendor extension, the default values are used:

                                                                                                                                                                          Accept: application/vnd.relax+json; version="current"; lang="en"
                                                                                                                                                                          

                                                                                                                                                                          When Accept indicates all media types "*&#5C;*", the media subtype can be requested through the URL path's extension. If the service doesn't support the media encoding, then it will respond with an HTTP error code.

                                                                                                                                                                          GET /api/v1/tickets.xml
                                                                                                                                                                          GET /company/users/123.json
                                                                                                                                                                          

                                                                                                                                                                          Note that the extension should be appended to a collection or a resource item. The extension is removed before the request is dispatched to the routing engine.

                                                                                                                                                                          If the request header Accept-Language is found, the value for content language is automatically set to that. The underlying application should use this to construct a proper respresentation in that language.

                                                                                                                                                                          Content passes down the following info to filters:

                                                                                                                                                                          ctx.Info.Get("content.encoding") // media type used for encoding
                                                                                                                                                                          ctx.Info.Get("content.decoding") // Type used in payload requests POST/PUT/PATCH
                                                                                                                                                                          ctx.Info.Get("content.version")  // requested version, or "current"
                                                                                                                                                                          ctx.Info.Get("content.language") // requested language, or "en_US"
                                                                                                                                                                          

                                                                                                                                                                          Requests and responses can use mixed representations if the service supports the media types.

                                                                                                                                                                          See also, http://tools.ietf.org/html/rfc5646; tags to identify languages.

                                                                                                                                                                          func (*Service) Handler

                                                                                                                                                                          func (svc *Service) Handler() (string, http.Handler)

                                                                                                                                                                            Handler is a function that returns the values needed by http.Handle to handle a path. This allows Relax services to work along http.ServeMux. It returns the path of the service and the Service.Adapter handler.

                                                                                                                                                                            // restrict requests to host "api.codehack.com"
                                                                                                                                                                            myAPI := relax.NewService("http://api.codehack.com/v1")
                                                                                                                                                                            
                                                                                                                                                                            // ... your resources might go here ...
                                                                                                                                                                            
                                                                                                                                                                            // maps "api.codehack.com/v1" in http.ServeMux
                                                                                                                                                                            http.Handle(myAPI.Handler())
                                                                                                                                                                            
                                                                                                                                                                            // map other resources independently
                                                                                                                                                                            http.Handle("/docs", DocsHandler)
                                                                                                                                                                            http.Handle("/help", HelpHandler)
                                                                                                                                                                            http.Handle("/blog", BlogHandler)
                                                                                                                                                                            
                                                                                                                                                                            log.Fatal(http.ListenAndServe(":8000", nil))
                                                                                                                                                                            

                                                                                                                                                                            Using this function with http.Handle is recommended over using Service.Adapter directly. You benefit from the security options built-in to http.ServeMux; like restricting to specific hosts, clean paths and separate path matching.

                                                                                                                                                                            func (*Service) Logf

                                                                                                                                                                            func (svc *Service) Logf(format string, args ...interface{})

                                                                                                                                                                              Logf prints an log entry to logger if set, or stdlog if nil. Based on the unexported function logf() in “net/http“.

                                                                                                                                                                              func (*Service) Logger

                                                                                                                                                                              func (svc *Service) Logger() Logger

                                                                                                                                                                                Logger returns the service logging system.

                                                                                                                                                                                func (*Service) Options

                                                                                                                                                                                func (svc *Service) Options() *ServiceOptions

                                                                                                                                                                                  Options returns the options available from this service. This information is useful when creating OPTIONS routes.

                                                                                                                                                                                  func (*Service) Resource

                                                                                                                                                                                  func (svc *Service) Resource(collection Resourcer, filters ...Filter) *Resource

                                                                                                                                                                                    Resource creates a new Resource object within a Service, and returns it. It will add an OPTIONS route that replies with an Allow header listing the methods available. Also, it will create a GET route to the handler in Resourcer.Index.

                                                                                                                                                                                    collection is an object that implements the Resourcer interface.

                                                                                                                                                                                    filters are resource-level filters that are ran before a resource handler, but after service-level filters.

                                                                                                                                                                                    This function will panic if it can't determine the name of a collection through reflection.

                                                                                                                                                                                    func (*Service) Router

                                                                                                                                                                                    func (svc *Service) Router() Router

                                                                                                                                                                                      Router returns the service routing engine.

                                                                                                                                                                                      The routing engine is responsible for creating routes (method + path) to service resources, and accessing them for each request. To add new routes you can use this interface directly:

                                                                                                                                                                                      myservice.Router().AddRoute(method, path, handler)
                                                                                                                                                                                      

                                                                                                                                                                                      Any route added directly with AddRoute() must reside under the service URI base path, otherwise it won't work. No checks are made. To find a handler to a request:

                                                                                                                                                                                      h := myservice.Router().FindHandler(ctx)
                                                                                                                                                                                      

                                                                                                                                                                                      This will return the handler for the route in request context 'ctx'.

                                                                                                                                                                                      func (*Service) Run

                                                                                                                                                                                      func (svc *Service) Run(args ...string)

                                                                                                                                                                                        Run will start the service using basic defaults or using arguments supplied. If 'args' is nil, it will start the service on port 8000. If 'args' is not nil, it expects in order: address (host:port), certificate file and key file for TLS.

                                                                                                                                                                                        Run() is equivalent to:

                                                                                                                                                                                        http.Handle(svc.Handler())
                                                                                                                                                                                        http.ListenAndServe(":8000", nil)
                                                                                                                                                                                        

                                                                                                                                                                                        Run(":3000") is equivalent to:

                                                                                                                                                                                        ...
                                                                                                                                                                                        http.ListenAndServe(":3000", nil)
                                                                                                                                                                                        

                                                                                                                                                                                        Run("10.1.1.100:10443", "tls/cert.pem", "tls/key.pem") is eq. to:

                                                                                                                                                                                        ...
                                                                                                                                                                                        http.ListenAndServeTLS("10.1.1.100:10443", "tls/cert.pem", "tls/key.pem", nil)
                                                                                                                                                                                        

                                                                                                                                                                                        If the key file is missing, TLS is not used.

                                                                                                                                                                                        func (*Service) ServeHTTP

                                                                                                                                                                                        func (svc *Service) ServeHTTP(w http.ResponseWriter, r *http.Request)

                                                                                                                                                                                          ServeHTTP implements http.HandlerFunc. It lets the Service route all requests directly, bypassing http.ServeMux.

                                                                                                                                                                                          myService := relax.NewService("/")
                                                                                                                                                                                          // ... your resources might go here ...
                                                                                                                                                                                          
                                                                                                                                                                                          // your service has complete handling of all the routes.
                                                                                                                                                                                          log.Fatal(http.ListenAndServe(":8000", myService))
                                                                                                                                                                                          

                                                                                                                                                                                          Using Service.Handler has more benefits than this method.

                                                                                                                                                                                          func (*Service) Uptime

                                                                                                                                                                                          func (svc *Service) Uptime() int

                                                                                                                                                                                            Uptime returns the service uptime in seconds.

                                                                                                                                                                                            func (*Service) Use

                                                                                                                                                                                            func (svc *Service) Use(entities ...interface{}) *Service

                                                                                                                                                                                              Use adds one or more encoders, filters and/or router to the service. Returns the service itself, for chaining.

                                                                                                                                                                                              To add new filters, assign an object that implements the Filter interface. Filters are not replaced or updated, only appended to the service list. Examples:

                                                                                                                                                                                              myservice.Use(&FilterCORS{})
                                                                                                                                                                                              myservice.Use(&FilterSecurity{CacheDisable: true})
                                                                                                                                                                                              

                                                                                                                                                                                              To add encoders, assign an object that implements the Encoder interface. Encoders will replace any matching existing encoder(s), and they will be discoverable on the service encoders map.

                                                                                                                                                                                              newenc := NewEncoderXML() // encoder with default settings
                                                                                                                                                                                              newenc.Indented = true    // change a setting
                                                                                                                                                                                              myservice.Use(newenc)     // assign it to service
                                                                                                                                                                                              

                                                                                                                                                                                              To change the routing engine, assign an object that implements the Router interface:

                                                                                                                                                                                              myservice.Use(MyFastRouter())
                                                                                                                                                                                              

                                                                                                                                                                                              To change the logging system, assign an object that implements the Logger interface:

                                                                                                                                                                                              // Use the excellent logrus package.
                                                                                                                                                                                              myservice.Use(logrus.New())
                                                                                                                                                                                              
                                                                                                                                                                                              // With advanced usage
                                                                                                                                                                                              log := &logrus.Logger{
                                                                                                                                                                                              	Out: os.Stderr,
                                                                                                                                                                                              	Formatter: new(JSONFormatter),
                                                                                                                                                                                              	Level: logrus.Debug,
                                                                                                                                                                                              }
                                                                                                                                                                                              myservice.Use(log)
                                                                                                                                                                                              

                                                                                                                                                                                              Any entities that don't implement the required interfaces, will be ignored.

                                                                                                                                                                                              type ServiceOptions

                                                                                                                                                                                              type ServiceOptions struct {
                                                                                                                                                                                              	BaseURI string `json:"href"`
                                                                                                                                                                                              	Media   struct {
                                                                                                                                                                                              		Type     string   `json:"type"`
                                                                                                                                                                                              		Version  string   `json:"version"`
                                                                                                                                                                                              		Language string   `json:"language"`
                                                                                                                                                                                              		Encoders []string `json:"encoders"`
                                                                                                                                                                                              	} `json:"media"`
                                                                                                                                                                                              }

                                                                                                                                                                                                ServiceOptions has a description of the options available for using this service. This is used by the OPTIONS handler.

                                                                                                                                                                                                type StatusError

                                                                                                                                                                                                type StatusError struct {
                                                                                                                                                                                                	// Code is meant for a HTTP status code or any other numeric ID.
                                                                                                                                                                                                	Code int `json:"code"`
                                                                                                                                                                                                
                                                                                                                                                                                                	// Message is the default error message used in logs.
                                                                                                                                                                                                	Message string `json:"message"`
                                                                                                                                                                                                
                                                                                                                                                                                                	// Details can be any data structure that gives more information about the
                                                                                                                                                                                                	// error.
                                                                                                                                                                                                	Details interface{} `json:"details,omitempty"`
                                                                                                                                                                                                }

                                                                                                                                                                                                  StatusError is an error with a HTTP Status code. It allows errors to be complete and uniform.

                                                                                                                                                                                                  func (*StatusError) Error

                                                                                                                                                                                                  func (e *StatusError) Error() string

                                                                                                                                                                                                    StatusError implements the error interface.

                                                                                                                                                                                                    Notes

                                                                                                                                                                                                    Bugs

                                                                                                                                                                                                    Directories

                                                                                                                                                                                                    Path Synopsis