Documentation ¶
Overview ¶
Example ¶
Example shows an injection chain handling a single endpoint using nject, nape, and nvelope.
package main import ( "errors" "fmt" "io/ioutil" "net/http/httptest" "strings" "github.com/muir/nchi" "github.com/muir/nvelope" ) type PostBodyModel struct { Use string `json:"use"` Exported string `json:"exported"` Names string `json:"names"` } type ExampleRequestBundle struct { Request PostBodyModel `nvelope:"model"` With *string `nvelope:"path,name=with"` Parameters int64 `nvelope:"path,name=parameters"` Friends []int `nvelope:"query,name=friends"` ContentType string `nvelope:"header,name=Content-Type"` } type ExampleResponse struct { Stuff string `json:"stuff,omitempty"` Here string `json:"here,omitempty"` } func HandleExampleEndpoint(req ExampleRequestBundle) (nvelope.Response, error) { if req.ContentType != "application/json" { return nil, errors.New("content type must be application/json") } switch req.Parameters { case 666: panic("something is not right") case 100: return nil, nil default: return ExampleResponse{ Stuff: *req.With, }, nil } } func Service(r *nchi.Mux) { r.Use( // order matters and this is a correct order nvelope.NoLogger, nvelope.InjectWriter, nvelope.EncodeJSON, nvelope.CatchPanic, nvelope.Nil204, nvelope.ReadBody, nchi.DecodeJSON, ) r.Post("/a/path/:with/:parameters", HandleExampleEndpoint, ) } // Example shows an injection chain handling a single endpoint using nject, // nape, and nvelope. func main() { r := nchi.NewRouter() Service(r) ts := httptest.NewServer(r) client := ts.Client() doPost := func(url string, body string) { // nolint:noctx res, err := client.Post(ts.URL+url, "application/json", strings.NewReader(body)) if err != nil { fmt.Println("response error:", err) return } b, err := ioutil.ReadAll(res.Body) if err != nil { fmt.Println("read error:", err) return } res.Body.Close() fmt.Println(res.StatusCode, "->"+string(b)) } doPost("/a/path/joe/37", `{"Use":"yeah","Exported":"uh hu"}`) doPost("/a/path/joe/100", `{"Use":"yeah","Exported":"uh hu"}`) doPost("/a/path/joe/38", `invalid json`) doPost("/a/path/joe/666", `{"Use":"yeah","Exported":"uh hu"}`) }
Output: 200 ->{"stuff":"joe"} 204 -> 400 ->nchi_test.ExampleRequestBundle model: Could not decode application/json into nchi_test.PostBodyModel: invalid character 'i' looking for beginning of value 500 ->panic: something is not right
Index ¶
- Variables
- type Endpoint
- type Mux
- func (mux *Mux) Bind() error
- func (mux *Mux) Delete(path string, providers ...interface{})
- func (mux *Mux) Get(path string, providers ...interface{})
- func (mux *Mux) GlobalOPTIONS(providers ...interface{})
- func (mux *Mux) Group(f func(mux *Mux))
- func (mux *Mux) Head(path string, providers ...interface{})
- func (mux *Mux) Method(method string, path string, providers ...interface{})
- func (mux *Mux) MethodNotAllowed(providers ...interface{})
- func (mux *Mux) NotFound(providers ...interface{})
- func (mux *Mux) Options(path string, providers ...interface{})
- func (mux *Mux) PanicHandler(providers ...interface{})
- func (mux *Mux) Patch(path string, providers ...interface{})
- func (mux *Mux) Post(path string, providers ...interface{})
- func (mux *Mux) Put(path string, providers ...interface{})
- func (mux *Mux) Route(path string, f func(mux *Mux))
- func (mux *Mux) ServeFiles(path string, fs http.FileSystem)
- func (mux *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (mux *Mux) Use(providers ...interface{})
- func (mux *Mux) With(providers ...interface{}) *Mux
- type Option
- type Params
- type RecoverInterface
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DecodeJSON = nvelope.GenerateDecoder( nvelope.WithDecoder("application/json", json.Unmarshal), nvelope.WithDefaultContentType("application/json"), nvelope.WithPathVarsFunction(func(p httprouter.Params) nvelope.RouteVarLookup { return p.ByName }), )
DecodeJSON is is a pre-defined special nject.Provider created with nvelope.GenerateDecoder for decoding JSON requests. Use it with the other features of https://github.com/muir/nvelope . DecodeJSON must be paired with nvelope.ReadBody to actually decode JSON.
var DecodeXML = nvelope.GenerateDecoder( nvelope.WithDecoder("application/xml", xml.Unmarshal), nvelope.WithDefaultContentType("application/xml"), nvelope.WithPathVarsFunction(func(p httprouter.Params) nvelope.RouteVarLookup { return p.ByName }), )
DecodeXML is is a pre-defined special nject.Provider created with nvelope.GenerateDecoder for decoding XML requests.Use it with the other features of https://github.com/muir/nvelope . DecodeXML must be paired with nvelope.ReadBody to actually decode XML.
Functions ¶
This section is empty.
Types ¶
type Endpoint ¶ added in v0.1.0
type Endpoint string
Endpoint is a type that handlers can accepte as an input. It will be the combined URL path without path variables substituted. If you have
mux.Get("/thing/:thingID", handler)
and handler takes an nchi.Endpoint argument, and there is a request for http://example.com/thing/3802, then the nchi.Endpoint will be "/thing/:thingID".
type Mux ¶
type Mux struct {
// contains filtered or unexported fields
}
func (*Mux) Bind ¶
Bind validates that the injection chains for all routes are valid. If any are not, an error is returned. If you do not call bind, and there are any invalid injection chains, then routes will panic when used.
func (*Mux) GlobalOPTIONS ¶
func (mux *Mux) GlobalOPTIONS(providers ...interface{})
GlobalOPTIONS sets a handler that is called on automatically on OPTIONS requests. The handler is only called if HandleOPTIONS is true and no OPTIONS handler for the specific path was set. The "Allowed" header is set before calling the handler.
Only the first GobalOPTIONS call counts.
func (*Mux) Group ¶
Group establishes a new Mux at the current path but does not inherit any middlewhere.
func (*Mux) Method ¶
Method registers an endpoint handler at the new path (combined with the current path) using a combination of inherited middleware and the providers here.
func (*Mux) MethodNotAllowed ¶
func (mux *Mux) MethodNotAllowed(providers ...interface{})
MethodNotAllowed sets a handler which is called when a request cannot be routed and HandleMethodNotAllowed is true. If it is not set, http.Error with http.StatusMethodNotAllowed is used. The "Allow" header with allowed request methods is set before the handler is called.
Only the first MethodNotFound call counts.
func (*Mux) NotFound ¶
func (mux *Mux) NotFound(providers ...interface{})
NotFound sets a handler which is called when no matching route is found. If it is not set, http.NotFound is used.
Only the first NotFound call counts.
func (*Mux) PanicHandler ¶
func (mux *Mux) PanicHandler(providers ...interface{})
PanicHandler sets a handler to handle panics recovered from http handlers. It should be used to generate a error page and return the http error code 500 (Internal Server Error). The handler can be used to keep your server from crashing because of unrecovered panics.
The type RecoverInterface can be used to receive the interface{} that is returned from recover().
Alternatively, use the nvelope.CatchPanic middleware to catch panics.
Only the first PanicHandler call counts.
func (*Mux) Route ¶
Route establishes a new Mux at a new path (combined with the current path context).
func (*Mux) ServeFiles ¶
func (mux *Mux) ServeFiles(path string, fs http.FileSystem)
ServeFiles serves files from the given file system root. The path must end with "/*filepath", files are then served from the local path /defined/root/dir/*filepath. For example if root is "/etc" and *filepath is "passwd", the local file "/etc/passwd" would be served. Internally a http.FileServer is used, therefore http.NotFound is used instead of the Router's NotFound handler. To use the operating system's file system implementation, use http.Dir:
Currently, ServeFiles does not use any middleware. That may change in a future release.
func (*Mux) Use ¶
func (mux *Mux) Use(providers ...interface{})
Use adds additional http middleware (implementing the http.Handler interface) or nject-style providers to the current handler context. These middleware and providers will be injected into the handler chain for any downstream endpoints that are defined after the call to Use.
type Option ¶
type Option func(*rtr)
func WithHandleMethodNotAllowed ¶
WithHandleMethodNotAllowed enables/disables, checking if another method is allowed for the current route, if the current request can not be routed. If this is the case, the request is answered with 'Method Not Allowed' and HTTP status code 405. If no other Method is allowed, the request is delegated to the NotFound handler. The default is: enabled..
func WithHandleOPTIONS ¶
WIthHandleOPTIONS enables/disables automatic replies to OPTIONS requests. Custom OPTIONS handlers take priority over automatic replies. The default is: enabled.
func WithRedirectFixedPath ¶
WithRedirectFixedPath enables/disables trying to fix the current request path, if no handle is registered for it. First superfluous path elements like ../ or // are removed. Afterwards the router does a case-insensitive lookup of the cleaned path. If a handle can be found for this route, the router makes a redirection to the corrected path with status code 301 for GET requests and 307 for all other request methods. For example /FOO and /..//Foo could be redirected to /foo. RedirectTrailingSlash is independent of this option. The default is: enabled.
func WithRedirectTrailingSlash ¶
WithRedirectTrailingSlash enables/disables automatic redirection if the current route can't be matched but a handler for the path with (without) the trailing slash exists. For example if /foo/ is requested but a route only exists for /foo, the client is redirected to /foo with http status code 301 for GET requests and 307 for all other request methods. The default is: enabled.
type Params ¶
type Params = httprouter.Params
type RecoverInterface ¶
type RecoverInterface interface{}