func New(o Options) (*Gelada, error) {
	g := &Gelada{options: &o}
	if g.options.Path == "" {
		g.options.Path = "/"
	}
	if g.options.SessionName == "" {
		g.options.SessionName = "gelada-session"
	}
	if g.options.SessionLifeTime == 0 {
		g.options.SessionLifeTime = 86400
	}
	if g.options.GorillaCookieStore == nil {
		if len(g.options.SessionKeys) == 0 {  
			g.store = sessions.NewCookieStore(
				[]byte("261AD9502C583BD7D8AA03083598653B"),
				[]byte("E9F6FDFAC2772D33FC5C7B3D6E4DDAFF"),
			)
		} else {  
			g.store = sessions.NewCookieStore(g.options.SessionKeys...)
		}
	} else {
		g.store = g.options.GorillaCookieStore
	}
	if g.options.LoginRoute == "" {
		return nil, errors.New("LoginRoute not declared")
	}
	if g.options.LoginUserFieldName == "" {
		g.options.LoginUserFieldName = "login"
	}
	if g.options.LoginPasswordFieldName == "" {
		g.options.LoginPasswordFieldName = "password"
	}
	if g.options.PostLogoutRoute == "" {
		g.options.PostLogoutRoute = "/"
	}
	if g.options.AuthProvider == nil {
		return nil, errors.New("AuthProvider not declared")
	}
	if len(g.options.Exceptions) > 0 {
		noAuthRules := []*exception{}
		for i, rule := range g.options.Exceptions {
			exceptionObject := &exception{
				RawRule: rule,
			}
			if len(exceptionObject.RawRule) == 0 {
				e := fmt.Errorf("error in exception rule (%d): empty rule", i)
				return nil, e
			}
			expr, err := regexp.Compile(exceptionObject.RawRule)
			if err != nil {
				e := fmt.Errorf("error in exception rule (%d: %s): %v\n",
					i, exceptionObject.RawRule, err,
				)
				return nil, e
			}
			exceptionObject.Rule = expr
			noAuthRules = append(noAuthRules, exceptionObject)
		}
		g.exceptions = noAuthRules
	}
	g.store.Options = &sessions.Options{
		Path:     g.options.Path,
		Domain:   g.options.Domain,
		MaxAge:   g.options.MaxAge,
		Secure:   g.options.Secure,
		HttpOnly: g.options.HTTPOnly,
	}
	return g, nil
}
New - init and return new Gelada struct.
package gelada
import (
	"crypto/subtle"
	"errors"
	"fmt"
	"html/template"
	"net/http"
	"regexp"
	"strings"
	"time"
	"github.com/gorilla/sessions"
)
type AuthProviderType func(user, password string) bool
type Gelada struct {
	options    *Options
	store      *sessions.CookieStore
	exceptions []*exception
}
type exception struct {
	Rule    *regexp.Regexp
	RawRule string
}
type Options struct {
	Path     string
	Domain   string
	MaxAge   int
	Secure   bool
	HTTPOnly bool
	SessionName string
	SessionLifeTime int
	SessionKeys [][]byte
	BindUserAgent bool
	BindUserHost bool
	LoginRoute string
	LoginUserFieldName     string
	LoginPasswordFieldName string
	PostLoginRoute string
	LogoutRoute string
	PostLogoutRoute string
	GorillaCookieStore *sessions.CookieStore
	AuthProvider AuthProviderType
	Exceptions []string
	AuthGuard AuthGuard
	UnauthorizedHeaderName string
}
type AuthGuard interface {
	Check(username string, req *http.Request) bool
	Complaint(username string, req *http.Request)
}
type Client struct {
	Username   string
	UserAgent  string
	UserHost   string
	LoginDate  time.Time
	ExpireDate time.Time
	gelada  *Gelada
	session *sessions.Session
}
func (c *Client) TimeToEndOfSession() int {
	t := c.ExpireDate.Sub(time.Now().Local()).Seconds()
	if t <= 0 {
		return 0
	}
	return int(t)
}
func (c *Client) Logout(res http.ResponseWriter, req *http.Request) error {
	c.session.Options.MaxAge = -1
	if err := c.session.Save(req, res); err != nil {
		return fmt.Errorf("user logout error: %v\n", err)
	}
	return nil
}
func (c *Client) Expire() bool {
	t := c.ExpireDate.Sub(time.Now().Local()).Seconds()
	if t <= 0 {
		return true
	}
	return false
}