예제 #1
0
func (self *CachedView) Render(context *Context, writer *utils.XMLWriter) (err error) {
	if self.Content == nil {
		return nil
	}
	if Config.DisableCachedViews || len(context.Params) > 0 || context.Request.Method != "GET" {
		return self.Content.Render(context, writer)
	}
	if self.data == nil || time.Now().After(self.validUntil) {
		xmlBuffer := utils.NewXMLBuffer()
		err = self.Content.Render(context, &xmlBuffer.XMLWriter)
		if err != nil {
			return err
		}
		self.data = xmlBuffer.Bytes()
		self.validUntil = time.Now().Add(self.Duration)
	}
	_, err = writer.Write(self.data)
	return err
}
예제 #2
0
파일: page.go 프로젝트: sedzinreri/go-start
func (self *Page) Render(context *Context, writer *utils.XMLWriter) (err error) {
	if self.OnPreRender != nil {
		err = self.OnPreRender(self, context)
		if err != nil {
			return err
		}
	}

	var templateContext struct {
		Title              string
		MetaDescription    string
		MetaViewport       string
		Head               string
		PreCSS             string
		CSS                string
		PostCSS            string
		DynamicStyle       string
		HeadScripts        string
		DynamicHeadScripts string
		Scripts            string
		DynamicScripts     string
		Favicon16x16URL    string
		Favicon57x57URL    string
		Favicon72x72URL    string
		Favicon114x114URL  string
		Favicon129x129URL  string
		Content            string
	}

	if self.WriteTitle != nil {
		var buf bytes.Buffer
		err := self.WriteTitle(context, &buf)
		if err != nil {
			return err
		}
		templateContext.Title = html.EscapeString(buf.String())
	}
	if self.WriteMetaDescription != nil {
		var buf bytes.Buffer
		err := self.WriteMetaDescription(context, &buf)
		if err != nil {
			return err
		}
		templateContext.MetaDescription = html.EscapeString(buf.String())
	}

	metaViewport := self.MetaViewport
	if metaViewport == "" {
		metaViewport = Config.Page.DefaultMetaViewport
	}
	templateContext.MetaViewport = metaViewport

	writeHead := self.WriteHead
	if writeHead == nil {
		writeHead = Config.Page.DefaultWriteHead
	}
	if writeHead != nil {
		var buf bytes.Buffer
		err := writeHead(context, &buf)
		if err != nil {
			return err
		}
		templateContext.Head = buf.String()
	}

	//templateContext.Meta = self.Meta
	templateContext.Favicon16x16URL = self.Favicon16x16URL
	templateContext.Favicon57x57URL = self.Favicon57x57URL
	templateContext.Favicon72x72URL = self.Favicon72x72URL
	templateContext.Favicon114x114URL = self.Favicon114x114URL
	templateContext.Favicon129x129URL = self.Favicon129x129URL

	if self.WritePreCSS != nil {
		var buf bytes.Buffer
		if err = self.WritePreCSS(context, &buf); err != nil {
			return err
		}
		templateContext.PreCSS = buf.String()
	}
	if self.CSS != nil {
		templateContext.CSS = self.CSS.URL(context.PathArgs...)
	} else {
		templateContext.CSS = Config.Page.DefaultCSS
	}
	if self.WritePostCSS != nil {
		var buf bytes.Buffer
		if err = self.WritePostCSS(context, &buf); err != nil {
			return err
		}
		templateContext.PostCSS = buf.String()
	}

	writeHeadScripts := self.WriteHeadScripts
	if writeHeadScripts == nil {
		writeHeadScripts = Config.Page.DefaultWriteHeadScripts
	}
	if writeHeadScripts != nil {
		var buf bytes.Buffer
		if err = writeHeadScripts(context, &buf); err != nil {
			return err
		}
		templateContext.HeadScripts = buf.String()
	}

	writeScripts := self.WriteScripts
	if writeScripts == nil {
		writeScripts = Config.Page.DefaultWriteScripts
	}
	if writeScripts != nil {
		var buf bytes.Buffer
		if err = writeScripts(context, &buf); err != nil {
			return err
		}
		if Config.Page.PostWriteScripts != nil {
			if err = Config.Page.PostWriteScripts(context, &buf); err != nil {
				return err
			}
		}
		templateContext.Scripts = buf.String()
	}

	contentHtml := utils.NewXMLBuffer()
	if self.Content != nil {
		err = self.Content.Render(context, &contentHtml.XMLWriter)
		if err != nil {
			return err
		}
	}
	templateContext.Content = contentHtml.String()

	// Get dynamic style and scripts after self.Content.Render()
	// because they are added in Render()
	templateContext.DynamicStyle = context.dynamicStyle.String()
	templateContext.DynamicHeadScripts = context.dynamicHeadScripts.String()
	templateContext.DynamicScripts = context.dynamicScripts.String()

	self.Template.GetContext = TemplateContext(templateContext)
	return self.Template.Render(context, writer)
}
예제 #3
0
// Pages and nil views will be registered with a trailing slash at their path
// and a permanent redirect from the path without trailing slash
// Nil views will be registered as NotFound404
// parentPath always ends with a slash
func (self *ViewPath) initAndRegisterViewsRecursive(parentPath string) {
	if parentPath == "" || parentPath[len(parentPath)-1] != '/' {
		panic("Parent path must end with a slash: " + parentPath)
	}
	if parentPath != "/" && self.Name == "" && self.Args == 0 {
		panic("Sub path of " + parentPath + " with no Name and Args")
	}
	if self.Name != "" && !PathFragmentRegexp.MatchString(self.Name) {
		panic("Invalid characters in view.ViewPath.Name: " + self.Name)
	}
	if self.View != nil && utils.IsDeepNil(self.View) {
		panic("Nil value wrapped with non nil view.View under parentPath: " + parentPath)
	}

	addSlash := self.Args > 0
	if self.View == nil {
		addSlash = true
		self.View = &NotFoundView{Message: "Invalid URL"}
	} else if _, isPage := self.View.(*Page); isPage {
		addSlash = true
		if self.Auth != nil {
			if self.NoAuth == nil && Config.LoginSignupPage != nil && *Config.LoginSignupPage != nil {
				self.NoAuth = IndirectURL(Config.LoginSignupPage)
			}
		}
	}

	path := parentPath + self.Name
	if self.Args > 0 {
		if self.Name != "" {
			path += "/"
		}
		for i := 0; i < self.Args; i++ {
			path += PathFragmentPattern + "/"
		}
	}

	if addSlash {
		if path[len(path)-1] != '/' {
			path += "/"
		}
		if path != "/" {
			web.Get(path[:len(path)-1], func(webContext *web.Context, args ...string) string {
				webContext.Redirect(http.StatusMovedPermanently, webContext.Request.RequestURI+"/")
				return ""
			})
		}
	}

	if self.Args < 0 {
		panic("Negative Args at " + path)
	}
	if _, pathExists := viewsByPath[path]; pathExists {
		panic("View with path '" + path + "' already registered")
	}
	viewsByPath[path] = self.View

	if Config.Debug.PrintPaths {
		debug.Print(path)
	}

	//debug.Print(path)
	self.View.Init(self.View)
	if viewWithURL, ok := self.View.(ViewWithURL); ok {
		viewWithURL.SetPath(path)
	}

	htmlFunc := func(webContext *web.Context, args ...string) string {

		// See: http://groups.google.com/group/golang-nuts/browse_thread/thread/ab1971bb9459025d
		// Slows down the memory leak on 32 bit systems a little bit:
		defer func() {
			go runtime.GC()
		}()

		context := NewContext(webContext, self.View, args)

		for _, subdomain := range Config.RedirectSubdomains {
			if len(subdomain) > 0 {
				if subdomain[len(subdomain)-1] != '.' {
					subdomain += "."
				}
				host := context.Request.Host
				if strings.Index(host, subdomain) == 0 {
					host = host[len(subdomain):]
					url := "http://" + host + context.Request.URL.Path
					context.Redirect(http.StatusMovedPermanently, url)
					return ""
				}
			}
		}

		handleErr := func(err error) string {
			switch err.(type) {
			case NotFound:
				context.NotFound(err.Error())
			case Redirect:
				if Config.Debug.PrintRedirects {
					fmt.Printf("%d Redirect: %s\n", http.StatusFound, err.Error())
				}
				context.Redirect(http.StatusFound, err.Error())
			case PermanentRedirect:
				if Config.Debug.PrintRedirects {
					fmt.Printf("%d Permanent Redirect: %s\n", http.StatusMovedPermanently, err.Error())
				}
				context.Redirect(http.StatusMovedPermanently, err.Error())
			case Forbidden:
				context.Abort(http.StatusForbidden, err.Error())
			default:
				context.Abort(http.StatusInternalServerError, err.Error())
			}
			return ""
		}

		handleNoAuth := func(err error) string {
			switch {
			case err != nil:
				return handleErr(err)
			case self.NoAuth != nil:
				from := url.QueryEscape(context.Request.RequestURI)
				to := self.NoAuth.URL(context.PathArgs...) + "?from=" + from
				return handleErr(Redirect(to))
			}
			return handleErr(Forbidden("403 Forbidden: authentication required"))
		}

		if Config.OnPreAuth != nil {
			if err := Config.OnPreAuth(context); err != nil {
				return handleErr(err)
			}
		}

		if Config.GlobalAuth != nil {
			if ok, err := Config.GlobalAuth.Authenticate(context); !ok {
				return handleNoAuth(err)
			}
		}

		if self.Auth == nil {
			self.Auth = Config.FallbackAuth
		}
		if self.Auth != nil {
			if ok, err := self.Auth.Authenticate(context); !ok {
				return handleNoAuth(err)
			}
		}

		//		numMiddlewares := len(Config.Middlewares)
		//		for i := 0; i < numMiddlewares; i++ {
		//			if abort := Config.Middlewares[i].PreRender(context); abort {
		//				return ""
		//			}
		//		}

		xmlBuffer := utils.NewXMLBuffer()

		err := self.View.Render(context, &xmlBuffer.XMLWriter)

		//		for i := numMiddlewares - 1; i >= 0; i-- {
		//			html, err = Config.Middlewares[i].PostRender(context, html, err)
		//		}

		if err != nil {
			return handleErr(err)
		}
		return xmlBuffer.String()
	}

	web.Get(path, htmlFunc)
	web.Post(path, htmlFunc)

	for i := range self.Sub {
		self.Sub[i].initAndRegisterViewsRecursive(path)
	}
}