Files
casecmp/vendor/github.com/qiangxue/fasthttp-routing/context.go
2017-03-30 01:09:55 +01:00

127 lines
4.2 KiB
Go

// Copyright 2016 Qiang Xue. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package routing
import (
"fmt"
"github.com/valyala/fasthttp"
)
// SerializeFunc serializes the given data of arbitrary type into a byte array.
type SerializeFunc func(data interface{}) ([]byte, error)
// Context represents the contextual data and environment while processing an incoming HTTP request.
type Context struct {
*fasthttp.RequestCtx
Serialize SerializeFunc // the function serializing the given data of arbitrary type into a byte array.
router *Router
pnames []string // list of route parameter names
pvalues []string // list of parameter values corresponding to pnames
data map[string]interface{} // data items managed by Get and Set
index int // the index of the currently executing handler in handlers
handlers []Handler // the handlers associated with the current route
}
// Router returns the Router that is handling the incoming HTTP request.
func (c *Context) Router() *Router {
return c.router
}
// Param returns the named parameter value that is found in the URL path matching the current route.
// If the named parameter cannot be found, an empty string will be returned.
func (c *Context) Param(name string) string {
for i, n := range c.pnames {
if n == name {
return c.pvalues[i]
}
}
return ""
}
// Get returns the named data item previously registered with the context by calling Set.
// If the named data item cannot be found, nil will be returned.
func (c *Context) Get(name string) interface{} {
return c.data[name]
}
// Set stores the named data item in the context so that it can be retrieved later.
func (c *Context) Set(name string, value interface{}) {
if c.data == nil {
c.data = make(map[string]interface{})
}
c.data[name] = value
}
// Next calls the rest of the handlers associated with the current route.
// If any of these handlers returns an error, Next will return the error and skip the following handlers.
// Next is normally used when a handler needs to do some postprocessing after the rest of the handlers
// are executed.
func (c *Context) Next() error {
c.index++
for n := len(c.handlers); c.index < n; c.index++ {
if err := c.handlers[c.index](c); err != nil {
return err
}
}
return nil
}
// Abort skips the rest of the handlers associated with the current route.
// Abort is normally used when a handler handles the request normally and wants to skip the rest of the handlers.
// If a handler wants to indicate an error condition, it should simply return the error without calling Abort.
func (c *Context) Abort() {
c.index = len(c.handlers)
}
// URL creates a URL using the named route and the parameter values.
// The parameters should be given in the sequence of name1, value1, name2, value2, and so on.
// If a parameter in the route is not provided a value, the parameter token will remain in the resulting URL.
// Parameter values will be properly URL encoded.
// The method returns an empty string if the URL creation fails.
func (c *Context) URL(route string, pairs ...interface{}) string {
if r := c.router.routes[route]; r != nil {
return r.URL(pairs...)
}
return ""
}
// WriteData writes the given data of arbitrary type to the response.
// The method calls the Serialize() method to convert the data into a byte array and then writes
// the byte array to the response.
func (c *Context) WriteData(data interface{}) (err error) {
var bytes []byte
if bytes, err = c.Serialize(data); err == nil {
_, err = c.Write(bytes)
}
return
}
// init sets the request and response of the context and resets all other properties.
func (c *Context) init(ctx *fasthttp.RequestCtx) {
c.RequestCtx = ctx
c.data = nil
c.index = -1
c.Serialize = Serialize
}
// Serialize converts the given data into a byte array.
// If the data is neither a byte array nor a string, it will call fmt.Sprint to convert it into a string.
func Serialize(data interface{}) (bytes []byte, err error) {
switch data.(type) {
case []byte:
return data.([]byte), nil
case string:
return []byte(data.(string)), nil
default:
if data != nil {
return []byte(fmt.Sprint(data)), nil
}
}
return nil, nil
}