コード例 #1
0
ファイル: fs.go プロジェクト: app-kit/go-appkit
// Retrieve a cache item from the cache.
func (fs *Fs) Get(key string, items ...kit.CacheItem) (kit.CacheItem, apperror.Error) {
	var item kit.CacheItem = &StrItem{}
	if items != nil {
		if len(items) != 1 {
			return nil, &apperror.Err{
				Code:    "invalid_item",
				Message: "You must specify one item only",
			}
		}
		item = items[0]
	}

	key = fs.key(key)
	if key == "" {
		return nil, apperror.New("empty_key")
	}

	exists, err := utils.FileExists(fs.keyPath(key))
	if err != nil {
		return nil, err
	}

	if !exists {
		return nil, nil
	}

	metaContent, err := utils.ReadFile(fs.keyMetaPath(key))
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(metaContent, &item); err != nil {
		return nil, apperror.Wrap(err, "metadata_unmarshal_error")
	}

	// Reset ExpiresAt if it is zero, since json.Unmarshal produces
	// a time.Time which is not exactly equal to the zero value.
	if item.GetExpiresAt().IsZero() {
		item.SetExpiresAt(time.Time{})
	}

	content, err := utils.ReadFile(fs.keyPath(key))
	if err != nil {
		return nil, err
	}

	if err := item.FromString(string(content)); err != nil {
		return nil, apperror.Wrap(err, "cacheitem_fromstring_error")
	}

	// Return nil if item is expired.
	if item.IsExpired() {
		return nil, nil
	}

	return item, nil
}
コード例 #2
0
ファイル: email.go プロジェクト: app-kit/go-appkit
func (e *Mail) EmbedFile(path string) apperror.Error {
	content, err := utils.ReadFile(path)
	if err != nil {
		return err
	}
	e.Attachments = append(e.Attachments, &Part{Content: content})
	return nil
}
コード例 #3
0
ファイル: engine.go プロジェクト: app-kit/go-appkit
func (e *Engine) BuildFile(name string, paths ...string) (interface{}, Error) {
	if len(paths) != 1 {
		panic("Must specify exactly one path")
	}

	tpl, err := utils.ReadFile(paths[0])
	if err != nil {
		return nil, err
	}

	return e.Build(name, string(tpl))
}
コード例 #4
0
ファイル: api.go プロジェクト: app-kit/go-appkit
func serverRenderer(registry kit.Registry, r kit.Request) kit.Response {
	url := r.GetHttpRequest().URL

	// Build the url to query.
	if url.Scheme == "" {
		url.Scheme = "http"
	}
	if url.Host == "" {
		url.Host = registry.Config().UString("host", "localhost") + ":" + registry.Config().UString("port", "8000")
	}

	q := url.Query()
	q.Set("no-server-render", "1")
	url.RawQuery = q.Encode()

	strUrl := url.String()

	cacheKey := "serverrenderer_" + strUrl
	cacheName := registry.Config().UString("serverRenderer.cache")
	var cache kit.Cache

	// If a cache is specified, try to retrieve it.
	if cacheName != "" {
		cache = registry.Cache(cacheName)
		if cache == nil {
			registry.Logger().Errorf("serverRenderer.cache is set to %v, but the cache is not registered with app", cacheName)
		}
	}

	// If a cache was found, try to retrieve cached response.
	if cache != nil {
		item, err := cache.Get(cacheKey)
		if err != nil {
			registry.Logger().Errorf("serverRenderer: cache retrieval error: %v", err)
		} else if item != nil {
			// Cache item found, return response with cache item.
			status, _ := strconv.ParseInt(item.GetTags()[0], 10, 64)
			data, _ := item.ToString()

			return &kit.AppResponse{
				HttpStatus: int(status),
				RawData:    []byte(data),
			}
		}
	}

	// Either no cache or url not yet cached, so render it.

	// First, ensure that the tmp directory exists.
	tmpDir := path.Join(registry.Config().TmpDir(), "phantom")
	if ok, _ := utils.FileExists(tmpDir); !ok {
		if err := os.MkdirAll(tmpDir, 0777); err != nil {
			return &kit.AppResponse{
				Error: &apperror.Err{
					Code:    "create_tmp_dir_failed",
					Message: fmt.Sprintf("Could not create the tmp directory at %v: %v", tmpDir, err),
				},
			}
		}
	}

	// Build a unique file name.
	filePath := path.Join(tmpDir, utils.UUIdv4()+".html")

	// Execute phantom js.

	// Find path of phantom script.
	_, filename, _, _ := runtime.Caller(1)
	scriptPath := path.Join(path.Dir(path.Dir(filename)), "phantom", "render.js")

	start := time.Now()

	phantomPath := registry.Config().UString("serverRenderer.phantomJsPath", "phantomjs")

	args := []string{
		"--web-security=false",
		"--local-to-remote-url-access=true",
		scriptPath,
		"10",
		strUrl,
		filePath,
	}
	result, err := exec.Command(phantomPath, args...).CombinedOutput()
	if err != nil {
		registry.Logger().Errorf("Phantomjs execution error: %v", string(result))

		return &kit.AppResponse{
			Error: apperror.Wrap(err, "phantom_execution_failed"),
		}
	}

	// Get time taken as milliseconds.
	timeTaken := int(time.Now().Sub(start) / time.Millisecond)
	registry.Logger().WithFields(log.Fields{
		"action":       "phantomjs_render",
		"milliseconds": timeTaken,
	}).Debugf("Rendered url %v with phantomjs", url)

	content, err2 := utils.ReadFile(filePath)
	if err2 != nil {
		return kit.NewErrorResponse(err2)
	}

	// Find http status code.
	status := 200
	res := regexp.MustCompile("http_status_code\\=(\\d+)").FindStringSubmatch(string(content))
	if res != nil {
		s, _ := strconv.ParseInt(res[1], 10, 64)
		status = int(s)
	}

	// Save to cache.
	if cache != nil {
		lifetime := registry.Config().UInt("serverRenderer.cacheLiftetime", 3600)

		err := cache.Set(&caches.StrItem{
			Key:       cacheKey,
			Value:     string(content),
			Tags:      []string{strconv.FormatInt(int64(status), 10)},
			ExpiresAt: time.Now().Add(time.Duration(lifetime) * time.Second),
		})
		if err != nil {
			registry.Logger().Errorf("serverRenderer: Cache persist error: %v", err)
		}
	}

	return &kit.AppResponse{
		HttpStatus: status,
		RawData:    content,
	}
}