Skip to content

Commit

Permalink
Merge pull request #45 for v0.5.1 Release
Browse files Browse the repository at this point in the history
  • Loading branch information
jeevatkm authored May 21, 2017
2 parents e14192d + 40f36d8 commit e0e9fbe
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 54 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# aah web framework for Go
[![Build Status](https://travis-ci.org/go-aah/aah.svg?branch=master)](https://travis-ci.org/go-aah/aah) [![codecov](https://codecov.io/gh/go-aah/aah/branch/master/graph/badge.svg)](https://codecov.io/gh/go-aah/aah/branch/master) [![Go Report Card](https://goreportcard.com/badge/aahframework.org/aah.v0)](https://goreportcard.com/report/aahframework.org/aah.v0)
[![Powered by Go](https://img.shields.io/badge/powered_by-go-blue.svg)](https://golang.org)
[![Version](https://img.shields.io/badge/version-0.5-blue.svg)](https://github.com/go-aah/aah/releases/latest) [![GoDoc](https://godoc.org/aahframework.org/aah.v0?status.svg)](https://godoc.org/aahframework.org/aah.v0)
[![Version](https://img.shields.io/badge/version-0.5.1-blue.svg)](https://github.com/go-aah/aah/releases/latest) [![GoDoc](https://godoc.org/aahframework.org/aah.v0?status.svg)](https://godoc.org/aahframework.org/aah.v0)
[![License](https://img.shields.io/github/license/go-aah/aah.svg)](LICENSE)

***Release [v0.5](https://github.com/go-aah/aah/releases/latest) tagged on May 19, 2017***
***Release [v0.5.1](https://github.com/go-aah/aah/releases/latest) tagged on May 21, 2017***

aah framework - A scalable, performant, rapid development Web framework for Go.

Expand Down
2 changes: 1 addition & 1 deletion aah.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
)

// Version no. of aah framework
const Version = "0.5"
const Version = "0.5.1"

// aah application variables
var (
Expand Down
2 changes: 1 addition & 1 deletion aah_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func TestAahRecover(t *testing.T) {
}

func TestAahLogDir(t *testing.T) {
logsDir := filepath.Join(getTestdataPath(), "logs")
logsDir := filepath.Join(getTestdataPath(), appLogsDir())
logFile := filepath.Join(logsDir, "test.log")
defer ess.DeleteFiles(logsDir)

Expand Down
14 changes: 7 additions & 7 deletions context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,12 @@ func TestContextNil(t *testing.T) {
func TestContextEmbeddedAndController(t *testing.T) {
addToCRegistry()

assertEmbeddedIndexes(t, Level1{}, [][]int{{0}})
assertEmbeddedIndexes(t, Level2{}, [][]int{{0, 0}})
assertEmbeddedIndexes(t, Level3{}, [][]int{{0, 0, 0}})
assertEmbeddedIndexes(t, Level4{}, [][]int{{0, 0, 0, 0}})
assertEmbeddedIndexes(t, Path1{}, [][]int{{1}})
assertEmbeddedIndexes(t, Path2{}, [][]int{{0, 0}, {1, 1}, {2, 0, 0, 0, 0}})
testEmbeddedIndexes(t, Level1{}, [][]int{{0}})
testEmbeddedIndexes(t, Level2{}, [][]int{{0, 0}})
testEmbeddedIndexes(t, Level3{}, [][]int{{0, 0, 0}})
testEmbeddedIndexes(t, Level4{}, [][]int{{0, 0, 0, 0}})
testEmbeddedIndexes(t, Path1{}, [][]int{{1}})
testEmbeddedIndexes(t, Path2{}, [][]int{{0, 0}, {1, 1}, {2, 0, 0, 0, 0}})
}

func TestContextSetURL(t *testing.T) {
Expand Down Expand Up @@ -234,7 +234,7 @@ func TestContextSetMethod(t *testing.T) {
assert.Equal(t, "GET", ctx.Req.Method)
}

func assertEmbeddedIndexes(t *testing.T, c interface{}, expected [][]int) {
func testEmbeddedIndexes(t *testing.T, c interface{}, expected [][]int) {
actual := findEmbeddedContext(reflect.TypeOf(c))
if !reflect.DeepEqual(expected, actual) {
t.Errorf("Indexes do not match. expected %v actual %v", expected, actual)
Expand Down
4 changes: 1 addition & 3 deletions param_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"testing"

"aahframework.org/ahttp.v0"
ess "aahframework.org/essentials.v0"
"aahframework.org/essentials.v0"
"aahframework.org/test.v0/assert"
)

Expand Down Expand Up @@ -46,8 +46,6 @@ func TestParamTemplateFuncs(t *testing.T) {

func TestParamParse(t *testing.T) {
defer ess.DeleteFiles("testapp.pid")
testEng.Lock()
defer testEng.Unlock()

r1 := httptest.NewRequest("GET", "http://localhost:8080/index.html?lang=en-CA", nil)
ctx1 := &Context{
Expand Down
6 changes: 2 additions & 4 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ func TestServerStart1(t *testing.T) {

func TestServerStart2(t *testing.T) {
defer ess.DeleteFiles("testapp.pid")
testEng.Lock()
defer testEng.Unlock()

// App Config
cfgDir := filepath.Join(getTestdataPath(), appConfigDir())
Expand Down Expand Up @@ -67,6 +65,6 @@ func TestServerStart2(t *testing.T) {
Date: buildTime,
Version: "1.0.0",
})
AppConfig().SetString("server.port", "8080")
go Start()
AppConfig().SetString("server.port", "80")
Start()
}
69 changes: 40 additions & 29 deletions static.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,23 @@ import (
"aahframework.org/log.v0"
)

const dirStatic = "static"

// serveStatic method static file/directory delivery.
func (e *engine) serveStatic(ctx *Context) error {
// TODO static assets Dynamic minify for JS and CSS for non-dev profile
dir, file := filepath.Split(getFilepath(ctx))
log.Tracef("Dir: %s, File: %s", dir, file)

ctx.Reply().gzip = checkGzipRequired(file)
e.wrapGzipWriter(ctx)
e.writeHeaders(ctx)
// Determine route is file or directory as per user defined
// static route config (refer to https://docs.aahframework.org/static-files.html#section-static).
// httpDir -> value is from routes config
// filePath -> value is from request
httpDir, filePath := getHTTPDirAndFilePath(ctx)
log.Tracef("Dir: %s, Filepath: %s", httpDir, filePath)

res, req := ctx.Res, ctx.Req
fs := ahttp.Dir(dir, ctx.route.ListDir)
f, err := fs.Open(file)
f, err := httpDir.Open(filePath)
if err != nil {
if err == ahttp.ErrDirListNotAllowed {
log.Warnf("directory listing not allowed: %s", req.Path)
res.WriteHeader(http.StatusForbidden)
fmt.Fprintf(res, "403 Directory listing not allowed")
} else if os.IsNotExist(err) {
if os.IsNotExist(err) {
log.Errorf("file not found: %s", req.Path)
return errFileNotFound
} else if os.IsPermission(err) {
Expand All @@ -48,20 +46,36 @@ func (e *engine) serveStatic(ctx *Context) error {
res.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(res, "500 Internal Server Error")
}

return nil
}

defer ess.CloseQuietly(f)

fi, err := f.Stat()
if err != nil {
res.WriteHeader(http.StatusInternalServerError)
_, _ = res.Write([]byte("500 Internal Server Error"))
fmt.Fprintf(res, "500 Internal Server Error")
return nil
}

if fi.IsDir() {
// Gzip
ctx.Reply().gzip = checkGzipRequired(filePath)
e.wrapGzipWriter(ctx)
e.writeHeaders(ctx)

// Serve file
if fi.Mode().IsRegular() {
// 'OnPreReply' server extension point
publishOnPreReplyEvent(ctx)

http.ServeContent(ctx.Res, ctx.Req.Raw, path.Base(filePath), fi.ModTime(), f)

// 'OnAfterReply' server extension point
publishOnAfterReplyEvent(ctx)
return nil
}

// Serve directory
if fi.Mode().IsDir() && ctx.route.ListDir {
// redirect if the directory name doesn't end in a slash
if req.Path[len(req.Path)-1] != '/' {
log.Debugf("redirecting to dir: %s", req.Path+"/")
Expand All @@ -79,13 +93,11 @@ func (e *engine) serveStatic(ctx *Context) error {
return nil
}

// 'OnPreReply' server extension point
publishOnPreReplyEvent(ctx)

http.ServeContent(res, req.Raw, file, fi.ModTime(), f)
// Flow reached here it means directory listing is not allowed
log.Warnf("directory listing not allowed: %s", req.Path)
res.WriteHeader(http.StatusForbidden)
fmt.Fprintf(res, "403 Directory listing not allowed")

// 'OnAfterReply' server extension point
publishOnAfterReplyEvent(ctx)
return nil
}

Expand Down Expand Up @@ -138,14 +150,13 @@ func checkGzipRequired(file string) bool {
}
}

func getFilepath(ctx *Context) string {
var file string
if ctx.route.IsDir() {
file = filepath.Join(AppBaseDir(), ctx.route.Dir, ctx.Req.PathValue("filepath"))
} else {
file = filepath.Join(AppBaseDir(), "static", ctx.route.File)
// getHTTPDirAndFilePath method returns the `http.Dir` and requested file path.
// Note: `ctx.route.*` values come from application routes configuration.
func getHTTPDirAndFilePath(ctx *Context) (http.Dir, string) {
if ctx.route.IsFile() { // this is configured value from routes.conf
return http.Dir(filepath.Join(AppBaseDir(), dirStatic)), ctx.route.File
}
return filepath.FromSlash(file)
return http.Dir(filepath.Join(AppBaseDir(), ctx.route.Dir)), ctx.Req.PathValue("filepath")
}

// Sort interface for Directory list
Expand Down
67 changes: 67 additions & 0 deletions static_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) Jeevanandam M. (https://github.com/jeevatkm)
// go-aah/aah source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

package aah

import (
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"

"aahframework.org/config.v0"
"aahframework.org/router.v0"
"aahframework.org/test.v0/assert"
)

func TestStaticDirectoryListing(t *testing.T) {
appCfg, _ := config.ParseString("")
e := newEngine(appCfg)

testStaticServe(t, e, "http://localhost:8080/static/css/aah\x00.css", "static", "css/aah\x00.css", "", "500 Internal Server Error", false)

testStaticServe(t, e, "http://localhost:8080/static/test.txt", "static", "test.txt", "", "This is file content of test.txt", false)

testStaticServe(t, e, "http://localhost:8080/static", "static", "", "", "403 Directory listing not allowed", false)

testStaticServe(t, e, "http://localhost:8080/static", "static", "", "", `<a href="/static/">Found</a>`, true)

testStaticServe(t, e, "http://localhost:8080/static/", "static", "", "", `<title>Listing of /static/</title>`, true)

testStaticServe(t, e, "http://localhost:8080/robots.txt", "", "", "test.txt", "This is file content of test.txt", false)
}

func TestStaticMisc(t *testing.T) {
// File extension check for gzip
v1 := checkGzipRequired("sample.css")
assert.True(t, v1)

v2 := checkGzipRequired("font.otf")
assert.True(t, v2)

// directoryList for read error
r1 := httptest.NewRequest("GET", "http://localhost:8080/assets/css/app.css", nil)
w1 := httptest.NewRecorder()
f, err := os.Open(filepath.Join(getTestdataPath(), "static", "test.txt"))
assert.Nil(t, err)

directoryList(w1, r1, f)
assert.Equal(t, "Error reading directory", w1.Body.String())
}

func testStaticServe(t *testing.T, e *engine, reqURL, dir, filePath, file, result string, listDir bool) {
r := httptest.NewRequest("GET", reqURL, nil)
w := httptest.NewRecorder()
ctx := e.prepareContext(w, r)
ctx.route = &router.Route{IsStatic: true, Dir: dir, ListDir: listDir, File: file}
ctx.Req.Params.Path = map[string]string{
"filepath": filePath,
}
appBaseDir = getTestdataPath()
err := e.serveStatic(ctx)
appBaseDir = ""
assert.Nil(t, err)
assert.True(t, strings.Contains(w.Body.String(), result))
}
2 changes: 1 addition & 1 deletion testdata/static/test.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
test.txt
This is file content of test.txt
7 changes: 1 addition & 6 deletions view_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net/http/httptest"
"path/filepath"
"strings"
"sync"
"testing"

"aahframework.org/ahttp.v0"
Expand Down Expand Up @@ -96,12 +95,8 @@ func TestViewStore(t *testing.T) {
assert.False(t, found)
}

var testEng = sync.Mutex{}

func TestViewResolveView(t *testing.T) {
defer ess.DeleteFiles("testapp.pid")
testEng.Lock()
defer testEng.Unlock()
appCfg, _ := config.ParseString("")
e := newEngine(appCfg)

Expand Down Expand Up @@ -131,7 +126,7 @@ func TestViewResolveView(t *testing.T) {
assert.Equal(t, "http", htmlRdr.ViewArgs["Scheme"])
assert.Equal(t, "localhost:8080", htmlRdr.ViewArgs["Host"])
assert.Equal(t, "/index.html", htmlRdr.ViewArgs["RequestPath"])
assert.Equal(t, "0.5", htmlRdr.ViewArgs["AahVersion"])
assert.Equal(t, Version, htmlRdr.ViewArgs["AahVersion"])
assert.Equal(t, "aah framework", htmlRdr.ViewArgs["MyName"])

// cleanup
Expand Down

0 comments on commit e0e9fbe

Please sign in to comment.