Example #1
0
// New returns a new App. Any errors will result in a panic, Since
// this function should be called only during app initialization.
func New(opts Options) *App {
	if opts.Name == "" {
		panic(errors.New("reusable app name can't be empty"))
	}
	a := &App{
		App:  *app.New(),
		opts: &opts,
		name: opts.Name,
	}
	var k interface{} = reusableAppKey
	if opts.DataKey != nil {
		k = opts.DataKey
	}
	a.Set(k, a)
	_, file, _, ok := runtime.Caller(1)
	if ok {
		a.dir = filepath.Dir(file)
	}
	assetsFS, assetsRel := a.mustOpenVFS("assets", opts.AssetsDir, opts.AssetsData)
	if assetsFS != nil {
		assetsPrefix := path.Clean("/" + filepath.ToSlash(assetsRel) + "/")
		manager := assets.New(assetsFS, assetsPrefix)
		a.SetAssetsManager(manager)
		a.Handle("^"+assetsPrefix, app.HandlerFromHTTPFunc(manager.Handler()))
	}
	templatesFS, _ := a.mustOpenVFS("tmpl", opts.TemplatesDir, opts.TemplatesData)
	if templatesFS != nil {
		a.SetTemplatesFS(templatesFS)
	}
	return a
}
Example #2
0
func init() {
	template.AddFuncs(template.FuncMap{
		"#config": func(name string, def string) template.HTML {
			var buf bytes.Buffer
			buf.WriteString("<h3 class=\"config\">")
			buf.WriteString(html.Escape(name))
			if def != "" {
				buf.WriteString(" <span class=\"label label-success\">optional</span>")
				fmt.Fprintf(&buf, " <span class=\"default\">default: %s</span>", html.Escape(def))
			} else {
				buf.WriteString(" <span class=\"label label-danger\">required</span>")
			}
			buf.WriteString("</h3>")
			return template.HTML(buf.String())
		}})
	config.MustParse()
	App = app.New()
	App.SetTrustXHeaders(true)

	// Redirect all other possible hosts to governator.io
	redir := app.RedirectHandler("http://governator.io${0}", true)
	App.Handle("(.*)", redir, app.HostHandler("governator-io.appspot.com"))
	App.Handle("(.*)", redir, app.HostHandler("www.governator.io"))

	App.HandleAssets("/assets/", pathutil.Relative("assets"))
	App.Handle("^/$", app.TemplateHandler("main.html", nil))
	App.Handle("^/install\\.sh$", fileHandler("contrib/install.sh"))
	App.Handle("^/get/releases/linux/x86_64/latest/governator$", fileHandler("governator"))

	App.Handle("^/contrib/(.*)", func(ctx *app.Context) {
		path := filepath.Join(data, "contrib", filepath.FromSlash(ctx.IndexValue(0)))
		serveFile(ctx, path)
	})
}
Example #3
0
func TestXHeaders(t *testing.T) {
	a := app.New()
	a.Handle("/", func(ctx *app.Context) {
		fmt.Fprintf(ctx, "%s\n%s", ctx.RemoteAddress(), ctx.URL().String())
	})
	tt := tester.New(t, a)
	tt.Get("/", nil).AddHeader("X-Real-IP", "8.8.8.8").AddHeader("X-Scheme", "https").Expect("\nhttp://localhost/")
	a.SetTrustXHeaders(true)
	tt.Get("/", nil).AddHeader("X-Real-IP", "8.8.8.8").AddHeader("X-Scheme", "https").Expect("8.8.8.8\nhttps://localhost/")
}
Example #4
0
func TestAppendSlash(t *testing.T) {
	a := app.New()
	a.Handle("/foo/", func(ctx *app.Context) {
		ctx.WriteString("Hello world")
	})
	tt := tester.New(t, a)
	tt.Get("/foo", nil).Expect(301).ExpectHeader("Location", "/foo/")
	a.SetAppendSlash(false)
	tt.Get("/foo", nil).Expect(404)
}
Example #5
0
func TestParameters(t *testing.T) {
	a := app.New()
	a.Handle("/parse-string-param/(?P<string>\\w+)?$", func(ctx *app.Context) {
		str := "default"
		ctx.ParseParamValue("string", &str)
		ctx.WriteString(str)
	})
	a.Handle("/parse-int-param/(?P<number>\\d+)?$", func(ctx *app.Context) {
		val := -1
		ctx.ParseParamValue("number", &val)
		ctx.WriteString(strconv.Itoa(val))
	})
	a.Handle("/parse-int-form-value/$", func(ctx *app.Context) {
		val := -1
		ctx.ParseFormValue("v", &val)
		ctx.WriteString(strconv.Itoa(val))
	})
	a.Handle("/must-parse-int-form-value/$", func(ctx *app.Context) {
		val := -1
		ctx.MustParseFormValue("v", &val)
		ctx.WriteString(strconv.Itoa(val))
	})
	a.Handle("/parse-index-value/(\\d+)?$", func(ctx *app.Context) {
		val := -1
		ctx.ParseIndexValue(0, &val)
		ctx.WriteString(strconv.Itoa(val))
	})
	tester := tester.New(t, a)
	tester.Get("/parse-string-param/", nil).Expect(200).Expect("default")
	tester.Get("/parse-string-param/foo", nil).Expect(200).Expect("foo")
	tester.Get("/parse-int-param/", nil).Expect(200).Expect("-1")
	// -10 does not match the handler
	tester.Get("/parse-int-param/-10", nil).Expect(404)
	tester.Get("/parse-int-param/42", nil).Expect(200).Expect("42")

	tester.Get("/parse-int-form-value/", nil).Expect(200).Expect("-1")
	tester.Get("/parse-int-form-value/", map[string]interface{}{"v": 9000}).Expect(200).Expect("9000")
	tester.Get("/parse-int-form-value/", map[string]interface{}{"v": "not-a-number"}).Expect(200).Expect("-1")

	tester.Get("/must-parse-int-form-value/", nil).Expect(400)
	tester.Get("/must-parse-int-form-value/", map[string]interface{}{"v": 9000}).Expect(200).Expect("9000")
	tester.Get("/must-parse-int-form-value/", map[string]interface{}{"v": "not-a-number"}).Expect(400)

	tester.Get("/parse-index-value/", nil).Expect(200).Expect("-1")
	tester.Get("/parse-index-value/42", nil).Expect(200).Expect("42")
}
Example #6
0
func TestGoWait(t *testing.T) {
	a := app.New()
	a.Handle("/(no)?wait", func(ctx *app.Context) {
		value := 42
		ctx.Go(func(bg *app.Context) {
			time.Sleep(time.Second)
			value++
			panic("handled")
		})
		if ctx.IndexValue(0) != "no" {
			ctx.Wait()
		}
		fmt.Fprintf(ctx, "%d", value)
	})
	tt := tester.New(t, a)
	tt.Get("/wait", nil).Expect("43")
	tt.Get("/nowait", nil).Expect("42")
}
Example #7
0
func init() {
	testApp = app.New()
	testApp.Config().Secret = stringutil.Random(32)
	testApp.Handle("^/hello$", func(ctx *app.Context) {
		ctx.Header().Add("X-Hello", "World")
		ctx.Header().Add("X-Number", "42")
		ctx.WriteString("hello world")
	})
	testApp.Handle("^/empty$", func(ctx *app.Context) {})
	testApp.Handle("^/echo$", func(ctx *app.Context) {
		if ctx.R.Method == "POST" {
			data, err := ioutil.ReadAll(ctx.R.Body)
			if err != nil {
				panic(err)
			}
			ctx.Write(data)
		}
	})
	testApp.Handle("^/echo-form$", func(ctx *app.Context) {
		if err := ctx.R.ParseForm(); err != nil {
			panic(err)
		}
		var values url.Values
		if ctx.R.Method == "POST" || ctx.R.Method == "PUT" {
			values = ctx.R.PostForm
		} else {
			values = ctx.R.Form
		}
		keys := generic.Keys(values).([]string)
		sort.Strings(keys)
		for _, k := range keys {
			fmt.Fprintf(ctx, "%s=%s\n", k, values.Get(k))
		}
	})
	testApp.Handle("^/invalid-write-header$", func(ctx *app.Context) {
		ctx.WriteHeader(0)
	})
	testApp.Handle("^/multiple-write-header$", func(ctx *app.Context) {
		ctx.WriteHeader(200)
		ctx.WriteHeader(300)
	})
}