Beispiel #1
0
func TestPat(t *testing.T) {
	t.Parallel()

	for _, test := range PatTests {
		pat := New(test.pat)

		if str := pat.String(); str != test.pat {
			t.Errorf("[%q %q] String()=%q, expected=%q", test.pat, test.req, str, test.pat)
		}

		ctx := pat.Match(mustReq("GET", test.req))
		if (ctx != nil) != test.match {
			t.Errorf("[%q %q] match=%v, expected=%v", test.pat, test.req, ctx != nil, test.match)
		}
		if ctx == nil {
			continue
		}

		if path := pattern.Path(ctx); path != test.path {
			t.Errorf("[%q %q] path=%q, expected=%q", test.pat, test.req, path, test.path)
		}

		vars := ctx.Value(pattern.AllVariables)
		if (vars != nil) != (test.vars != nil) {
			t.Errorf("[%q %q] vars=%#v, expected=%#v", test.pat, test.req, vars, test.vars)
		}
		if vars == nil {
			continue
		}
		if tvars := vars.(map[pattern.Variable]interface{}); !reflect.DeepEqual(tvars, test.vars) {
			t.Errorf("[%q %q] vars=%v, expected=%v", test.pat, test.req, tvars, test.vars)
		}
	}
}
func (l *Logger) printRequest(ctx context.Context, r *http.Request) {
	var buf bytes.Buffer

	if l.Debug {
		buf.WriteString("[DEBUG]")
	}

	buf.WriteString("Serving route: ")

	// Goji routing details
	colorWrite(&buf, bGreen, "%s", pattern.Path(ctx))

	// Server details
	buf.WriteString(fmt.Sprintf(" from %s ", r.RemoteAddr))

	// Request details
	buf.WriteString("for ")
	colorWrite(&buf, bMagenta, "%s ", r.Method)

	urlStr := r.URL.String()

	// if not in debug mode, remove Query params from logging as not to include any
	// sensitive information inadvertantly into user's logs
	if !l.Debug && r.URL.RawQuery != "" {
		tempURL := &url.URL{}
		*tempURL = *r.URL
		tempURL.RawQuery = "<omitted>"
		urlStr = tempURL.String()
	}

	colorWrite(&buf, bBlue, "%q", urlStr)
	log.Print(buf.String())
}
Beispiel #3
0
/*
Match runs the Pat pattern on the given request, returning a non-nil context if
the request matches the request.

This function satisfies goji.Pattern.
*/
func (p *Pattern) Match(ctx context.Context, r *http.Request) context.Context {
	path := pattern.Path(ctx)
	var scratch []string
	if p.wildcard {
		scratch = make([]string, len(p.pats)+1)
	} else if len(p.pats) > 0 {
		scratch = make([]string, len(p.pats))
	}

	for i := range p.pats {
		sli := p.literals[i]
		if !strings.HasPrefix(path, sli) {
			return nil
		}
		path = path[len(sli):]

		m := 0
		bc := p.breaks[i]
		for ; m < len(path); m++ {
			if path[m] == bc || path[m] == '/' {
				break
			}
		}
		if m == 0 {
			// Empty strings are not matches, otherwise routes like
			// "/:foo" would match the path "/"
			return nil
		}
		scratch[i] = path[:m]
		path = path[m:]
	}

	// There's exactly one more literal than pat.
	tail := p.literals[len(p.pats)]
	if p.wildcard {
		if !strings.HasPrefix(path, tail) {
			return nil
		}
		scratch[len(p.pats)] = path[len(tail)-1:]
	} else if path != tail {
		return nil
	}

	for i := range p.pats {
		var err error
		scratch[i], err = unescape(scratch[i])
		if err != nil {
			// If we encounter an encoding error here, there's
			// really not much we can do about it with our current
			// API, and I'm not really interested in supporting
			// clients that misencode URLs anyways.
			return nil
		}
	}

	return &match{ctx, p, scratch}
}
Beispiel #4
0
func TestExistingContext(t *testing.T) {
	t.Parallel()

	pat := New("/hi/:c/:a/:r/:l")
	req, err := http.NewRequest("GET", "/hi/foo/bar/baz/quux", nil)
	if err != nil {
		panic(err)
	}
	ctx := context.Background()
	ctx = pattern.SetPath(ctx, req.URL.EscapedPath())
	ctx = context.WithValue(ctx, pattern.AllVariables, map[pattern.Variable]interface{}{
		"hello": "world",
		"c":     "nope",
	})
	ctx = context.WithValue(ctx, pattern.Variable("user"), "carl")

	req = req.WithContext(ctx)
	req = pat.Match(req)
	if req == nil {
		t.Fatalf("expected pattern to match")
	}
	ctx = req.Context()

	expected := map[pattern.Variable]interface{}{
		"c": "foo",
		"a": "bar",
		"r": "baz",
		"l": "quux",
	}
	for k, v := range expected {
		if p := Param(req, string(k)); p != v {
			t.Errorf("expected %s=%q, got %q", k, v, p)
		}
	}

	expected["hello"] = "world"
	all := ctx.Value(pattern.AllVariables).(map[pattern.Variable]interface{})
	if !reflect.DeepEqual(all, expected) {
		t.Errorf("expected %v, got %v", expected, all)
	}

	if path := pattern.Path(ctx); path != "" {
		t.Errorf("expected path=%q, got %q", "", path)
	}

	if user := ctx.Value(pattern.Variable("user")); user != "carl" {
		t.Errorf("expected user=%q, got %q", "carl", user)
	}
}
Beispiel #5
0
// IntegrationHandler handles webhooks to integration handlers in the integration
// package by calling their hook function with the request.
func IntegrationHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	// integration is push only with status code returns. no response output.
	dataRender := data.FromContext(ctx)
	dataRender.Type = data.DataNoRender

	// get the handler name (as the first part)
	handlerName := pattern.Path(ctx)
	impl := integration.Implementations[strings.Split(handlerName, "/")[0]]

	if impl == nil {
		http.NotFound(rw, r)
	}

	impl.Hook(r)

	rw.WriteHeader(200)
}
Beispiel #6
0
func StaticHandler(ctx context.Context, rw http.ResponseWriter, r *http.Request) {
	file := pattern.Path(ctx)

	f, err := staticDir.Open(file)
	if err != nil {
		panic(ErrNotFound) // assume not found
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		panic(err) // this is weird
	}

	// try to serve index file
	if fi.IsDir() {
		// redirect if missing trailing slash
		if !strings.HasSuffix(r.URL.Path, "/") {
			http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound)
			return
		}

		file = path.Join(file, indexFile)
		f, err = staticDir.Open(file)
		if err != nil {
			panic(ErrNotFound) // just hide its existence
		}
		defer f.Close()

		fi, err = f.Stat()
		if err != nil || fi.IsDir() {
			panic(ErrNotFound) // go away
		}
	}

	// okay, we don't need to render this.
	dataRender := data.FromContext(ctx)
	dataRender.Type = data.DataNoRender

	http.ServeContent(rw, r, file, fi.ModTime(), f)
}