2016-06-14 07:45:40 +02:00
package iris
import (
2016-06-24 08:28:40 +02:00
"flag"
2016-06-14 07:45:40 +02:00
"fmt"
"os"
"sync"
"time"
"github.com/kataras/iris/config"
"github.com/kataras/iris/logger"
"github.com/kataras/iris/websocket"
"github.com/kataras/iris/render/rest"
"github.com/kataras/iris/render/template"
"github.com/kataras/iris/sessions"
///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 */
// 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
// 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
}
2016-06-24 08:28:40 +02:00
// SkipBannerFlag, if enabled then means that this instance ran propably by an external software, which can disable the banner output by the command line argument '-s'
var SkipBannerFlag bool
func init ( ) {
flag . BoolVar ( & SkipBannerFlag , "s" , false , "Disable banner via command line tool, overrides the logger's config field" ) // this mostly used by the iris command line tool
flag . Parse ( )
}
2016-06-14 07:45:40 +02:00
// 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-24 08:28:40 +02:00
if s . Config . DisableBanner || SkipBannerFlag {
// skip the banner
} else {
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
}