2016-06-14 07:45:40 +02:00
|
|
|
package iris
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/kataras/iris/config"
|
|
|
|
"github.com/kataras/iris/logger"
|
|
|
|
"github.com/kataras/iris/render/rest"
|
|
|
|
"github.com/kataras/iris/render/template"
|
|
|
|
"github.com/kataras/iris/sessions"
|
2016-06-28 11:50:26 +02:00
|
|
|
"github.com/kataras/iris/websocket"
|
2016-06-14 07:45:40 +02:00
|
|
|
///NOTE: register the session providers, but the s.Config.Sessions.Provider will be used only, if this empty then sessions are disabled.
|
|
|
|
_ "github.com/kataras/iris/sessions/providers/memory"
|
|
|
|
_ "github.com/kataras/iris/sessions/providers/redis"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Default entry, use it with iris.$anyPublicFunc
|
|
|
|
var (
|
|
|
|
Default *Framework
|
|
|
|
Config *config.Iris
|
|
|
|
Logger *logger.Logger
|
|
|
|
Plugins PluginContainer
|
|
|
|
Websocket websocket.Server
|
|
|
|
HTTPServer *Server
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
Default = New()
|
|
|
|
Config = Default.Config
|
|
|
|
Logger = Default.Logger
|
|
|
|
Plugins = Default.Plugins
|
|
|
|
Websocket = Default.Websocket
|
|
|
|
HTTPServer = Default.HTTPServer
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
/* conversional */
|
2016-06-28 17:06:52 +02:00
|
|
|
|
2016-06-14 07:45:40 +02:00
|
|
|
// HTMLEngine conversion for config.HTMLEngine
|
|
|
|
HTMLEngine = config.HTMLEngine
|
|
|
|
// PongoEngine conversion for config.PongoEngine
|
|
|
|
PongoEngine = config.PongoEngine
|
|
|
|
// MarkdownEngine conversion for config.MarkdownEngine
|
|
|
|
MarkdownEngine = config.MarkdownEngine
|
|
|
|
// JadeEngine conversion for config.JadeEngine
|
|
|
|
JadeEngine = config.JadeEngine
|
|
|
|
// AmberEngine conversion for config.AmberEngine
|
|
|
|
AmberEngine = config.AmberEngine
|
2016-06-28 11:50:26 +02:00
|
|
|
// HandlebarsEngine conversion for config.HandlebarsEngine
|
|
|
|
HandlebarsEngine = config.HandlebarsEngine
|
2016-06-14 07:45:40 +02:00
|
|
|
// DefaultEngine conversion for config.DefaultEngine
|
|
|
|
DefaultEngine = config.DefaultEngine
|
|
|
|
// NoEngine conversion for config.NoEngine
|
|
|
|
NoEngine = config.NoEngine
|
|
|
|
// NoLayout to disable layout for a particular template file
|
|
|
|
// conversion for config.NoLayout
|
|
|
|
NoLayout = config.NoLayout
|
|
|
|
/* end conversional */
|
|
|
|
)
|
|
|
|
|
|
|
|
// Framework is our God |\| Google.Search('Greek mythology Iris')
|
|
|
|
//
|
|
|
|
// Implements the FrameworkAPI
|
|
|
|
type Framework struct {
|
|
|
|
*muxAPI
|
2016-06-24 00:34:49 +02:00
|
|
|
rest *rest.Render
|
|
|
|
templates *template.Template
|
|
|
|
sessions *sessions.Manager
|
2016-06-14 07:45:40 +02:00
|
|
|
// fields which are useful to the user/dev
|
|
|
|
HTTPServer *Server
|
|
|
|
Config *config.Iris
|
|
|
|
Logger *logger.Logger
|
|
|
|
Plugins PluginContainer
|
|
|
|
Websocket websocket.Server
|
|
|
|
}
|
|
|
|
|
|
|
|
// New creates and returns a new Iris station aka Framework.
|
|
|
|
//
|
|
|
|
// Receives an optional config.Iris as parameter
|
|
|
|
// If empty then config.Default() is used instead
|
|
|
|
func New(cfg ...config.Iris) *Framework {
|
|
|
|
c := config.Default().Merge(cfg)
|
|
|
|
|
|
|
|
// we always use 's' no 'f' because 's' is easier for me to remember because of 'station'
|
|
|
|
// some things never change :)
|
|
|
|
s := &Framework{Config: &c}
|
|
|
|
{
|
|
|
|
///NOTE: set all with s.Config pointer
|
|
|
|
// set the Logger
|
|
|
|
s.Logger = logger.New(s.Config.Logger)
|
|
|
|
// set the plugin container
|
|
|
|
s.Plugins = &pluginContainer{logger: s.Logger}
|
|
|
|
// set the websocket server
|
|
|
|
s.Websocket = websocket.NewServer(s.Config.Websocket)
|
|
|
|
// set the servemux, which will provide us the public API also, with its context pool
|
2016-06-16 04:24:01 +02:00
|
|
|
mux := newServeMux(sync.Pool{New: func() interface{} { return &Context{framework: s} }}, s.Logger)
|
2016-06-14 07:45:40 +02:00
|
|
|
// set the public router API (and party)
|
|
|
|
s.muxAPI = &muxAPI{mux: mux, relativePath: "/"}
|
|
|
|
// set the server
|
|
|
|
s.HTTPServer = newServer(&s.Config.Server)
|
|
|
|
}
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Framework) initialize() {
|
|
|
|
// set sessions
|
|
|
|
if s.Config.Sessions.Provider != "" {
|
|
|
|
s.sessions = sessions.New(s.Config.Sessions)
|
|
|
|
}
|
|
|
|
|
2016-06-22 15:01:31 +02:00
|
|
|
// set the rest
|
2016-06-14 07:45:40 +02:00
|
|
|
s.rest = rest.New(s.Config.Render.Rest)
|
|
|
|
|
2016-06-24 00:34:49 +02:00
|
|
|
// set templates if not already setted
|
2016-06-14 07:45:40 +02:00
|
|
|
s.prepareTemplates()
|
|
|
|
|
|
|
|
// listen to websocket connections
|
|
|
|
websocket.RegisterServer(s, s.Websocket, s.Logger)
|
|
|
|
|
2016-06-17 06:18:09 +02:00
|
|
|
// prepare the mux & the server
|
2016-06-14 07:45:40 +02:00
|
|
|
s.mux.setCorrectPath(!s.Config.DisablePathCorrection)
|
|
|
|
s.mux.setEscapePath(!s.Config.DisablePathEscape)
|
2016-06-16 04:24:01 +02:00
|
|
|
s.mux.setHostname(s.HTTPServer.VirtualHostname())
|
2016-06-14 07:45:40 +02:00
|
|
|
// set the debug profiling handlers if ProfilePath is setted
|
|
|
|
if debugPath := s.Config.ProfilePath; debugPath != "" {
|
|
|
|
s.Handle(MethodGet, debugPath+"/*action", profileMiddleware(debugPath)...)
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.Config.MaxRequestBodySize > 0 {
|
|
|
|
s.HTTPServer.MaxRequestBodySize = int(s.Config.MaxRequestBodySize)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// prepareTemplates sets the templates if not nil, we make this check because of .TemplateString, which can be called before Listen
|
|
|
|
func (s *Framework) prepareTemplates() {
|
|
|
|
// prepare the templates
|
|
|
|
if s.templates == nil {
|
|
|
|
// These functions are directly contact with Iris' functionality.
|
|
|
|
funcs := map[string]interface{}{
|
|
|
|
"url": s.URL,
|
|
|
|
"urlpath": s.Path,
|
|
|
|
}
|
|
|
|
|
|
|
|
template.RegisterSharedFuncs(funcs)
|
|
|
|
|
|
|
|
s.templates = template.New(s.Config.Render.Template)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// openServer is internal method, open the server with specific options passed by the Listen and ListenTLS
|
|
|
|
// it's a blocking func
|
|
|
|
func (s *Framework) openServer() (err error) {
|
|
|
|
s.initialize()
|
|
|
|
s.Plugins.DoPreListen(s)
|
2016-06-17 06:18:09 +02:00
|
|
|
// set the server's handler now, in order to give the chance to the plugins to add their own middlewares and routes to this station
|
|
|
|
s.HTTPServer.SetHandler(s.mux)
|
2016-06-15 23:13:56 +02:00
|
|
|
if err = s.HTTPServer.Open(); err == nil {
|
2016-06-14 07:45:40 +02:00
|
|
|
// print the banner
|
2016-06-25 06:38:47 +02:00
|
|
|
if !s.Config.DisableBanner {
|
2016-06-14 07:45:40 +02:00
|
|
|
s.Logger.PrintBanner(banner,
|
|
|
|
fmt.Sprintf("%s: Running at %s\n", time.Now().Format(config.TimeFormat),
|
|
|
|
s.HTTPServer.Host()))
|
|
|
|
}
|
|
|
|
s.Plugins.DoPostListen(s)
|
|
|
|
ch := make(chan os.Signal)
|
|
|
|
<-ch
|
|
|
|
s.Close()
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// closeServer is used to close the tcp listener from the server, returns an error
|
|
|
|
func (s *Framework) closeServer() error {
|
|
|
|
s.Plugins.DoPreClose(s)
|
|
|
|
return s.HTTPServer.close()
|
|
|
|
}
|
2016-06-17 06:18:09 +02:00
|
|
|
|
|
|
|
// justServe initializes the whole framework but server doesn't listens to a specific net.Listener
|
|
|
|
func (s *Framework) justServe() *Server {
|
|
|
|
s.initialize()
|
|
|
|
s.Plugins.DoPreListen(s)
|
|
|
|
s.HTTPServer.SetHandler(s.mux)
|
|
|
|
s.Plugins.DoPostListen(s)
|
|
|
|
return s.HTTPServer
|
|
|
|
}
|