mirror of
https://github.com/kataras/iris.git
synced 2026-01-10 21:45:57 +00:00
SetImmutable for sessions and context's values. https://github.com/iris-contrib/community-board/issues/5
New package "memstore" created, read it to see how I made it. Former-commit-id: 9edc344b938786b2ef68defec03c44259a2d539c
This commit is contained in:
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/russross/blackfriday"
|
||||
|
||||
"github.com/kataras/iris/core/errors"
|
||||
"github.com/kataras/iris/core/memstore"
|
||||
"github.com/kataras/iris/sessions"
|
||||
)
|
||||
|
||||
@@ -73,6 +74,64 @@ func (u UnmarshalerFunc) Unmarshal(data []byte, v interface{}) error {
|
||||
return u(data, v)
|
||||
}
|
||||
|
||||
// RequestParams is a key string - value string storage which context's request params should implement.
|
||||
// RequestValues is for communication between middleware, RequestParams cannot be changed, are setted at the routing
|
||||
// time, stores the dynamic named parameters, can be empty if the route is static.
|
||||
type RequestParams struct {
|
||||
store memstore.Store
|
||||
}
|
||||
|
||||
// Set shouldn't be used as a local storage, context's values store
|
||||
// is the local storage, not params.
|
||||
func (r *RequestParams) Set(key, value string) {
|
||||
r.store.Set(key, value)
|
||||
}
|
||||
|
||||
// Visit accepts a visitor which will be filled
|
||||
// by the key-value params.
|
||||
func (r *RequestParams) Visit(visitor func(key string, value interface{})) {
|
||||
r.store.Visit(visitor)
|
||||
}
|
||||
|
||||
// Get returns a path parameter's value based on its route's dynamic path key.
|
||||
func (r RequestParams) Get(key string) string {
|
||||
return r.store.GetString(key)
|
||||
}
|
||||
|
||||
// GetInt returns the param's value as int, based on its key.
|
||||
func (r RequestParams) GetInt(key string) (int, error) {
|
||||
return r.store.GetInt(key)
|
||||
}
|
||||
|
||||
// GetInt64 returns the user's value as int64, based on its key.
|
||||
func (r RequestParams) GetInt64(key string) (int64, error) {
|
||||
return r.store.GetInt64(key)
|
||||
}
|
||||
|
||||
// GetDecoded returns the url-query-decoded user's value based on its key.
|
||||
func (r RequestParams) GetDecoded(key string) string {
|
||||
return DecodeQuery(DecodeQuery(r.Get(key)))
|
||||
}
|
||||
|
||||
// GetIntUnslashed same as Get but it removes the first slash if found.
|
||||
// Usage: Get an id from a wildcard path.
|
||||
//
|
||||
// Returns -1 with an error if the parameter couldn't be found.
|
||||
func (r RequestParams) GetIntUnslashed(key string) (int, error) {
|
||||
v := r.Get(key)
|
||||
if v != "" {
|
||||
if len(v) > 1 {
|
||||
if v[0] == '/' {
|
||||
v = v[1:]
|
||||
}
|
||||
}
|
||||
return strconv.Atoi(v)
|
||||
|
||||
}
|
||||
|
||||
return -1, memstore.ErrIntParse.Format(v)
|
||||
}
|
||||
|
||||
// Context is the midle-man server's "object" for the clients.
|
||||
//
|
||||
// A New context is being acquired from a sync.Pool on each connection.
|
||||
@@ -163,9 +222,7 @@ type Context interface {
|
||||
// Params returns the current url's named parameters key-value storage.
|
||||
// Named path parameters are being saved here.
|
||||
// This storage, as the whole Context, is per-request lifetime.
|
||||
Params() RequestParams
|
||||
// SetParams sets/or/overrides the request's url named parameters key-value storage.
|
||||
SetParams(RequestParams)
|
||||
Params() *RequestParams
|
||||
|
||||
// Values returns the current "user" storage.
|
||||
// Named path parameters and any optional data can be saved here.
|
||||
@@ -173,7 +230,7 @@ type Context interface {
|
||||
//
|
||||
// You can use this function to Set and Get local values
|
||||
// that can be used to share information between handlers and middleware.
|
||||
Values() *RequestValues
|
||||
Values() *memstore.Store
|
||||
// Translate is the i18n (localization) middleware's function,
|
||||
// it calls the Get("translate") to return the translated value.
|
||||
//
|
||||
@@ -684,8 +741,8 @@ type context struct {
|
||||
// the original http.Request
|
||||
request *http.Request
|
||||
// the local key-value storage
|
||||
params RequestParams // url named parameters
|
||||
values RequestValues // generic storage, middleware communication
|
||||
params RequestParams // url named parameters
|
||||
values memstore.Store // generic storage, middleware communication
|
||||
|
||||
// the underline application framework
|
||||
framework Application
|
||||
@@ -720,7 +777,7 @@ func (ctx *context) BeginRequest(w http.ResponseWriter, r *http.Request) {
|
||||
ctx.handlers = nil // will be filled by router.Serve/HTTP
|
||||
ctx.session = nil // >> >> by sessions.Session()
|
||||
ctx.values = ctx.values[0:0] // >> >> by context.Values().Set
|
||||
ctx.params = ctx.params[0:0]
|
||||
ctx.params.store = ctx.params.store[0:0]
|
||||
ctx.request = r
|
||||
ctx.currentHandlerIndex = 0
|
||||
ctx.writer = AcquireResponseWriter()
|
||||
@@ -861,13 +918,8 @@ func (ctx *context) IsStopped() bool {
|
||||
// Params returns the current url's named parameters key-value storage.
|
||||
// Named path parameters are being saved here.
|
||||
// This storage, as the whole context, is per-request lifetime.
|
||||
func (ctx *context) Params() RequestParams {
|
||||
return ctx.params
|
||||
}
|
||||
|
||||
// SetParams sets/or/overrides the request's url named parameters key-value storage.
|
||||
func (ctx *context) SetParams(params RequestParams) {
|
||||
ctx.params = params
|
||||
func (ctx *context) Params() *RequestParams {
|
||||
return &ctx.params
|
||||
}
|
||||
|
||||
// Values returns the current "user" storage.
|
||||
@@ -876,7 +928,7 @@ func (ctx *context) SetParams(params RequestParams) {
|
||||
//
|
||||
// You can use this function to Set and Get local values
|
||||
// that can be used to share information between handlers and middleware.
|
||||
func (ctx *context) Values() *RequestValues {
|
||||
func (ctx *context) Values() *memstore.Store {
|
||||
return &ctx.values
|
||||
}
|
||||
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/kataras/iris/core/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
// RequestValue is the entry of the context storage RequestValues - .Values()
|
||||
RequestValue struct {
|
||||
key string
|
||||
value interface{}
|
||||
}
|
||||
|
||||
// RequestValues is just a key-value storage which context's request values should implement.
|
||||
RequestValues []RequestValue
|
||||
)
|
||||
|
||||
// RequestValuesReadOnly the request values with read-only access.
|
||||
type RequestValuesReadOnly struct {
|
||||
RequestValues
|
||||
}
|
||||
|
||||
// Set does nothing.
|
||||
func (r RequestValuesReadOnly) Set(string, interface{}) {}
|
||||
|
||||
// Set sets a value to the key-value context storage, can be familiar as "User Values".
|
||||
func (r *RequestValues) Set(key string, value interface{}) {
|
||||
args := *r
|
||||
n := len(args)
|
||||
for i := 0; i < n; i++ {
|
||||
kv := &args[i]
|
||||
if kv.key == key {
|
||||
kv.value = value
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c := cap(args)
|
||||
if c > n {
|
||||
args = args[:n+1]
|
||||
kv := &args[n]
|
||||
kv.key = key
|
||||
kv.value = value
|
||||
*r = args
|
||||
return
|
||||
}
|
||||
|
||||
kv := RequestValue{}
|
||||
kv.key = key
|
||||
kv.value = value
|
||||
*r = append(args, kv)
|
||||
}
|
||||
|
||||
// Get returns the user's value based on its key.
|
||||
func (r *RequestValues) Get(key string) interface{} {
|
||||
args := *r
|
||||
n := len(args)
|
||||
for i := 0; i < n; i++ {
|
||||
kv := &args[i]
|
||||
if kv.key == key {
|
||||
return kv.value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Visit accepts a visitor which will be filled
|
||||
// by the key-value objects, the caller should not try to change the underline values.
|
||||
func (r *RequestValues) Visit(visitor func(key string, value interface{})) {
|
||||
args := *r
|
||||
for i, n := 0, len(args); i < n; i++ {
|
||||
visitor(args[i].key, args[i].value)
|
||||
}
|
||||
}
|
||||
|
||||
// GetString returns the user's value as string, based on its key.
|
||||
func (r *RequestValues) GetString(key string) string {
|
||||
if v, ok := r.Get(key).(string); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
var errIntParse = errors.New("unable to find or parse the integer, found: %#v")
|
||||
|
||||
// GetInt returns the user's value as int, based on its key.
|
||||
func (r *RequestValues) GetInt(key string) (int, error) {
|
||||
v := r.Get(key)
|
||||
if vint, ok := v.(int); ok {
|
||||
return vint, nil
|
||||
} else if vstring, sok := v.(string); sok {
|
||||
return strconv.Atoi(vstring)
|
||||
}
|
||||
|
||||
return -1, errIntParse.Format(v)
|
||||
}
|
||||
|
||||
// GetInt64 returns the user's value as int64, based on its key.
|
||||
func (r *RequestValues) GetInt64(key string) (int64, error) {
|
||||
return strconv.ParseInt(r.GetString(key), 10, 64)
|
||||
}
|
||||
|
||||
// Reset clears all the request values.
|
||||
func (r *RequestValues) Reset() {
|
||||
*r = (*r)[0:0]
|
||||
}
|
||||
|
||||
// ReadOnly returns a new request values with read-only access.
|
||||
func (r *RequestValues) ReadOnly() RequestValuesReadOnly {
|
||||
args := *r
|
||||
values := make(RequestValues, len(args))
|
||||
copy(values, args)
|
||||
return RequestValuesReadOnly{values}
|
||||
}
|
||||
|
||||
// Len returns the full length of the values.
|
||||
func (r *RequestValues) Len() int {
|
||||
args := *r
|
||||
return len(args)
|
||||
}
|
||||
|
||||
// RequestParam is the entry of RequestParams, request's url named parameters are storaged here.
|
||||
type RequestParam struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
// RequestParams is a key string - value string storage which context's request params should implement.
|
||||
// RequestValues is for communication between middleware, RequestParams cannot be changed, are setted at the routing
|
||||
// time, stores the dynamic named parameters, can be empty if the route is static.
|
||||
type RequestParams []RequestParam
|
||||
|
||||
// Get returns the param's value based on its key.
|
||||
func (r RequestParams) Get(key string) string {
|
||||
for _, p := range r {
|
||||
if p.Key == key {
|
||||
return p.Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Visit accepts a visitor which will be filled
|
||||
// by the key and value.
|
||||
// The caller should not try to change the underline values.
|
||||
func (r RequestParams) Visit(visitor func(key string, value string)) {
|
||||
for i, n := 0, len(r); i < n; i++ {
|
||||
visitor(r[i].Key, r[i].Value)
|
||||
}
|
||||
}
|
||||
|
||||
// GetInt returns the user's value as int, based on its key.
|
||||
func (r RequestParams) GetInt(key string) (int, error) {
|
||||
v := r.Get(key)
|
||||
return strconv.Atoi(v)
|
||||
}
|
||||
|
||||
// GetInt64 returns the user's value as int64, based on its key.
|
||||
func (r RequestParams) GetInt64(key string) (int64, error) {
|
||||
return strconv.ParseInt(r.Get(key), 10, 64)
|
||||
}
|
||||
|
||||
// GetDecoded returns the url-query-decoded user's value based on its key.
|
||||
func (r RequestParams) GetDecoded(key string) string {
|
||||
return DecodeQuery(DecodeQuery(r.Get(key)))
|
||||
}
|
||||
|
||||
// GetIntUnslashed same as Get but it removes the first slash if found.
|
||||
// Usage: Get an id from a wildcard path.
|
||||
//
|
||||
// Returns -1 with an error if the parameter couldn't be found.
|
||||
func (r RequestParams) GetIntUnslashed(key string) (int, error) {
|
||||
v := r.Get(key)
|
||||
if v != "" {
|
||||
if len(v) > 1 {
|
||||
if v[0] == '/' {
|
||||
v = v[1:]
|
||||
}
|
||||
}
|
||||
return strconv.Atoi(v)
|
||||
|
||||
}
|
||||
|
||||
return -1, errIntParse.Format(v)
|
||||
}
|
||||
|
||||
// Len returns the full length of the params.
|
||||
func (r RequestParams) Len() int {
|
||||
return len(r)
|
||||
}
|
||||
Reference in New Issue
Block a user