~tsileo/blobstash

04f83bc3d61645aa360b59141dbfe9ad7df4ab5c — Thomas Sileo 2 months ago 876db62
apps,extra: new `url_for` template helper, also new `extra.random`
2 files changed, 55 insertions(+), 27 deletions(-)

M pkg/apps/apps.go
M pkg/extra/extra.go
M pkg/apps/apps.go => pkg/apps/apps.go +45 -27
@@ 3,6 3,7 @@ package apps // import "a4.io/blobstash/pkg/apps"
import (
	"context"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	rhttputil "net/http/httputil"


@@ 195,40 196,50 @@ func (apps *Apps) newApp(appConf *config.AppConfig, conf *config.Config) (*App, 
		return app, nil
	}

	// Build the app "base URL"
	// 1. Assume a custom domain at the "app level" (that will serve the app at `/`)
	baseURL := app.domain
	if baseURL == "" {
		// 2. Check if the server has a custom domain setup (and take the first one if any)
		if len(app.rootConfig.Domains) > 0 {
			baseURL = app.rootConfig.Domains[0]
		} else {
			// 3. No custom domain, most likely running on localhost/dev setup
			baseURL = app.rootConfig.Listen
			if strings.HasPrefix(baseURL, ":") {
				// The default listen has no host, replace it with localhost
				baseURL = "localhost" + baseURL
			}
		}
		// In {2, 3} (i.e. no custom app domain), join the `/api/apps/{app.name}` path
		baseURL = baseURL + "/api/apps/" + app.name
	}
	// Check if Let's Encrypt is setup
	if app.rootConfig.AutoTLS {
		baseURL = "https://" + baseURL
	} else {
		baseURL = "http://" + baseURL
	}

	// Setup the gluapp app
	if app.path != "" {
		var err error
		app.app, err = gluapp.NewApp(&gluapp.Config{
			Path:       app.path,
			Entrypoint: app.entrypoint,
			SetupState: func(L *lua.LState) error {
				cache := app.buildCache(L)

				// Build the app "base URL"
				// 1. Assume a custom domain at the "app level" (that will serve the app at `/`)
				baseURL := app.domain
				if baseURL == "" {
					// 2. Check if the server has a custom domain setup (and take the first one if any)
					if len(app.rootConfig.Domains) > 0 {
						baseURL = app.rootConfig.Domains[0]
					} else {
						// 3. No custom domain, most likely running on localhost/dev setup
						baseURL = app.rootConfig.Listen
						if strings.HasPrefix(baseURL, ":") {
							// The default listen has no host, replace it with localhost
							baseURL = "localhost" + baseURL
						}
			TemplateFuncMap: template.FuncMap{
				"url_for": func(p string) string {
					u, err := url.Parse(baseURL)
					if err != nil {
						panic(err)
					}
					// In {2, 3} (i.e. no custom app domain), join the `/api/apps/{app.name}` path
					baseURL = baseURL + "/api/apps/" + app.name
				}
				// Check if Let's Encrypt is setup
				if app.rootConfig.AutoTLS {
					baseURL = "https://" + baseURL
				} else {
					baseURL = "http://" + baseURL
				}
					u.Path = path.Join(u.Path, p)
					return u.String()

				},
			},
			SetupState: func(L *lua.LState) error {
				cache := app.buildCache(L)
				// Now that we have the base URL, we can export a new `url_for` helper
				L.SetGlobal("url_for", L.NewFunction(func(L *lua.LState) int {
					u, err := url.Parse(baseURL)


@@ 285,7 296,14 @@ func (app *App) buildCache(L *lua.LState) *lua.LTable {
	}))
	L.SetField(mt, "__newindex", L.NewFunction(func(ls *lua.LState) int {
		// FIXME(tsileo): extract the LGFunction for functions and reject invalid types
		app.appCache.Add(ls.Get(2), ls.Get(3))
		key := ls.Get(2)
		val := ls.Get(3)

		// Setting the value to nil is the same as removing the key
		if val == lua.LNil {
			app.appCache.Remove(key)
		}
		app.appCache.Add(key, val)
		return 0
	}))


M pkg/extra/extra.go => pkg/extra/extra.go +10 -0
@@ 1,6 1,7 @@
package extra // import "a4.io/blobstash/pkg/extra"

import (
	"crypto/rand"
	"fmt"
	"net/http"
	"path/filepath"


@@ 53,6 54,15 @@ func setupExtra(e *Extra) func(*lua.LState) int {
				L.Push(tbl)
				return 1
			},
			"random": func(L *lua.LState) int {
				raw := make([]byte, L.ToInt(1))
				if _, err := rand.Read(raw); err != nil {
					panic(err)
				}
				out := fmt.Sprintf("%x", raw)
				L.Push(lua.LString(out))
				return 1
			},
			"v": func(L *lua.LState) int {
				L.Push(lua.LString(fmt.Sprintf("%v", time.Now().UnixNano())))
				return 1