Example #1
0
func nextFunc(shouldGzip bool) middleware.Handler {
	return middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
		if shouldGzip {
			if r.Header.Get("Accept-Encoding") != "" {
				return 0, fmt.Errorf("Accept-Encoding header not expected")
			}
			if w.Header().Get("Content-Encoding") != "gzip" {
				return 0, fmt.Errorf("Content-Encoding must be gzip, found %v", r.Header.Get("Content-Encoding"))
			}
			if _, ok := w.(gzipResponseWriter); !ok {
				return 0, fmt.Errorf("ResponseWriter should be gzipResponseWriter, found %T", w)
			}
			return 0, nil
		}
		if r.Header.Get("Accept-Encoding") == "" {
			return 0, fmt.Errorf("Accept-Encoding header expected")
		}
		if w.Header().Get("Content-Encoding") == "gzip" {
			return 0, fmt.Errorf("Content-Encoding must not be gzip, found gzip")
		}
		if _, ok := w.(gzipResponseWriter); ok {
			return 0, fmt.Errorf("ResponseWriter should not be gzipResponseWriter")
		}
		return 0, nil
	})
}
Example #2
0
// GET handles the GET method on browse page
func GET(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) {
	functions := template.FuncMap{
		"CanBeEdited": utils.CanBeEdited,
		"Defined":     utils.Defined,
	}

	tpl, err := utils.GetTemplate(r, functions, "browse")

	if err != nil {
		return http.StatusInternalServerError, err
	}

	b := browse.Browse{
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			return 404, nil
		}),
		Root: c.Path,
		Configs: []browse.Config{
			{
				PathScope: "/",
				Variables: c,
				Template:  tpl,
			},
		},
		IgnoreIndexes: true,
	}

	return b.ServeHTTP(w, r)
}
Example #3
0
func TestExpVar(t *testing.T) {
	rw := ExpVar{
		Next:     middleware.HandlerFunc(contentHandler),
		Resource: "/d/v",
	}

	tests := []struct {
		from   string
		result int
	}{
		{"/d/v", 0},
		{"/x/y", http.StatusOK},
	}

	for i, test := range tests {
		req, err := http.NewRequest("GET", test.from, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request %v", i, err)
		}
		rec := httptest.NewRecorder()
		result, err := rw.ServeHTTP(rec, req)
		if err != nil {
			t.Fatalf("Test %d: Could not ServeHTTP %v", i, err)
		}
		if result != test.result {
			t.Errorf("Test %d: Expected Header '%d' but was '%d'",
				i, test.result, result)
		}
	}
}
Example #4
0
func TestBrowseTemplate(t *testing.T) {
	tmpl, err := template.ParseFiles("testdata/photos.tpl")
	if err != nil {
		t.Fatalf("An error occured while parsing the template: %v", err)
	}

	b := Browse{
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			t.Fatalf("Next shouldn't be called")
			return 0, nil
		}),
		Root: "./testdata",
		Configs: []Config{
			{
				PathScope: "/photos",
				Template:  tmpl,
			},
		},
	}

	req, err := http.NewRequest("GET", "/photos/", nil)
	if err != nil {
		t.Fatalf("Test: Could not create HTTP request: %v", err)
	}

	rec := httptest.NewRecorder()

	code, err := b.ServeHTTP(rec, req)
	if code != http.StatusOK {
		t.Fatalf("Wrong status, expected %d, got %d", http.StatusOK, code)
	}

	respBody := rec.Body.String()
	expectedBody := `<!DOCTYPE html>
<html>
<head>
<title>Template</title>
</head>
<body>
<h1>Header</h1>

<h1>/photos/</h1>

<a href="./test.html">test.html</a><br>

<a href="./test2.html">test2.html</a><br>

<a href="./test3.html">test3.html</a><br>

</body>
</html>
`

	if respBody != expectedBody {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

}
Example #5
0
func genErrorHandler(status int, err error, body string) middleware.Handler {
	return middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
		if len(body) > 0 {
			w.Header().Set("Content-Length", strconv.Itoa(len(body)))
			fmt.Fprint(w, body)
		}
		return status, err
	})
}
Example #6
0
func TestBasicAuth(t *testing.T) {

	rw := BasicAuth{
		Next: middleware.HandlerFunc(contentHandler),
		Rules: []Rule{
			{Username: "******", Password: PlainMatcher("ttest"), Resources: []string{"/testing"}},
		},
	}

	tests := []struct {
		from   string
		result int
		cred   string
	}{
		{"/testing", http.StatusUnauthorized, "ttest:test"},
		{"/testing", http.StatusOK, "test:ttest"},
		{"/testing", http.StatusUnauthorized, ""},
	}

	for i, test := range tests {

		req, err := http.NewRequest("GET", test.from, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request %v", i, err)
		}
		auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(test.cred))
		req.Header.Set("Authorization", auth)

		rec := httptest.NewRecorder()
		result, err := rw.ServeHTTP(rec, req)
		if err != nil {
			t.Fatalf("Test %d: Could not ServeHTTP %v", i, err)
		}
		if result != test.result {
			t.Errorf("Test %d: Expected Header '%d' but was '%d'",
				i, test.result, result)
		}
		if result == http.StatusUnauthorized {
			headers := rec.Header()
			if val, ok := headers["Www-Authenticate"]; ok {
				if val[0] != "Basic" {
					t.Errorf("Test %d, Www-Authenticate should be %s provided %s", i, "Basic", val[0])
				}
			} else {
				t.Errorf("Test %d, should provide a header Www-Authenticate", i)
			}
		}

	}

}
Example #7
0
func nextFunc(shouldMime bool, contentType string) middleware.Handler {
	return middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
		if shouldMime {
			if w.Header().Get("Content-Type") != contentType {
				return 0, fmt.Errorf("expected Content-Type: %v, found %v", contentType, r.Header.Get("Content-Type"))
			}
			return 0, nil
		}
		if w.Header().Get("Content-Type") != "" {
			return 0, fmt.Errorf("Content-Type header not expected")
		}
		return 0, nil
	})
}
Example #8
0
func TestHeaders(t *testing.T) {
	hostname, err := os.Hostname()
	if err != nil {
		t.Fatalf("Could not determine hostname: %v", err)
	}
	for i, test := range []struct {
		from  string
		name  string
		value string
	}{
		{"/a", "Foo", "Bar"},
		{"/a", "Bar", ""},
		{"/a", "Baz", ""},
		{"/a", "ServerName", hostname},
		{"/b", "Foo", ""},
		{"/b", "Bar", "Removed in /a"},
	} {
		he := Headers{
			Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
				return 0, nil
			}),
			Rules: []Rule{
				{Path: "/a", Headers: []Header{
					{Name: "Foo", Value: "Bar"},
					{Name: "ServerName", Value: "{hostname}"},
					{Name: "-Bar"},
				}},
			},
		}

		req, err := http.NewRequest("GET", test.from, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
		}

		rec := httptest.NewRecorder()
		rec.Header().Set("Bar", "Removed in /a")

		he.ServeHTTP(rec, req)

		if got := rec.Header().Get(test.name); got != test.value {
			t.Errorf("Test %d: Expected %s header to be %q but was %q",
				i, test.name, test.value, got)
		}
	}
}
Example #9
0
func TestResponseFilterWriter(t *testing.T) {
	tests := []struct {
		body           string
		shouldCompress bool
	}{
		{"Hello\t\t\t\n", false},
		{"Hello the \t\t\t world is\n\n\n great", true},
		{"Hello \t\t\nfrom gzip", true},
		{"Hello gzip\n", false},
	}

	filters := []ResponseFilter{
		LengthFilter(15),
	}

	server := Gzip{Configs: []Config{
		{ResponseFilters: filters},
	}}

	for i, ts := range tests {
		server.Next = middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			w.Header().Set("Content-Length", fmt.Sprint(len(ts.body)))
			w.Write([]byte(ts.body))
			return 200, nil
		})

		r := urlRequest("/")
		r.Header.Set("Accept-Encoding", "gzip")

		w := httptest.NewRecorder()

		server.ServeHTTP(w, r)

		resp := w.Body.String()

		if !ts.shouldCompress {
			if resp != ts.body {
				t.Errorf("Test %v: No compression expected, found %v", i, resp)
			}
		} else {
			if resp == ts.body {
				t.Errorf("Test %v: Compression expected, found %v", i, resp)
			}
		}
	}
}
Example #10
0
func TestRedirect(t *testing.T) {
	for i, test := range []struct {
		from             string
		expectedLocation string
	}{
		{"/from", "/to"},
		{"/a", "/b"},
		{"/aa", ""},
		{"/", ""},
		{"/a?foo=bar", "/b"},
		{"/asdf?foo=bar", ""},
		{"/foo#bar", ""},
		{"/a#foo", "/b"},
	} {
		var nextCalled bool

		re := Redirect{
			Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
				nextCalled = true
				return 0, nil
			}),
			Rules: []Rule{
				{From: "/from", To: "/to"},
				{From: "/a", To: "/b"},
			},
		}

		req, err := http.NewRequest("GET", test.from, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
		}

		rec := httptest.NewRecorder()
		re.ServeHTTP(rec, req)

		if rec.Header().Get("Location") != test.expectedLocation {
			t.Errorf("Test %d: Expected Location header to be %q but was %q",
				i, test.expectedLocation, rec.Header().Get("Location"))
		}

		if nextCalled && test.expectedLocation != "" {
			t.Errorf("Test %d: Next handler was unexpectedly called", i)
		}
	}
}
Example #11
0
func TestRealIP(t *testing.T) {
	for i, test := range []struct {
		actualIP   string
		headerVal  string
		expectedIP string
	}{
		{"1.2.3.4:123", "", "1.2.3.4:123"},
		{"4.4.255.255:123", "", "4.4.255.255:123"},
		{"4.5.0.0:123", "1.2.3.4", "1.2.3.4:123"},
		{"4.5.2.3:123", "1.2.6.7,5.6.7.8,111.111.111.111", "1.2.6.7:123"},
		{"4.5.5.5:123", "NOTANIP", "4.5.5.5:123"},
		{"aaaaaa", "1.2.3.4", "aaaaaa"},
		{"aaaaaa:123", "1.2.3.4", "aaaaaa:123"},
	} {
		remoteAddr := ""
		_, ipnet, err := net.ParseCIDR("4.5.0.0/16") // "4.5.x.x"
		if err != nil {
			t.Fatal(err)
		}
		he := &module{
			next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
				remoteAddr = r.RemoteAddr
				return 0, nil
			}),
			Header: "X-Real-IP",
			From:   []*net.IPNet{ipnet},
		}

		req, err := http.NewRequest("GET", "http://foo.tld/", nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
		}
		req.RemoteAddr = test.actualIP
		if test.headerVal != "" {
			req.Header.Set("X-Real-IP", test.headerVal)
		}

		rec := httptest.NewRecorder()
		he.ServeHTTP(rec, req)

		if remoteAddr != test.expectedIP {
			t.Errorf("Test %d: Expected '%s', but found '%s'", i, test.expectedIP, remoteAddr)
		}
	}
}
Example #12
0
func TestExtensions(t *testing.T) {
	rootDir := os.TempDir()

	// create a temporary page
	path := filepath.Join(rootDir, "extensions_test.html")
	_, err := os.Create(path)
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(path)

	for i, test := range []struct {
		path        string
		extensions  []string
		expectedURL string
	}{
		{"/extensions_test", []string{".html"}, "/extensions_test.html"},
		{"/extensions_test/", []string{".html"}, "/extensions_test/"},
		{"/extensions_test", []string{".json"}, "/extensions_test"},
		{"/another_test", []string{".html"}, "/another_test"},
		{"", []string{".html"}, ""},
	} {
		ex := Ext{
			Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
				return 0, nil
			}),
			Root:       rootDir,
			Extensions: test.extensions,
		}

		req, err := http.NewRequest("GET", test.path, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
		}

		rec := httptest.NewRecorder()

		ex.ServeHTTP(rec, req)

		if got := req.URL.String(); got != test.expectedURL {
			t.Fatalf("Test %d: Got unexpected request URL: %q, wanted %q", i, got, test.expectedURL)
		}
	}
}
Example #13
0
func TestMultipleOverlappingRules(t *testing.T) {
	rw := BasicAuth{
		Next: middleware.HandlerFunc(contentHandler),
		Rules: []Rule{
			{Username: "******", Password: PlainMatcher("p1"), Resources: []string{"/t"}},
			{Username: "******", Password: PlainMatcher("p2"), Resources: []string{"/t/t"}},
		},
	}

	tests := []struct {
		from   string
		result int
		cred   string
	}{
		{"/t", http.StatusOK, "t:p1"},
		{"/t/t", http.StatusOK, "t:p1"},
		{"/t/t", http.StatusOK, "t1:p2"},
		{"/a", http.StatusOK, "t1:p2"},
		{"/t/t", http.StatusUnauthorized, "t1:p3"},
		{"/t", http.StatusUnauthorized, "t1:p2"},
	}

	for i, test := range tests {

		req, err := http.NewRequest("GET", test.from, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request %v", i, err)
		}
		auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(test.cred))
		req.Header.Set("Authorization", auth)

		rec := httptest.NewRecorder()
		result, err := rw.ServeHTTP(rec, req)
		if err != nil {
			t.Fatalf("Test %d: Could not ServeHTTP %v", i, err)
		}
		if result != test.result {
			t.Errorf("Test %d: Expected Header '%d' but was '%d'",
				i, test.result, result)
		}

	}

}
Example #14
0
func nextFunc(shouldGzip bool) middleware.Handler {
	return middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {

		// write a relatively large text file
		b, err := ioutil.ReadFile("testdata/test.txt")
		if err != nil {
			return 500, err
		}
		if _, err := w.Write(b); err != nil {
			return 500, err
		}

		if shouldGzip {
			if r.Header.Get("Accept-Encoding") != "" {
				return 0, fmt.Errorf("Accept-Encoding header not expected")
			}
			if w.Header().Get("Content-Encoding") != "gzip" {
				return 0, fmt.Errorf("Content-Encoding must be gzip, found %v", r.Header.Get("Content-Encoding"))
			}
			if w.Header().Get("Vary") != "Accept-Encoding" {
				return 0, fmt.Errorf("Vary must be Accept-Encoding, found %v", r.Header.Get("Vary"))
			}
			if _, ok := w.(*gzipResponseWriter); !ok {
				return 0, fmt.Errorf("ResponseWriter should be gzipResponseWriter, found %T", w)
			}
			if strings.Contains(w.Header().Get("Content-Type"), "application/x-gzip") {
				return 0, fmt.Errorf("Content type should not be gzip.")
			}
			return 0, nil
		}
		if r.Header.Get("Accept-Encoding") == "" {
			return 0, fmt.Errorf("Accept-Encoding header expected")
		}
		if w.Header().Get("Content-Encoding") == "gzip" {
			return 0, fmt.Errorf("Content-Encoding must not be gzip, found gzip")
		}
		if _, ok := w.(*gzipResponseWriter); ok {
			return 0, fmt.Errorf("ResponseWriter should not be gzipResponseWriter")
		}
		return 0, nil
	})
}
Example #15
0
func TestInternal(t *testing.T) {
	im := Internal{
		Next:  middleware.HandlerFunc(internalTestHandlerFunc),
		Paths: []string{"/internal"},
	}

	tests := []struct {
		url          string
		expectedCode int
		expectedBody string
	}{
		{"/internal", http.StatusNotFound, ""},

		{"/public", 0, "/public"},
		{"/public/internal", 0, "/public/internal"},

		{"/redirect", 0, "/internal"},

		{"/cycle", http.StatusInternalServerError, ""},
	}

	for i, test := range tests {
		req, err := http.NewRequest("GET", test.url, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
		}

		rec := httptest.NewRecorder()
		code, err := im.ServeHTTP(rec, req)

		if code != test.expectedCode {
			t.Errorf("Test %d: Expected status code %d for %s, but got %d",
				i, test.expectedCode, test.url, code)
		}
		if rec.Body.String() != test.expectedBody {
			t.Errorf("Test %d: Expected body '%s' for %s, but got '%s'",
				i, test.expectedBody, test.url, rec.Body.String())
		}
	}
}
Example #16
0
func TestServeHTTP(t *testing.T) {
	h := Handler{
		Next: middleware.HandlerFunc(nextHandler),
		Mux:  NewMux(),
	}

	w := httptest.NewRecorder()
	r, err := http.NewRequest("GET", "/debug/pprof", nil)
	if err != nil {
		t.Fatal(err)
	}
	status, err := h.ServeHTTP(w, r)

	if status != 0 {
		t.Errorf("Expected status %d but got %d", 0, status)
	}
	if err != nil {
		t.Errorf("Expected nil error, but got: %v", err)
	}
	if w.Body.String() == "content" {
		t.Errorf("Expected pprof to handle request, but it didn't")
	}

	w = httptest.NewRecorder()
	r, err = http.NewRequest("GET", "/foo", nil)
	if err != nil {
		t.Fatal(err)
	}
	status, err = h.ServeHTTP(w, r)
	if status != http.StatusNotFound {
		t.Errorf("Test two: Expected status %d but got %d", http.StatusNotFound, status)
	}
	if err != nil {
		t.Errorf("Test two: Expected nil error, but got: %v", err)
	}
	if w.Body.String() != "content" {
		t.Errorf("Expected pprof to pass the request thru, but it didn't; got: %s", w.Body.String())
	}
}
Example #17
0
func TestBrowseHTTPMethods(t *testing.T) {
	tmpl, err := template.ParseFiles("testdata/photos.tpl")
	if err != nil {
		t.Fatalf("An error occured while parsing the template: %v", err)
	}

	b := Browse{
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			return http.StatusTeapot, nil // not t.Fatalf, or we will not see what other methods yield
		}),
		Configs: []Config{
			{
				PathScope: "/photos",
				Root:      http.Dir("./testdata"),
				Template:  tmpl,
			},
		},
	}

	rec := httptest.NewRecorder()
	for method, expected := range map[string]int{
		http.MethodGet:     http.StatusOK,
		http.MethodHead:    http.StatusOK,
		http.MethodOptions: http.StatusNotImplemented,
		"PROPFIND":         http.StatusNotImplemented,
	} {
		req, err := http.NewRequest(method, "/photos/", nil)
		if err != nil {
			t.Fatalf("Test: Could not create HTTP request: %v", err)
		}

		code, _ := b.ServeHTTP(rec, req)
		if code != expected {
			t.Errorf("Wrong status with HTTP Method %s: expected %d, got %d", method, expected, code)
		}
	}
}
Example #18
0
func TestVisibleErrorWithPanic(t *testing.T) {
	const panicMsg = "I'm a panic"
	eh := ErrorHandler{
		ErrorPages: make(map[int]string),
		Debug:      true,
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			panic(panicMsg)
		}),
	}

	req, err := http.NewRequest("GET", "/", nil)
	if err != nil {
		t.Fatal(err)
	}
	rec := httptest.NewRecorder()

	code, err := eh.ServeHTTP(rec, req)

	if code != 0 {
		t.Errorf("Expected error handler to return 0 (it should write to response), got status %d", code)
	}
	if err != nil {
		t.Errorf("Expected error handler to return nil error (it should panic!), but got '%v'", err)
	}

	body := rec.Body.String()

	if !strings.Contains(body, "[PANIC /] middleware/errors/errors_test.go") {
		t.Errorf("Expected response body to contain error log line, but it didn't:\n%s", body)
	}
	if !strings.Contains(body, panicMsg) {
		t.Errorf("Expected response body to contain panic message, but it didn't:\n%s", body)
	}
	if len(body) < 500 {
		t.Errorf("Expected response body to contain stack trace, but it was too short: len=%d", len(body))
	}
}
Example #19
0
func TestHeaders(t *testing.T) {
	he := handler{
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			return 0, nil
		}),
	}

	req, err := http.NewRequest("GET", "/", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}

	rec := httptest.NewRecorder()

	he.ServeHTTP(rec, req)

	if got := rec.Header().Get("X-Request-Id"); got == "" {
		t.Error("Expected X-Request-Id header from rec but got nothing.")
	}

	if got := req.Header.Get("X-Request-Id"); got == "" {
		t.Error("Expected X-Request-Id header from req but got nothing.")
	}
}
Example #20
0
func TestMarkdownStaticGen(t *testing.T) {
	c := NewTestController(`markdown /blog {
	ext .md
	template tpl_with_include.html
	sitegen
}`)

	c.Root = "./testdata"
	mid, err := Markdown(c)

	if err != nil {
		t.Errorf("Expected no errors, got: %v", err)
	}

	if mid == nil {
		t.Fatal("Expected middleware, was nil instead")
	}

	for _, start := range c.Startup {
		err := start()
		if err != nil {
			t.Errorf("Startup error: %v", err)
		}
	}

	next := middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
		t.Fatalf("Next shouldn't be called")
		return 0, nil
	})
	hndlr := mid(next)
	mkdwn, ok := hndlr.(markdown.Markdown)
	if !ok {
		t.Fatalf("Was expecting a markdown.Markdown but got %T", hndlr)
	}

	expectedStaticFiles := map[string]string{"/blog/first_post.md": "testdata/generated_site/blog/first_post.md/index.html"}
	if fmt.Sprint(expectedStaticFiles) != fmt.Sprint(mkdwn.Configs[0].StaticFiles) {
		t.Fatalf("Test expected StaticFiles to be  %s, but got %s",
			fmt.Sprint(expectedStaticFiles), fmt.Sprint(mkdwn.Configs[0].StaticFiles))
	}

	filePath := "testdata/generated_site/blog/first_post.md/index.html"
	if _, err := os.Stat(filePath); err != nil {
		t.Fatalf("An error occured when getting the file information: %v", err)
	}

	html, err := ioutil.ReadFile(filePath)
	if err != nil {
		t.Fatalf("An error occured when getting the file content: %v", err)
	}

	expectedBody := `<!DOCTYPE html>
<html>
<head>
<title>first_post</title>
</head>
<body>
<h1>Header title</h1>

<h1>Test h1</h1>

</body>
</html>
`
	if string(html) != expectedBody {
		t.Fatalf("Expected file content: %v got: %v", expectedBody, html)
	}

	fp := filepath.Join(c.Root, markdown.DefaultStaticDir)
	if err = os.RemoveAll(fp); err != nil {
		t.Errorf("Error while removing the generated static files: %v", err)
	}
}
Example #21
0
func genErrorHandler(status int, err error, body string) middleware.Handler {
	return middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
		fmt.Fprint(w, body)
		return status, err
	})
}
Example #22
0
func TestMarkdown(t *testing.T) {
	rootDir := "./testdata"

	f := func(filename string) string {
		return filepath.ToSlash(rootDir + string(filepath.Separator) + filename)
	}

	md := Markdown{
		Root:    rootDir,
		FileSys: http.Dir(rootDir),
		Configs: []*Config{
			{
				Renderer:  blackfriday.HtmlRenderer(0, "", ""),
				PathScope: "/blog",
				Extensions: map[string]struct{}{
					".md": {},
				},
				Styles:   []string{},
				Scripts:  []string{},
				Template: setDefaultTemplate(f("markdown_tpl.html")),
			},
			{
				Renderer:  blackfriday.HtmlRenderer(0, "", ""),
				PathScope: "/docflags",
				Extensions: map[string]struct{}{
					".md": {},
				},
				Styles:   []string{},
				Scripts:  []string{},
				Template: setDefaultTemplate(f("docflags/template.txt")),
			},
			{
				Renderer:  blackfriday.HtmlRenderer(0, "", ""),
				PathScope: "/log",
				Extensions: map[string]struct{}{
					".md": {},
				},
				Styles:   []string{"/resources/css/log.css", "/resources/css/default.css"},
				Scripts:  []string{"/resources/js/log.js", "/resources/js/default.js"},
				Template: GetDefaultTemplate(),
			},
			{
				Renderer:  blackfriday.HtmlRenderer(0, "", ""),
				PathScope: "/og",
				Extensions: map[string]struct{}{
					".md": {},
				},
				Styles:   []string{},
				Scripts:  []string{},
				Template: setDefaultTemplate(f("markdown_tpl.html")),
			},
		},
		IndexFiles: []string{"index.html"},
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			t.Fatalf("Next shouldn't be called")
			return 0, nil
		}),
	}

	req, err := http.NewRequest("GET", "/blog/test.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}

	rec := httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}

	respBody := rec.Body.String()
	expectedBody := `<!DOCTYPE html>
<html>
<head>
<title>Markdown test 1</title>
</head>
<body>
<h1>Header for: Markdown test 1</h1>

Welcome to A Caddy website!
<h2>Welcome on the blog</h2>

<p>Body</p>

<pre><code class="language-go">func getTrue() bool {
    return true
}
</code></pre>

</body>
</html>
`
	if !equalStrings(respBody, expectedBody) {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	req, err = http.NewRequest("GET", "/docflags/test.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}
	rec = httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}
	respBody = rec.Body.String()
	expectedBody = `Doc.var_string hello
Doc.var_bool <no value>
DocFlags.var_string <no value>
DocFlags.var_bool true`

	if !equalStrings(respBody, expectedBody) {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	req, err = http.NewRequest("GET", "/log/test.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}
	rec = httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}
	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html>
<html>
	<head>
		<title>Markdown test 2</title>
		<meta charset="utf-8">
		<link rel="stylesheet" href="/resources/css/log.css">
		<link rel="stylesheet" href="/resources/css/default.css">
		<script src="/resources/js/log.js"></script>
		<script src="/resources/js/default.js"></script>
	</head>
	<body>
		<h2>Welcome on the blog</h2>

<p>Body</p>

<pre><code class="language-go">func getTrue() bool {
    return true
}
</code></pre>

	</body>
</html>`

	if !equalStrings(respBody, expectedBody) {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	req, err = http.NewRequest("GET", "/og/first.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}
	rec = httptest.NewRecorder()
	currenttime := time.Now().Local().Add(-time.Second)
	_ = os.Chtimes("testdata/og/first.md", currenttime, currenttime)
	currenttime = time.Now().Local()
	_ = os.Chtimes("testdata/og_static/og/first.md/index.html", currenttime, currenttime)
	time.Sleep(time.Millisecond * 200)

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}
	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html>
<html>
<head>
<title>first_post</title>
</head>
<body>
<h1>Header for: first_post</h1>

Welcome to title!
<h1>Test h1</h1>

</body>
</html>`

	if !equalStrings(respBody, expectedBody) {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}
}
Example #23
0
func Test(t *testing.T) {
	tmpl := Templates{
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			return 0, nil
		}),
		Rules: []Rule{
			{
				Extensions: []string{".html"},
				IndexFiles: []string{"index.html"},
				Path:       "/photos",
			},
			{
				Extensions: []string{".html", ".htm"},
				IndexFiles: []string{"index.html", "index.htm"},
				Path:       "/images",
				Delims:     [2]string{"{%", "%}"},
			},
		},
		Root:    "./testdata",
		FileSys: http.Dir("./testdata"),
	}

	tmplroot := Templates{
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			return 0, nil
		}),
		Rules: []Rule{
			{
				Extensions: []string{".html"},
				IndexFiles: []string{"index.html"},
				Path:       "/",
			},
		},
		Root:    "./testdata",
		FileSys: http.Dir("./testdata"),
	}

	/*
	* Test tmpl on /photos/test.html
	 */
	req, err := http.NewRequest("GET", "/photos/test.html", nil)
	if err != nil {
		t.Fatalf("Test: Could not create HTTP request: %v", err)
	}

	rec := httptest.NewRecorder()

	tmpl.ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("Test: Wrong response code: %d, should be %d", rec.Code, http.StatusOK)
	}

	respBody := rec.Body.String()
	expectedBody := `<!DOCTYPE html><html><head><title>test page</title></head><body><h1>Header title</h1>
</body></html>
`

	if respBody != expectedBody {
		t.Fatalf("Test: the expected body %v is different from the response one: %v", expectedBody, respBody)
	}

	/*
	* Test tmpl on /images/img.htm
	 */
	req, err = http.NewRequest("GET", "/images/img.htm", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}

	rec = httptest.NewRecorder()

	tmpl.ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("Test: Wrong response code: %d, should be %d", rec.Code, http.StatusOK)
	}

	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html><html><head><title>img</title></head><body><h1>Header title</h1>
</body></html>
`

	if respBody != expectedBody {
		t.Fatalf("Test: the expected body %v is different from the response one: %v", expectedBody, respBody)
	}

	/*
	* Test tmpl on /images/img2.htm
	 */
	req, err = http.NewRequest("GET", "/images/img2.htm", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}

	rec = httptest.NewRecorder()

	tmpl.ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("Test: Wrong response code: %d, should be %d", rec.Code, http.StatusOK)
	}

	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html><html><head><title>img</title></head><body>{{.Include "header.html"}}</body></html>
`

	if respBody != expectedBody {
		t.Fatalf("Test: the expected body %v is different from the response one: %v", expectedBody, respBody)
	}

	/*
	* Test tmplroot on /root.html
	 */
	req, err = http.NewRequest("GET", "/root.html", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}

	rec = httptest.NewRecorder()

	tmplroot.ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("Test: Wrong response code: %d, should be %d", rec.Code, http.StatusOK)
	}

	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html><html><head><title>root</title></head><body><h1>Header title</h1>
</body></html>
`

	if respBody != expectedBody {
		t.Fatalf("Test: the expected body %v is different from the response one: %v", expectedBody, respBody)
	}
}
Example #24
0
//
// Used primarily for testing but needs to be exported so
// add-ons can use this as a convenience. Does not initialize
// the server-block-related fields.
func NewTestController(input string) *Controller {
	return &Controller{
		Config: &server.Config{
			Root: ".",
		},
		Dispenser: parse.NewDispenser("Testfile", strings.NewReader(input)),
	}
}

// EmptyNext is a no-op function that can be passed into
// middleware.Middleware functions so that the assignment
// to the Next field of the Handler can be tested.
//
// Used primarily for testing but needs to be exported so
// add-ons can use this as a convenience.
var EmptyNext = middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
	return 0, nil
})

// SameNext does a pointer comparison between next1 and next2.
//
// Used primarily for testing but needs to be exported so
// add-ons can use this as a convenience.
func SameNext(next1, next2 middleware.Handler) bool {
	return fmt.Sprintf("%v", next1) == fmt.Sprintf("%v", next2)
}
Example #25
0
func TestRewrite(t *testing.T) {
	rw := Rewrite{
		Next: middleware.HandlerFunc(urlPrinter),
		Rules: []Rule{
			NewSimpleRule("/from", "/to"),
			NewSimpleRule("/a", "/b"),
			NewSimpleRule("/b", "/b{uri}"),
		},
		FileSys: http.Dir("."),
	}

	regexps := [][]string{
		{"/reg/", ".*", "/to", ""},
		{"/r/", "[a-z]+", "/toaz", "!.html|"},
		{"/url/", "a([a-z0-9]*)s([A-Z]{2})", "/to/{path}", ""},
		{"/ab/", "ab", "/ab?{query}", ".txt|"},
		{"/ab/", "ab", "/ab?type=html&{query}", ".html|"},
		{"/abc/", "ab", "/abc/{file}", ".html|"},
		{"/abcd/", "ab", "/a/{dir}/{file}", ".html|"},
		{"/abcde/", "ab", "/a#{fragment}", ".html|"},
		{"/ab/", `.*\.jpg`, "/ajpg", ""},
		{"/reggrp", `/ad/([0-9]+)([a-z]*)`, "/a{1}/{2}", ""},
		{"/reg2grp", `(.*)`, "/{1}", ""},
		{"/reg3grp", `(.*)/(.*)/(.*)`, "/{1}{2}{3}", ""},
	}

	for _, regexpRule := range regexps {
		var ext []string
		if s := strings.Split(regexpRule[3], "|"); len(s) > 1 {
			ext = s[:len(s)-1]
		}
		rule, err := NewComplexRule(regexpRule[0], regexpRule[1], regexpRule[2], 0, ext, nil)
		if err != nil {
			t.Fatal(err)
		}
		rw.Rules = append(rw.Rules, rule)
	}

	tests := []struct {
		from       string
		expectedTo string
	}{
		{"/from", "/to"},
		{"/a", "/b"},
		{"/b", "/b/b"},
		{"/aa", "/aa"},
		{"/", "/"},
		{"/a?foo=bar", "/b?foo=bar"},
		{"/asdf?foo=bar", "/asdf?foo=bar"},
		{"/foo#bar", "/foo#bar"},
		{"/a#foo", "/b#foo"},
		{"/reg/foo", "/to"},
		{"/re", "/re"},
		{"/r/", "/r/"},
		{"/r/123", "/r/123"},
		{"/r/a123", "/toaz"},
		{"/r/abcz", "/toaz"},
		{"/r/z", "/toaz"},
		{"/r/z.html", "/r/z.html"},
		{"/r/z.js", "/toaz"},
		{"/url/asAB", "/to/url/asAB"},
		{"/url/aBsAB", "/url/aBsAB"},
		{"/url/a00sAB", "/to/url/a00sAB"},
		{"/url/a0z0sAB", "/to/url/a0z0sAB"},
		{"/ab/aa", "/ab/aa"},
		{"/ab/ab", "/ab/ab"},
		{"/ab/ab.txt", "/ab"},
		{"/ab/ab.txt?name=name", "/ab?name=name"},
		{"/ab/ab.html?name=name", "/ab?type=html&name=name"},
		{"/abc/ab.html", "/abc/ab.html"},
		{"/abcd/abcd.html", "/a/abcd/abcd.html"},
		{"/abcde/abcde.html", "/a"},
		{"/abcde/abcde.html#1234", "/a#1234"},
		{"/ab/ab.jpg", "/ajpg"},
		{"/reggrp/ad/12", "/a12"},
		{"/reggrp/ad/124a", "/a124/a"},
		{"/reggrp/ad/124abc", "/a124/abc"},
		{"/reg2grp/ad/124abc", "/ad/124abc"},
		{"/reg3grp/ad/aa/66", "/adaa66"},
		{"/reg3grp/ad612/n1n/ab", "/ad612n1nab"},
	}

	for i, test := range tests {
		req, err := http.NewRequest("GET", test.from, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
		}

		rec := httptest.NewRecorder()
		rw.ServeHTTP(rec, req)

		if rec.Body.String() != test.expectedTo {
			t.Errorf("Test %d: Expected URL to be '%s' but was '%s'",
				i, test.expectedTo, rec.Body.String())
		}
	}

	statusTests := []struct {
		status         int
		base           string
		to             string
		regexp         string
		statusExpected bool
	}{
		{400, "/status", "", "", true},
		{400, "/ignore", "", "", false},
		{400, "/", "", "^/ignore", false},
		{400, "/", "", "(.*)", true},
		{400, "/status", "", "", true},
	}

	for i, s := range statusTests {
		urlPath := fmt.Sprintf("/status%d", i)
		rule, err := NewComplexRule(s.base, s.regexp, s.to, s.status, nil, nil)
		if err != nil {
			t.Fatalf("Test %d: No error expected for rule but found %v", i, err)
		}
		rw.Rules = []Rule{rule}
		req, err := http.NewRequest("GET", urlPath, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
		}

		rec := httptest.NewRecorder()
		code, err := rw.ServeHTTP(rec, req)
		if err != nil {
			t.Fatalf("Test %d: No error expected for handler but found %v", i, err)
		}
		if s.statusExpected {
			if rec.Body.String() != "" {
				t.Errorf("Test %d: Expected empty body but found %s", i, rec.Body.String())
			}
			if code != s.status {
				t.Errorf("Test %d: Expected status code %d found %d", i, s.status, code)
			}
		} else {
			if code != 0 {
				t.Errorf("Test %d: Expected no status code found %d", i, code)
			}
		}
	}
}
Example #26
0
func TestBrowseJson(t *testing.T) {

	b := Browse{
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			t.Fatalf("Next shouldn't be called")
			return 0, nil
		}),
		Root: "./testdata",
		Configs: []Config{
			Config{
				PathScope: "/photos",
			},
		},
	}

	req, err := http.NewRequest("GET", "/photos/", nil)
	if err != nil {
		t.Fatalf("Test: Could not create HTTP request: %v", err)
	}
	req.Header.Set("Accept", "application/json")
	rec := httptest.NewRecorder()

	b.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected %d, got %d", http.StatusOK, rec.Code)
	}
	if rec.HeaderMap.Get("Content-Type") != "application/json; charset=utf-8" {
		t.Fatalf("Expected Content type to be application/json; charset=utf-8, but got %s ", rec.HeaderMap.Get("Content-Type"))
	}

	actualJsonResponseString := rec.Body.String()

	//generating the listing to compare it with the response body
	file, err := os.Open(b.Root + req.URL.Path)
	if err != nil {
		if os.IsPermission(err) {
			t.Fatalf("Os Permission Error")

		}

	}
	defer file.Close()

	files, err := file.Readdir(-1)
	if err != nil {
		t.Fatalf("Unable to Read Contents of the directory")
	}
	var fileinfos []FileInfo
	for _, f := range files {
		name := f.Name()

		if f.IsDir() {
			name += "/"
		}

		url := url.URL{Path: name}

		fileinfos = append(fileinfos, FileInfo{
			IsDir:   f.IsDir(),
			Name:    f.Name(),
			Size:    f.Size(),
			URL:     url.String(),
			ModTime: f.ModTime(),
			Mode:    f.Mode(),
		})
	}
	listing := Listing{
		Items: fileinfos,
	}
	listing.Sort = "name"
	listing.Order = "asc"
	listing.applySort()

	marsh, err := json.Marshal(listing.Items)
	if err != nil {
		t.Fatalf("Unable to Marshal the listing ")
	}
	expectedJsonString := string(marsh)
	if actualJsonResponseString != expectedJsonString {
		t.Errorf("Json response string doesnt match the expected Json response ")
	}
}
Example #27
0
func TestRewrite(t *testing.T) {
	rw := Rewrite{
		Next: middleware.HandlerFunc(urlPrinter),
		Rules: []Rule{
			NewSimpleRule("/from", "/to"),
			NewSimpleRule("/a", "/b"),
		},
	}

	regexpRules := [][]string{
		[]string{"/reg/", ".*", "/to", ""},
		[]string{"/r/", "[a-z]+", "/toaz", "!.html|"},
		[]string{"/url/", "a([a-z0-9]*)s([A-Z]{2})", "/to/{path}", ""},
		[]string{"/ab/", "ab", "/ab?{query}", ".txt|"},
		[]string{"/ab/", "ab", "/ab?type=html&{query}", ".html|"},
		[]string{"/abc/", "ab", "/abc/{file}", ".html|"},
		[]string{"/abcd/", "ab", "/a/{dir}/{file}", ".html|"},
		[]string{"/abcde/", "ab", "/a#{frag}", ".html|"},
		[]string{"/ab/", `.*\.jpg`, "/ajpg", ""},
	}

	for _, regexpRule := range regexpRules {
		var ext []string
		if s := strings.Split(regexpRule[3], "|"); len(s) > 1 {
			ext = s[:len(s)-1]
		}
		rule, err := NewRegexpRule(regexpRule[0], regexpRule[1], regexpRule[2], ext)
		if err != nil {
			t.Fatal(err)
		}
		rw.Rules = append(rw.Rules, rule)
	}

	tests := []struct {
		from       string
		expectedTo string
	}{
		{"/from", "/to"},
		{"/a", "/b"},
		{"/aa", "/aa"},
		{"/", "/"},
		{"/a?foo=bar", "/b?foo=bar"},
		{"/asdf?foo=bar", "/asdf?foo=bar"},
		{"/foo#bar", "/foo#bar"},
		{"/a#foo", "/b#foo"},
		{"/reg/foo", "/to"},
		{"/re", "/re"},
		{"/r/", "/r/"},
		{"/r/123", "/r/123"},
		{"/r/a123", "/toaz"},
		{"/r/abcz", "/toaz"},
		{"/r/z", "/toaz"},
		{"/r/z.html", "/r/z.html"},
		{"/r/z.js", "/toaz"},
		{"/url/asAB", "/to/url/asAB"},
		{"/url/aBsAB", "/url/aBsAB"},
		{"/url/a00sAB", "/to/url/a00sAB"},
		{"/url/a0z0sAB", "/to/url/a0z0sAB"},
		{"/ab/aa", "/ab/aa"},
		{"/ab/ab", "/ab/ab"},
		{"/ab/ab.txt", "/ab"},
		{"/ab/ab.txt?name=name", "/ab?name=name"},
		{"/ab/ab.html?name=name", "/ab?type=html&name=name"},
		{"/abc/ab.html", "/abc/ab.html"},
		{"/abcd/abcd.html", "/a/abcd/abcd.html"},
		{"/abcde/abcde.html", "/a"},
		{"/abcde/abcde.html#1234", "/a#1234"},
		{"/ab/ab.jpg", "/ajpg"},
	}

	for i, test := range tests {
		req, err := http.NewRequest("GET", test.from, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
		}

		rec := httptest.NewRecorder()
		rw.ServeHTTP(rec, req)

		if rec.Body.String() != test.expectedTo {
			t.Errorf("Test %d: Expected URL to be '%s' but was '%s'",
				i, test.expectedTo, rec.Body.String())
		}
	}
}
Example #28
0
func TestRedirect(t *testing.T) {
	for i, test := range []struct {
		from             string
		expectedLocation string
		expectedCode     int
	}{
		{"http://localhost/from", "/to", http.StatusMovedPermanently},
		{"http://localhost/a", "/b", http.StatusTemporaryRedirect},
		{"http://localhost/aa", "", http.StatusOK},
		{"http://localhost/", "", http.StatusOK},
		{"http://localhost/a?foo=bar", "/b", http.StatusTemporaryRedirect},
		{"http://localhost/asdf?foo=bar", "", http.StatusOK},
		{"http://localhost/foo#bar", "", http.StatusOK},
		{"http://localhost/a#foo", "/b", http.StatusTemporaryRedirect},

		// The scheme checks that were added to this package don't actually
		// help with redirects because of Caddy's design: a redirect middleware
		// for http will always be different than the redirect middleware for
		// https because they have to be on different listeners. These tests
		// just go to show extra bulletproofing, I guess.
		{"http://localhost/scheme", "https://localhost/scheme", http.StatusMovedPermanently},
		{"https://localhost/scheme", "", http.StatusOK},
		{"https://localhost/scheme2", "http://localhost/scheme2", http.StatusMovedPermanently},
		{"http://localhost/scheme2", "", http.StatusOK},
		{"http://localhost/scheme3", "https://localhost/scheme3", http.StatusMovedPermanently},
		{"https://localhost/scheme3", "", http.StatusOK},
	} {
		var nextCalled bool

		re := Redirect{
			Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
				nextCalled = true
				return 0, nil
			}),
			Rules: []Rule{
				{FromPath: "/from", To: "/to", Code: http.StatusMovedPermanently},
				{FromPath: "/a", To: "/b", Code: http.StatusTemporaryRedirect},

				// These http and https schemes would never actually be mixed in the same
				// redirect rule with Caddy because http and https schemes have different listeners,
				// so they don't share a redirect rule. So although these tests prove something
				// impossible with Caddy, it's extra bulletproofing at very little cost.
				{FromScheme: "http", FromPath: "/scheme", To: "https://localhost/scheme", Code: http.StatusMovedPermanently},
				{FromScheme: "https", FromPath: "/scheme2", To: "http://localhost/scheme2", Code: http.StatusMovedPermanently},
				{FromScheme: "", FromPath: "/scheme3", To: "https://localhost/scheme3", Code: http.StatusMovedPermanently},
			},
		}

		req, err := http.NewRequest("GET", test.from, nil)
		if err != nil {
			t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
		}
		if strings.HasPrefix(test.from, "https://") {
			req.TLS = new(tls.ConnectionState) // faux HTTPS
		}

		rec := httptest.NewRecorder()
		re.ServeHTTP(rec, req)

		if rec.Header().Get("Location") != test.expectedLocation {
			t.Errorf("Test %d: Expected Location header to be %q but was %q",
				i, test.expectedLocation, rec.Header().Get("Location"))
		}

		if rec.Code != test.expectedCode {
			t.Errorf("Test %d: Expected status code to be %d but was %d",
				i, test.expectedCode, rec.Code)
		}

		if nextCalled && test.expectedLocation != "" {
			t.Errorf("Test %d: Next handler was unexpectedly called", i)
		}
	}
}
Example #29
0
func TestMarkdown(t *testing.T) {
	templates := make(map[string]string)
	templates[DefaultTemplate] = "testdata/markdown_tpl.html"
	md := Markdown{
		Root:    "./testdata",
		FileSys: http.Dir("./testdata"),
		Configs: []*Config{
			&Config{
				Renderer:    blackfriday.HtmlRenderer(0, "", ""),
				PathScope:   "/blog",
				Extensions:  []string{".md"},
				Styles:      []string{},
				Scripts:     []string{},
				Templates:   templates,
				StaticDir:   DefaultStaticDir,
				StaticFiles: make(map[string]string),
			},
			&Config{
				Renderer:    blackfriday.HtmlRenderer(0, "", ""),
				PathScope:   "/log",
				Extensions:  []string{".md"},
				Styles:      []string{"/resources/css/log.css", "/resources/css/default.css"},
				Scripts:     []string{"/resources/js/log.js", "/resources/js/default.js"},
				Templates:   make(map[string]string),
				StaticDir:   DefaultStaticDir,
				StaticFiles: make(map[string]string),
			},
			&Config{
				Renderer:    blackfriday.HtmlRenderer(0, "", ""),
				PathScope:   "/og",
				Extensions:  []string{".md"},
				Styles:      []string{},
				Scripts:     []string{},
				Templates:   templates,
				StaticDir:   "testdata/og_static",
				StaticFiles: map[string]string{"/og/first.md": "testdata/og_static/og/first.md/index.html"},
				Links: []PageLink{
					PageLink{
						Title:   "first",
						Summary: "",
						Date:    time.Now(),
						URL:     "/og/first.md",
					},
				},
			},
		},
		IndexFiles: []string{"index.html"},
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			t.Fatalf("Next shouldn't be called")
			return 0, nil
		}),
	}

	for i := range md.Configs {
		c := md.Configs[i]
		if err := GenerateStatic(md, c); err != nil {
			t.Fatalf("Error: %v", err)
		}
		Watch(md, c, time.Millisecond*100)
	}

	req, err := http.NewRequest("GET", "/blog/test.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}

	rec := httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}

	respBody := rec.Body.String()
	expectedBody := `<!DOCTYPE html>
<html>
<head>
<title>Markdown test</title>
</head>
<body>
<h1>Header</h1>

Welcome to A Caddy website!
<h2>Welcome on the blog</h2>

<p>Body</p>

<p><code>go
func getTrue() bool {
    return true
}
</code></p>

</body>
</html>
`
	if !equalStrings(respBody, expectedBody) {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	req, err = http.NewRequest("GET", "/log/test.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}
	rec = httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}
	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html>
<html>
	<head>
		<title>Markdown test</title>
		<meta charset="utf-8">
		<link rel="stylesheet" href="/resources/css/log.css">
<link rel="stylesheet" href="/resources/css/default.css">

		<script src="/resources/js/log.js"></script>
<script src="/resources/js/default.js"></script>

	</head>
	<body>
		<h2>Welcome on the blog</h2>

<p>Body</p>

<p><code>go
func getTrue() bool {
    return true
}
</code></p>

	</body>
</html>`

	if !equalStrings(respBody, expectedBody) {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	req, err = http.NewRequest("GET", "/og/first.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}
	rec = httptest.NewRecorder()
	currenttime := time.Now().Local().Add(-time.Second)
	err = os.Chtimes("testdata/og/first.md", currenttime, currenttime)
	currenttime = time.Now().Local()
	err = os.Chtimes("testdata/og_static/og/first.md/index.html", currenttime, currenttime)
	time.Sleep(time.Millisecond * 200)

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}
	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html>
<html>
<head>
<title>first_post</title>
</head>
<body>
<h1>Header</h1>

Welcome to title!
<h1>Test h1</h1>

</body>
</html>`

	if !equalStrings(respBody, expectedBody) {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	expectedLinks := []string{
		"/blog/test.md",
		"/log/test.md",
	}

	for i, c := range md.Configs[:2] {
		log.Printf("Test number: %d, configuration links: %v, config: %v", i, c.Links, c)
		if c.Links[0].URL != expectedLinks[i] {
			t.Fatalf("Expected %v got %v", expectedLinks[i], c.Links[0].URL)
		}
	}

	// attempt to trigger race conditions
	var w sync.WaitGroup
	f := func() {
		req, err := http.NewRequest("GET", "/log/test.md", nil)
		if err != nil {
			t.Fatalf("Could not create HTTP request: %v", err)
		}
		rec := httptest.NewRecorder()

		md.ServeHTTP(rec, req)
		w.Done()
	}
	for i := 0; i < 5; i++ {
		w.Add(1)
		go f()
	}
	w.Wait()

	f = func() {
		GenerateStatic(md, md.Configs[0])
		w.Done()
	}
	for i := 0; i < 5; i++ {
		w.Add(1)
		go f()
	}
	w.Wait()

	if err = os.RemoveAll(DefaultStaticDir); err != nil {
		t.Errorf("Error while removing the generated static files: %v", err)
	}

}
Example #30
0
func TestBrowseJson(t *testing.T) {

	b := Browse{
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			t.Fatalf("Next shouldn't be called")
			return 0, nil
		}),
		Root: "./testdata",
		Configs: []Config{
			{
				PathScope: "/photos/",
			},
		},
	}

	//Getting the listing from the ./testdata/photos, the listing returned will be used to validate test results
	testDataPath := b.Root + "/photos/"
	file, err := os.Open(testDataPath)
	if err != nil {
		if os.IsPermission(err) {
			t.Fatalf("Os Permission Error")
		}
	}
	defer file.Close()

	files, err := file.Readdir(-1)
	if err != nil {
		t.Fatalf("Unable to Read Contents of the directory")
	}
	var fileinfos []FileInfo

	for i, f := range files {
		name := f.Name()

		// Tests fail in CI environment because all file mod times are the same for
		// some reason, making the sorting unpredictable. To hack around this,
		// we ensure here that each file has a different mod time.
		chTime := f.ModTime().Add(-(time.Duration(i) * time.Second))
		if err := os.Chtimes(filepath.Join(testDataPath, name), chTime, chTime); err != nil {
			t.Fatal(err)
		}

		if f.IsDir() {
			name += "/"
		}

		url := url.URL{Path: "./" + name}

		fileinfos = append(fileinfos, FileInfo{
			IsDir:   f.IsDir(),
			Name:    f.Name(),
			Size:    f.Size(),
			URL:     url.String(),
			ModTime: chTime,
			Mode:    f.Mode(),
		})
	}
	listing := Listing{Items: fileinfos} // this listing will be used for validation inside the tests

	tests := []struct {
		QueryURL       string
		SortBy         string
		OrderBy        string
		Limit          int
		shouldErr      bool
		expectedResult []FileInfo
	}{
		//test case 1: testing for default sort and  order and without the limit parameter, default sort is by name and the default order is ascending
		//without the limit query entire listing will be produced
		{"/", "", "", -1, false, listing.Items},
		//test case 2: limit is set to 1, orderBy and sortBy is default
		{"/?limit=1", "", "", 1, false, listing.Items[:1]},
		//test case 3 : if the listing request is bigger than total size of listing then it should return everything
		{"/?limit=100000000", "", "", 100000000, false, listing.Items},
		//test case 4 : testing for negative limit
		{"/?limit=-1", "", "", -1, false, listing.Items},
		//test case 5 : testing with limit set to -1 and order set to descending
		{"/?limit=-1&order=desc", "", "desc", -1, false, listing.Items},
		//test case 6 : testing with limit set to 2 and order set to descending
		{"/?limit=2&order=desc", "", "desc", 2, false, listing.Items},
		//test case 7 : testing with limit set to 3 and order set to descending
		{"/?limit=3&order=desc", "", "desc", 3, false, listing.Items},
		//test case 8 : testing with limit set to 3 and order set to ascending
		{"/?limit=3&order=asc", "", "asc", 3, false, listing.Items},
		//test case 9 : testing with limit set to 1111111 and order set to ascending
		{"/?limit=1111111&order=asc", "", "asc", 1111111, false, listing.Items},
		//test case 10 : testing with limit set to default and order set to ascending and sorting by size
		{"/?order=asc&sort=size", "size", "asc", -1, false, listing.Items},
		//test case 11 : testing with limit set to default and order set to ascending and sorting by last modified
		{"/?order=asc&sort=time", "time", "asc", -1, false, listing.Items},
		//test case 12 : testing with limit set to 1 and order set to ascending and sorting by last modified
		{"/?order=asc&sort=time&limit=1", "time", "asc", 1, false, listing.Items},
		//test case 13 : testing with limit set to -100 and order set to ascending and sorting by last modified
		{"/?order=asc&sort=time&limit=-100", "time", "asc", -100, false, listing.Items},
		//test case 14 : testing with limit set to -100 and order set to ascending and sorting by size
		{"/?order=asc&sort=size&limit=-100", "size", "asc", -100, false, listing.Items},
	}

	for i, test := range tests {
		var marsh []byte
		req, err := http.NewRequest("GET", "/photos"+test.QueryURL, nil)

		if err == nil && test.shouldErr {
			t.Errorf("Test %d didn't error, but it should have", i)
		} else if err != nil && !test.shouldErr {
			t.Errorf("Test %d errored, but it shouldn't have; got '%v'", i, err)
		}

		req.Header.Set("Accept", "application/json")
		rec := httptest.NewRecorder()

		code, err := b.ServeHTTP(rec, req)

		if code != http.StatusOK {
			t.Fatalf("Wrong status, expected %d, got %d", http.StatusOK, code)
		}
		if rec.HeaderMap.Get("Content-Type") != "application/json; charset=utf-8" {
			t.Fatalf("Expected Content type to be application/json; charset=utf-8, but got %s ", rec.HeaderMap.Get("Content-Type"))
		}

		actualJSONResponse := rec.Body.String()
		copyOflisting := listing
		if test.SortBy == "" {
			copyOflisting.Sort = "name"
		} else {
			copyOflisting.Sort = test.SortBy
		}
		if test.OrderBy == "" {
			copyOflisting.Order = "asc"
		} else {
			copyOflisting.Order = test.OrderBy
		}

		copyOflisting.applySort()

		limit := test.Limit
		if limit <= len(copyOflisting.Items) && limit > 0 {
			marsh, err = json.Marshal(copyOflisting.Items[:limit])
		} else { // if the 'limit' query is empty, or has the wrong value, list everything
			marsh, err = json.Marshal(copyOflisting.Items)
		}

		if err != nil {
			t.Fatalf("Unable to Marshal the listing ")
		}
		expectedJSON := string(marsh)

		if actualJSONResponse != expectedJSON {
			t.Errorf("JSON response doesn't match the expected for test number %d with sort=%s, order=%s\nExpected response %s\nActual response = %s\n",
				i+1, test.SortBy, test.OrderBy, expectedJSON, actualJSONResponse)
		}
	}
}