1
0
mirror of https://github.com/kataras/iris.git synced 2026-01-09 13:05:56 +00:00

Publish the new version ✈️ | Look description please!

# FAQ

### Looking for free support?

	http://support.iris-go.com
    https://kataras.rocket.chat/channel/iris

### Looking for previous versions?

    https://github.com/kataras/iris#version

### Should I upgrade my Iris?

Developers are not forced to upgrade if they don't really need it. Upgrade whenever you feel ready.
> Iris uses the [vendor directory](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo) feature, so you get truly reproducible builds, as this method guards against upstream renames and deletes.

**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
For further installation support, please click [here](http://support.iris-go.com/d/16-how-to-install-iris-web-framework).

### About our new home page
    http://iris-go.com

Thanks to [Santosh Anand](https://github.com/santoshanand) the http://iris-go.com has been upgraded and it's really awesome!

[Santosh](https://github.com/santoshanand) is a freelancer, he has a great knowledge of nodejs and express js, Android, iOS, React Native, Vue.js etc, if you need a developer to find or create a solution for your problem or task, please contact with him.

The amount of the next two or three donations you'll send they will be immediately transferred to his own account balance, so be generous please!

Read more at https://github.com/kataras/iris/blob/master/HISTORY.md


Former-commit-id: eec2d71bbe011d6b48d2526eb25919e36e5ad94e
This commit is contained in:
kataras
2017-06-03 23:22:52 +03:00
parent 03bcadadec
commit 5e4b63acb2
330 changed files with 35786 additions and 17316 deletions

View File

@@ -0,0 +1,29 @@
## Session databases
Find more databases at [github.com/kataras/go-sessions/sessiondb](https://github.com/kataras/go-sessions/tree/master/sessiondb).
This folder contains only the redis database because the rest (two so far, 'file' and 'leveldb') were created by the Community.
So go [there](https://github.com/kataras/go-sessions/tree/master/sessiondb) and find more about them. `Database` is just an
interface so you're able to `UseDatabase(anyCompatibleDatabase)`. A Database should implement two functions, `Load` and `Update`.
**Database interface**
```go
type Database interface {
Load(string) map[string]interface{}
Update(string, map[string]interface{})
}
```
```go
import (
"...myDatabase"
)
s := New(...)
s.UseDatabase(myDatabase) // <---
app := iris.New()
app.Adapt(s)
app.Listen(":8080")
```

View File

@@ -0,0 +1,91 @@
// Copyright 2017 Gerasimos Maropoulos. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package redis
import (
"bytes"
"encoding/gob"
"github.com/kataras/iris/sessions/sessiondb/redis/service"
)
// Database the redis database for q sessions
type Database struct {
redis *service.Service
}
// New returns a new redis database
func New(cfg ...service.Config) *Database {
return &Database{redis: service.New(cfg...)}
}
// Config returns the configuration for the redis server bridge, you can change them
func (d *Database) Config() *service.Config {
return d.redis.Config
}
// Load loads the values to the underline
func (d *Database) Load(sid string) map[string]interface{} {
values := make(map[string]interface{})
if !d.redis.Connected { //yes, check every first time's session for valid redis connection
d.redis.Connect()
_, err := d.redis.PingPong()
if err != nil {
if err != nil {
// don't use to get the logger, just prin these to the console... atm
///TODO: Find a way to use the iris' defined logger via an optional interface to Database.
// println("Redis Connection error on Connect: " + err.Error())
// println("But don't panic, auto-switching to memory store right now!")
}
}
}
//fetch the values from this session id and copy-> store them
val, err := d.redis.GetBytes(sid)
if err == nil {
// err removed because of previous TODO
DeserializeBytes(val, &values)
}
return values
}
// serialize the values to be stored as strings inside the Redis, we panic at any serialization error here
func serialize(values map[string]interface{}) []byte {
val, err := SerializeBytes(values)
if err != nil {
println("On redisstore.serialize: " + err.Error())
}
return val
}
// Update updates the real redis store
func (d *Database) Update(sid string, newValues map[string]interface{}) {
if len(newValues) == 0 {
go d.redis.Delete(sid)
} else {
go d.redis.Set(sid, serialize(newValues)) //set/update all the values
}
}
// SerializeBytes serializa bytes using gob encoder and returns them
func SerializeBytes(m interface{}) ([]byte, error) {
buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf)
err := enc.Encode(m)
if err == nil {
return buf.Bytes(), nil
}
return nil, err
}
// DeserializeBytes converts the bytes to an object using gob decoder
func DeserializeBytes(b []byte, m interface{}) error {
dec := gob.NewDecoder(bytes.NewBuffer(b))
return dec.Decode(m) //no reference here otherwise doesn't work because of go remote object
}

View File

@@ -0,0 +1,82 @@
// Copyright 2017 Gerasimos Maropoulos. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package service
import (
"time"
"github.com/imdario/mergo"
)
const (
// DefaultRedisNetwork the redis network option, "tcp"
DefaultRedisNetwork = "tcp"
// DefaultRedisAddr the redis address option, "127.0.0.1:6379"
DefaultRedisAddr = "127.0.0.1:6379"
// DefaultRedisIdleTimeout the redis idle timeout option, time.Duration(5) * time.Minute
DefaultRedisIdleTimeout = time.Duration(5) * time.Minute
// DefaultRedisMaxAgeSeconds the redis storage last parameter (SETEX), 31556926.0 (1 year)
DefaultRedisMaxAgeSeconds = 31556926.0 //1 year
)
// Config the redis configuration used inside sessions
type Config struct {
// Network "tcp"
Network string
// Addr "127.0.0.1:6379"
Addr string
// Password string .If no password then no 'AUTH'. Default ""
Password string
// If Database is empty "" then no 'SELECT'. Default ""
Database string
// MaxIdle 0 no limit
MaxIdle int
// MaxActive 0 no limit
MaxActive int
// IdleTimeout time.Duration(5) * time.Minute
IdleTimeout time.Duration
// Prefix "myprefix-for-this-website". Default ""
Prefix string
// MaxAgeSeconds how much long the redis should keep the session in seconds. Default 31556926.0 (1 year)
MaxAgeSeconds int
}
// DefaultConfig returns the default configuration for Redis service
func DefaultConfig() Config {
return Config{
Network: DefaultRedisNetwork,
Addr: DefaultRedisAddr,
Password: "",
Database: "",
MaxIdle: 0,
MaxActive: 0,
IdleTimeout: DefaultRedisIdleTimeout,
Prefix: "",
MaxAgeSeconds: DefaultRedisMaxAgeSeconds,
}
}
// Merge merges the default with the given config and returns the result
func (c Config) Merge(cfg []Config) (config Config) {
if len(cfg) > 0 {
config = cfg[0]
mergo.Merge(&config, c)
} else {
_default := c
config = _default
}
return
}
// MergeSingle merges the default with the given config and returns the result
func (c Config) MergeSingle(cfg Config) (config Config) {
config = cfg
mergo.Merge(&config, c)
return
}

View File

@@ -0,0 +1,276 @@
// Copyright 2017 Gerasimos Maropoulos. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package service
import (
"time"
"github.com/garyburd/redigo/redis"
"github.com/kataras/iris/core/errors"
)
var (
// ErrRedisClosed an error with message 'Redis is already closed'
ErrRedisClosed = errors.New("Redis is already closed")
// ErrKeyNotFound an error with message 'Key $thekey doesn't found'
ErrKeyNotFound = errors.New("Key '%s' doesn't found")
)
// Service the Redis service, contains the config and the redis pool
type Service struct {
// Connected is true when the Service has already connected
Connected bool
// Config the redis config for this redis
Config *Config
pool *redis.Pool
}
// PingPong sends a ping and receives a pong, if no pong received then returns false and filled error
func (r *Service) PingPong() (bool, error) {
c := r.pool.Get()
defer c.Close()
msg, err := c.Do("PING")
if err != nil || msg == nil {
return false, err
}
return (msg == "PONG"), nil
}
// CloseConnection closes the redis connection
func (r *Service) CloseConnection() error {
if r.pool != nil {
return r.pool.Close()
}
return ErrRedisClosed
}
// Set sets to the redis
// key string, value string, you can use utils.Serialize(&myobject{}) to convert an object to []byte
func (r *Service) Set(key string, value []byte) (err error) { // map[interface{}]interface{}) (err error) {
c := r.pool.Get()
defer c.Close()
if err = c.Err(); err != nil {
return
}
_, err = c.Do("SETEX", r.Config.Prefix+key, r.Config.MaxAgeSeconds, value)
return
}
// Get returns value, err by its key
// you can use utils.Deserialize((.Get("yourkey"),&theobject{})
//returns nil and a filled error if something wrong happens
func (r *Service) Get(key string) (interface{}, error) {
c := r.pool.Get()
defer c.Close()
if err := c.Err(); err != nil {
return nil, err
}
redisVal, err := c.Do("GET", r.Config.Prefix+key)
if err != nil {
return nil, err
}
if redisVal == nil {
return nil, ErrKeyNotFound.Format(key)
}
return redisVal, nil
}
// GetBytes returns value, err by its key
// you can use utils.Deserialize((.GetBytes("yourkey"),&theobject{})
//returns nil and a filled error if something wrong happens
func (r *Service) GetBytes(key string) ([]byte, error) {
c := r.pool.Get()
defer c.Close()
if err := c.Err(); err != nil {
return nil, err
}
redisVal, err := c.Do("GET", r.Config.Prefix+key)
if err != nil {
return nil, err
}
if redisVal == nil {
return nil, ErrKeyNotFound.Format(key)
}
return redis.Bytes(redisVal, err)
}
// GetString returns value, err by its key
// you can use utils.Deserialize((.GetString("yourkey"),&theobject{})
//returns empty string and a filled error if something wrong happens
func (r *Service) GetString(key string) (string, error) {
redisVal, err := r.Get(key)
if redisVal == nil {
return "", ErrKeyNotFound.Format(key)
}
sVal, err := redis.String(redisVal, err)
if err != nil {
return "", err
}
return sVal, nil
}
// GetInt returns value, err by its key
// you can use utils.Deserialize((.GetInt("yourkey"),&theobject{})
//returns -1 int and a filled error if something wrong happens
func (r *Service) GetInt(key string) (int, error) {
redisVal, err := r.Get(key)
if redisVal == nil {
return -1, ErrKeyNotFound.Format(key)
}
intVal, err := redis.Int(redisVal, err)
if err != nil {
return -1, err
}
return intVal, nil
}
// GetStringMap returns map[string]string, err by its key
//returns nil and a filled error if something wrong happens
func (r *Service) GetStringMap(key string) (map[string]string, error) {
redisVal, err := r.Get(key)
if redisVal == nil {
return nil, ErrKeyNotFound.Format(key)
}
_map, err := redis.StringMap(redisVal, err)
if err != nil {
return nil, err
}
return _map, nil
}
// GetAll returns all keys and their values from a specific key (map[string]string)
// returns a filled error if something bad happened
func (r *Service) GetAll(key string) (map[string]string, error) {
c := r.pool.Get()
defer c.Close()
if err := c.Err(); err != nil {
return nil, err
}
reply, err := c.Do("HGETALL", r.Config.Prefix+key)
if err != nil {
return nil, err
}
if reply == nil {
return nil, ErrKeyNotFound.Format(key)
}
return redis.StringMap(reply, err)
}
// GetAllKeysByPrefix returns all []string keys by a key prefix from the redis
func (r *Service) GetAllKeysByPrefix(prefix string) ([]string, error) {
c := r.pool.Get()
defer c.Close()
if err := c.Err(); err != nil {
return nil, err
}
reply, err := c.Do("KEYS", r.Config.Prefix+prefix)
if err != nil {
return nil, err
}
if reply == nil {
return nil, ErrKeyNotFound.Format(prefix)
}
return redis.Strings(reply, err)
}
// Delete removes redis entry by specific key
func (r *Service) Delete(key string) error {
c := r.pool.Get()
defer c.Close()
if _, err := c.Do("DEL", r.Config.Prefix+key); err != nil {
return err
}
return nil
}
func dial(network string, addr string, pass string) (redis.Conn, error) {
if network == "" {
network = DefaultRedisNetwork
}
if addr == "" {
addr = DefaultRedisAddr
}
c, err := redis.Dial(network, addr)
if err != nil {
return nil, err
}
if pass != "" {
if _, err = c.Do("AUTH", pass); err != nil {
c.Close()
return nil, err
}
}
return c, err
}
// Connect connects to the redis, called only once
func (r *Service) Connect() {
c := r.Config
if c.IdleTimeout <= 0 {
c.IdleTimeout = DefaultRedisIdleTimeout
}
if c.Network == "" {
c.Network = DefaultRedisNetwork
}
if c.Addr == "" {
c.Addr = DefaultRedisAddr
}
if c.MaxAgeSeconds <= 0 {
c.MaxAgeSeconds = DefaultRedisMaxAgeSeconds
}
pool := &redis.Pool{IdleTimeout: DefaultRedisIdleTimeout, MaxIdle: c.MaxIdle, MaxActive: c.MaxActive}
pool.TestOnBorrow = func(c redis.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
}
if c.Database != "" {
pool.Dial = func() (redis.Conn, error) {
red, err := dial(c.Network, c.Addr, c.Password)
if err != nil {
return nil, err
}
if _, err = red.Do("SELECT", c.Database); err != nil {
red.Close()
return nil, err
}
return red, err
}
} else {
pool.Dial = func() (redis.Conn, error) {
return dial(c.Network, c.Addr, c.Password)
}
}
r.Connected = true
r.pool = pool
}
// New returns a Redis service filled by the passed config
// to connect call the .Connect()
func New(cfg ...Config) *Service {
c := DefaultConfig().Merge(cfg)
r := &Service{pool: &redis.Pool{}, Config: &c}
return r
}