From 9c94bb2ab17a0c0fc8d514d1595608320b0e397f Mon Sep 17 00:00:00 2001 From: James Hillyerd Date: Sun, 21 Oct 2012 09:57:42 -0700 Subject: [PATCH] The main index template renders now! --- conf/inbucket.conf | 2 +- config.go | 16 +++---- themes/integral/public/images/img10.jpg | Bin 8891 -> 0 bytes .../templates/{header.html => _base.html} | 29 ++++++++---- themes/integral/templates/footer.html | 8 ---- .../Index.html => root-index.html} | 12 ++--- web/app.go | 31 ------------- web/context.go | 25 ++++++++++ web/root_controller.go | 9 ++++ web/server.go | 43 +++++++++++++++++- web/template.go | 33 ++++++++++++++ 11 files changed, 141 insertions(+), 67 deletions(-) delete mode 100644 themes/integral/public/images/img10.jpg rename themes/integral/templates/{header.html => _base.html} (57%) delete mode 100644 themes/integral/templates/footer.html rename themes/integral/templates/{Application/Index.html => root-index.html} (68%) delete mode 100644 web/app.go create mode 100644 web/context.go create mode 100644 web/root_controller.go create mode 100644 web/template.go diff --git a/conf/inbucket.conf b/conf/inbucket.conf index ff64374..a38e978 100644 --- a/conf/inbucket.conf +++ b/conf/inbucket.conf @@ -32,7 +32,7 @@ ip4.port=9000 theme=integral # Path to the selected themes template files -templates.dir=%(install.dir)s/themes/%(theme)s/templates +template.dir=%(install.dir)s/themes/%(theme)s/templates # Path to the selected themes public (static) files public.dir=%(install.dir)s/themes/%(theme)s/public diff --git a/config.go b/config.go index beee858..4ae451b 100644 --- a/config.go +++ b/config.go @@ -17,10 +17,10 @@ type SmtpConfig struct { } type WebConfig struct { - Ip4address net.IP - Ip4port int - TemplatesDir string - PublicDir string + Ip4address net.IP + Ip4port int + TemplateDir string + PublicDir string } var smtpConfig *SmtpConfig @@ -68,7 +68,7 @@ func LoadConfig(filename string) error { requireOption(messages, "smtp", "domain") requireOption(messages, "web", "ip4.address") requireOption(messages, "web", "ip4.port") - requireOption(messages, "web", "templates.dir") + requireOption(messages, "web", "template.dir") requireOption(messages, "web", "public.dir") requireOption(messages, "datastore", "path") if messages.Len() > 0 { @@ -151,12 +151,12 @@ func parseWebConfig() error { return fmt.Errorf("Failed to parse %v: %v", option, err) } - option = "[web]templates.dir" - str, err = Config.String("web", "templates.dir") + option = "[web]template.dir" + str, err = Config.String("web", "template.dir") if err != nil { return fmt.Errorf("Failed to parse %v: %v", option, err) } - webConfig.TemplatesDir = str + webConfig.TemplateDir = str option = "[web]public.dir" str, err = Config.String("web", "public.dir") diff --git a/themes/integral/public/images/img10.jpg b/themes/integral/public/images/img10.jpg deleted file mode 100644 index 9fe1f17c00f79710b60aa2199d4aac85ef81466d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8891 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 diff --git a/themes/integral/templates/header.html b/themes/integral/templates/_base.html similarity index 57% rename from themes/integral/templates/header.html rename to themes/integral/templates/_base.html index a483983..f1d304a 100644 --- a/themes/integral/templates/header.html +++ b/themes/integral/templates/_base.html @@ -4,19 +4,21 @@ Design by Free CSS Templates http://www.freecsstemplates.org Released for free under a Creative Commons Attribution 2.5 License --> +{{define "col1menu"}}{{/* Used inside #content div */}} +
+ +
+{{end}} -{{.title}} - +{{template "title" .}} + - -{{range .moreStyles}} - -{{end}} -{{range .moreScripts}} - -{{end}} +
+{{template "content" .}} +
+ + + diff --git a/themes/integral/templates/footer.html b/themes/integral/templates/footer.html deleted file mode 100644 index ba7a67c..0000000 --- a/themes/integral/templates/footer.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - diff --git a/themes/integral/templates/Application/Index.html b/themes/integral/templates/root-index.html similarity index 68% rename from themes/integral/templates/Application/Index.html rename to themes/integral/templates/root-index.html index 466ec39..f809a4a 100644 --- a/themes/integral/templates/Application/Index.html +++ b/themes/integral/templates/root-index.html @@ -1,15 +1,11 @@ -{{set "title" "Inbucket" .}} -{{template "header.html" .}} -{{template "menu.html" .}} - +{{define "title"}}Inbucket{{end}} +{{define "content"}} +{{template "col1menu" .}}
- {{template "errors.html" .}} -

Inbucket is an email testing service; it will accept email for any email address and make it available to view without a password.

To view email for a particular address, enter the username portion of the address into the box on the upper right and click go.

- -{{template "footer.html" .}} +{{end}} diff --git a/web/app.go b/web/app.go deleted file mode 100644 index 17499a5..0000000 --- a/web/app.go +++ /dev/null @@ -1,31 +0,0 @@ -package web - -import ( - "github.com/jhillyerd/inbucket/app/smtpd" - "github.com/robfig/revel" -) - -type Application struct { - *rev.Controller -} - -func (c Application) Index() rev.Result { - return c.Render() -} - -type SmtpdPlugin struct { - rev.EmptyPlugin - server *smtpd.Server -} - -func (p SmtpdPlugin) OnAppStart() { - domain := rev.Config.StringDefault("smtpd.domain", "localhost") - port := rev.Config.IntDefault("smtpd.port", 2500) - rev.INFO.Printf("SMTP Daemon plugin init {domain: %v, port: %v}", domain, port) - p.server = smtpd.New(domain, port) - go p.server.Start() -} - -func init() { - rev.RegisterPlugin(SmtpdPlugin{}) -} diff --git a/web/context.go b/web/context.go new file mode 100644 index 0000000..73aaaf7 --- /dev/null +++ b/web/context.go @@ -0,0 +1,25 @@ +package web + +import ( + "github.com/gorilla/sessions" + "net/http" +) + +type Context struct { + Session *sessions.Session +} + +func (c *Context) Close() { + // Do nothing +} + +func NewContext(req *http.Request) (*Context, error) { + sess, err := sessionStore.Get(req, "inbucket") + ctx := &Context{ + Session: sess, + } + if err != nil { + return ctx, err + } + return ctx, err +} diff --git a/web/root_controller.go b/web/root_controller.go new file mode 100644 index 0000000..7205fdf --- /dev/null +++ b/web/root_controller.go @@ -0,0 +1,9 @@ +package web + +import ( + "net/http" +) + +func RootIndex(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) { + return T("root-index.html").Execute(w, nil) +} diff --git a/web/server.go b/web/server.go index 082d621..c4ac8bf 100644 --- a/web/server.go +++ b/web/server.go @@ -6,11 +6,15 @@ package web import ( "fmt" "github.com/gorilla/mux" + "github.com/gorilla/sessions" "github.com/jhillyerd/inbucket" "net/http" + "thegoods.biz/httpbuf" "time" ) +type handler func(http.ResponseWriter, *http.Request, *Context) error + /* type WebServer struct { thing string @@ -24,24 +28,31 @@ func NewWebServer() *Server { var Router *mux.Router +var sessionStore sessions.Store + func setupRoutes(cfg inbucket.WebConfig) { r := mux.NewRouter() Router = r - inbucket.Info("Theme templates mapped to '%v'", cfg.TemplatesDir) + inbucket.Info("Theme templates mapped to '%v'", cfg.TemplateDir) inbucket.Info("Theme static content mapped to '%v'", cfg.PublicDir) // Static content r.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir(cfg.PublicDir)))) + + // Root + r.Path("/").Handler(handler(RootIndex)) } // Start() the web server func Start() { cfg := inbucket.GetWebConfig() setupRoutes(cfg) + + sessionStore = sessions.NewCookieStore([]byte("something-very-secret")) + addr := fmt.Sprintf("%v:%v", cfg.Ip4address, cfg.Ip4port) inbucket.Info("HTTP listening on TCP4 %v", addr) - s := &http.Server{ Addr: addr, Handler: Router, @@ -54,3 +65,31 @@ func Start() { inbucket.Error("HTTP server failed: %v", err) } } + +// ServeHTTP builds the context and passes onto the real handler +func (h handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + // Create the context + ctx, err := NewContext(req) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + defer ctx.Close() + + // Run the handler, grab the error, and report it + buf := new(httpbuf.Buffer) + err = h(buf, req, ctx) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Save the session + if err = ctx.Session.Save(req, buf); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Apply the buffered response to the writer + buf.Apply(w) +} diff --git a/web/template.go b/web/template.go new file mode 100644 index 0000000..121f3c9 --- /dev/null +++ b/web/template.go @@ -0,0 +1,33 @@ +package web + +import ( + "github.com/jhillyerd/inbucket" + "html/template" + "path/filepath" + "sync" +) + +var cachedTemplates = map[string]*template.Template{} +var cachedMutex sync.Mutex + +func T(name string) *template.Template { + cachedMutex.Lock() + defer cachedMutex.Unlock() + + if t, ok := cachedTemplates[name]; ok { + return t + } + + templateDir := inbucket.GetWebConfig().TemplateDir + templateFile := filepath.Join(templateDir, name) + inbucket.Trace("Parsing template %v", templateFile) + + t := template.New("_base.html").Funcs(TemplateFuncs) + t = template.Must(t.ParseFiles( + filepath.Join(templateDir, "_base.html"), + templateFile, + )) + cachedTemplates[name] = t + + return t +}