tech: upgraded macaron & macaron inject, binding, session

This commit is contained in:
Torkel Ödegaard 2017-04-25 15:14:19 +02:00
parent 9f462c0519
commit 4720216e5e
39 changed files with 740 additions and 1319 deletions

View File

@ -1,24 +0,0 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
.idea
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.iml

View File

@ -1,7 +1,7 @@
Common functions
===
Common Functions
================
[![Build Status](https://drone.io/github.com/Unknwon/com/status.png)](https://drone.io/github.com/Unknwon/com/latest) [![Go Walker](http://gowalker.org/api/v1/badge)](http://gowalker.org/github.com/Unknwon/com)
[![Build Status](https://travis-ci.org/Unknwon/com.svg)](https://travis-ci.org/Unknwon/com) [![Go Walker](http://gowalker.org/api/v1/badge)](http://gowalker.org/github.com/Unknwon/com)
This is an open source project for commonly used functions for the Go programming language.
@ -17,8 +17,4 @@ Your contribute is welcome, but you have to check following steps after you adde
2. Make sure you wrote test cases with any possible condition for **all functions** in file `*_test.go`.
3. Make sure you wrote benchmarks for **all functions** in file `*_test.go`.
4. Make sure you wrote useful examples for **all functions** in file `example_test.go`.
5. Make sure you ran `go test -bench="."` and got **PASS** .
## Performance
See results on [drone.io](https://drone.io/github.com/Unknwon/com/latest) by `go test -bench="."`.
5. Make sure you ran `go test` and got **PASS** .

View File

@ -1,140 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"fmt"
"runtime"
"strings"
"testing"
)
func TestColorLogS(t *testing.T) {
if runtime.GOOS != "windows" {
// Trace + path.
cls := ColorLogS("[TRAC] Trace level test with path( %s )", "/path/to/somethere")
clsR := fmt.Sprintf(
"[\033[%dmTRAC%s] Trace level test with path(\033[%dm%s%s)",
Blue, EndColor, Yellow, "/path/to/somethere", EndColor)
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
// Error + error.
cls = ColorLogS("[ERRO] Error level test with error[ %s ]", "test error")
clsR = fmt.Sprintf(
"[\033[%dmERRO%s] Error level test with error[\033[%dm%s%s]",
Red, EndColor, Red, "test error", EndColor)
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
// Warning + highlight.
cls = ColorLogS("[WARN] Warnning level test with highlight # %s #", "special offer!")
clsR = fmt.Sprintf(
"[\033[%dmWARN%s] Warnning level test with highlight \033[%dm%s%s",
Magenta, EndColor, Gray, "special offer!", EndColor)
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
// Success.
cls = ColorLogS("[SUCC] Success level test")
clsR = fmt.Sprintf(
"[\033[%dmSUCC%s] Success level test",
Green, EndColor)
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
// Default.
cls = ColorLogS("[INFO] Default level test")
clsR = fmt.Sprintf(
"[INFO] Default level test")
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
} else {
// Trace + path.
cls := ColorLogS("[TRAC] Trace level test with path( %s )", "/path/to/somethere")
clsR := fmt.Sprintf(
"[TRAC] Trace level test with path(%s)",
"/path/to/somethere")
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
// Error + error.
cls = ColorLogS("[ERRO] Error level test with error[ %s ]", "test error")
clsR = fmt.Sprintf(
"[ERRO] Error level test with error[%s]",
"test error")
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
// Warning + highlight.
cls = ColorLogS("[WARN] Warnning level test with highlight # %s #", "special offer!")
clsR = fmt.Sprintf(
"[WARN] Warnning level test with highlight %s",
"special offer!")
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
// Success.
cls = ColorLogS("[SUCC] Success level test")
clsR = fmt.Sprintf(
"[SUCC] Success level test")
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
// Default.
cls = ColorLogS("[INFO] Default level test")
clsR = fmt.Sprintf(
"[INFO] Default level test")
if cls != clsR {
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
}
}
}
func TestExecCmd(t *testing.T) {
stdout, stderr, err := ExecCmd("go", "help", "get")
if err != nil {
t.Errorf("ExecCmd:\n Expect => %v\n Got => %v\n", nil, err)
} else if len(stderr) != 0 {
t.Errorf("ExecCmd:\n Expect => %s\n Got => %s\n", "", stderr)
} else if !strings.HasPrefix(stdout, "usage: go get") {
t.Errorf("ExecCmd:\n Expect => %s\n Got => %s\n", "usage: go get", stdout)
}
}
func BenchmarkColorLogS(b *testing.B) {
log := fmt.Sprintf(
"[WARN] This is a tesing log that should be colored, path( %s ),"+
" highlight # %s #, error [ %s ].",
"path to somewhere", "highlighted content", "tesing error")
for i := 0; i < b.N; i++ {
ColorLogS(log)
}
}
func BenchmarkExecCmd(b *testing.B) {
for i := 0; i < b.N; i++ {
ExecCmd("go", "help", "get")
}
}

View File

@ -32,7 +32,7 @@ func (f StrTo) Uint8() (uint8, error) {
}
func (f StrTo) Int() (int, error) {
v, err := strconv.ParseInt(f.String(), 10, 32)
v, err := strconv.ParseInt(f.String(), 10, 0)
return int(v), err
}

View File

@ -1,56 +0,0 @@
// Copyright 2014 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestHexStr2int(t *testing.T) {
Convey("Convert hex format string to decimal", t, func() {
hexDecs := map[string]int{
"1": 1,
"002": 2,
"011": 17,
"0a1": 161,
"35e": 862,
}
for hex, dec := range hexDecs {
val, err := HexStr2int(hex)
So(err, ShouldBeNil)
So(val, ShouldEqual, dec)
}
})
}
func TestInt2HexStr(t *testing.T) {
Convey("Convert decimal to hex format string", t, func() {
decHexs := map[int]string{
1: "1",
2: "2",
17: "11",
161: "a1",
862: "35e",
}
for dec, hex := range decHexs {
val := Int2HexStr(dec)
So(val, ShouldEqual, hex)
}
})
}

View File

@ -1,58 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"os"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestIsDir(t *testing.T) {
Convey("Check if given path is a directory", t, func() {
Convey("Pass a file name", func() {
So(IsDir("file.go"), ShouldEqual, false)
})
Convey("Pass a directory name", func() {
So(IsDir("testdata"), ShouldEqual, true)
})
Convey("Pass a invalid path", func() {
So(IsDir("foo"), ShouldEqual, false)
})
})
}
func TestCopyDir(t *testing.T) {
Convey("Items of two slices should be same", t, func() {
s1, err := StatDir("testdata", true)
So(err, ShouldEqual, nil)
err = CopyDir("testdata", "testdata2")
So(err, ShouldEqual, nil)
s2, err := StatDir("testdata2", true)
os.RemoveAll("testdata2")
So(err, ShouldEqual, nil)
So(CompareSliceStr(s1, s2), ShouldEqual, true)
})
}
func BenchmarkIsDir(b *testing.B) {
for i := 0; i < b.N; i++ {
IsDir("file.go")
}
}

View File

@ -1,299 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com_test
import (
"fmt"
"io/ioutil"
"net/http"
"github.com/Unknwon/com"
)
// ------------------------------
// cmd.go
// ------------------------------
func ExampleColorLogS() {
coloredLog := com.ColorLogS(fmt.Sprintf(
"[WARN] This is a tesing log that should be colored, path( %s ),"+
" highlight # %s #, error [ %s ].",
"path to somewhere", "highlighted content", "tesing error"))
fmt.Println(coloredLog)
}
func ExampleColorLog() {
com.ColorLog(fmt.Sprintf(
"[WARN] This is a tesing log that should be colored, path( %s ),"+
" highlight # %s #, error [ %s ].",
"path to somewhere", "highlighted content", "tesing error"))
}
func ExampleExecCmd() {
stdout, stderr, err := com.ExecCmd("go", "help", "get")
fmt.Println(stdout, stderr, err)
}
// ------------- END ------------
// ------------------------------
// html.go
// ------------------------------
func ExampleHtml2JS() {
htm := "<div id=\"button\" class=\"btn\">Click me</div>\n\r"
js := string(com.Html2JS([]byte(htm)))
fmt.Println(js)
// Output: <div id=\"button\" class=\"btn\">Click me</div>\n
}
// ------------- END ------------
// ------------------------------
// path.go
// ------------------------------
func ExampleGetGOPATHs() {
gps := com.GetGOPATHs()
fmt.Println(gps)
}
func ExampleGetSrcPath() {
srcPath, err := com.GetSrcPath("github.com/Unknwon/com")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(srcPath)
}
func ExampleHomeDir() {
hd, err := com.HomeDir()
fmt.Println(hd, err)
}
// ------------- END ------------
// ------------------------------
// file.go
// ------------------------------
func ExampleIsFile() {
if com.IsFile("file.go") {
fmt.Println("file.go exists")
return
}
fmt.Println("file.go is not a file or does not exist")
}
func ExampleIsExist() {
if com.IsExist("file.go") {
fmt.Println("file.go exists")
return
}
fmt.Println("file.go does not exist")
}
// ------------- END ------------
// ------------------------------
// dir.go
// ------------------------------
func ExampleIsDir() {
if com.IsDir("files") {
fmt.Println("directory 'files' exists")
return
}
fmt.Println("'files' is not a directory or does not exist")
}
// ------------- END ------------
// ------------------------------
// string.go
// ------------------------------
func ExampleIsLetter() {
fmt.Println(com.IsLetter('1'))
fmt.Println(com.IsLetter('['))
fmt.Println(com.IsLetter('a'))
fmt.Println(com.IsLetter('Z'))
// Output:
// false
// false
// true
// true
}
func ExampleExpand() {
match := map[string]string{
"domain": "gowalker.org",
"subdomain": "github.com",
}
s := "http://{domain}/{subdomain}/{0}/{1}"
fmt.Println(com.Expand(s, match, "Unknwon", "gowalker"))
// Output: http://gowalker.org/github.com/Unknwon/gowalker
}
// ------------- END ------------
// ------------------------------
// http.go
// ------------------------------
func ExampleHttpGet() ([]byte, error) {
rc, err := com.HttpGet(&http.Client{}, "http://gowalker.org", nil)
if err != nil {
return nil, err
}
p, err := ioutil.ReadAll(rc)
rc.Close()
return p, err
}
func ExampleHttpGetBytes() ([]byte, error) {
p, err := com.HttpGetBytes(&http.Client{}, "http://gowalker.org", nil)
return p, err
}
func ExampleHttpGetJSON() interface{} {
j := com.HttpGetJSON(&http.Client{}, "http://gowalker.org", nil)
return j
}
type rawFile struct {
name string
rawURL string
data []byte
}
func (rf *rawFile) Name() string {
return rf.name
}
func (rf *rawFile) RawUrl() string {
return rf.rawURL
}
func (rf *rawFile) Data() []byte {
return rf.data
}
func (rf *rawFile) SetData(p []byte) {
rf.data = p
}
func ExampleFetchFiles() {
// Code that should be outside of your function body.
// type rawFile struct {
// name string
// rawURL string
// data []byte
// }
// func (rf *rawFile) Name() string {
// return rf.name
// }
// func (rf *rawFile) RawUrl() string {
// return rf.rawURL
// }
// func (rf *rawFile) Data() []byte {
// return rf.data
// }
// func (rf *rawFile) SetData(p []byte) {
// rf.data = p
// }
files := []com.RawFile{
&rawFile{rawURL: "http://example.com"},
&rawFile{rawURL: "http://example.com/foo"},
}
err := com.FetchFiles(&http.Client{}, files, nil)
fmt.Println(err, len(files[0].Data()), len(files[1].Data()))
}
func ExampleFetchFilesCurl() {
// Code that should be outside of your function body.
// type rawFile struct {
// name string
// rawURL string
// data []byte
// }
// func (rf *rawFile) Name() string {
// return rf.name
// }
// func (rf *rawFile) RawUrl() string {
// return rf.rawURL
// }
// func (rf *rawFile) Data() []byte {
// return rf.data
// }
// func (rf *rawFile) SetData(p []byte) {
// rf.data = p
// }
files := []com.RawFile{
&rawFile{rawURL: "http://example.com"},
&rawFile{rawURL: "http://example.com/foo"},
}
err := com.FetchFilesCurl(files)
fmt.Println(err, len(files[0].Data()), len(files[1].Data()))
}
// ------------- END ------------
// ------------------------------
// regex.go
// ------------------------------
func ExampleIsEmail() {
fmt.Println(com.IsEmail("test@example.com"))
fmt.Println(com.IsEmail("@example.com"))
// Output:
// true
// false
}
func ExampleIsUrl() {
fmt.Println(com.IsUrl("http://example.com"))
fmt.Println(com.IsUrl("http//example.com"))
// Output:
// true
// false
}
// ------------- END ------------
// ------------------------------
// slice.go
// ------------------------------
func ExampleAppendStr() {
s := []string{"a"}
s = com.AppendStr(s, "a")
s = com.AppendStr(s, "b")
fmt.Println(s)
// Output: [a b]
}
// ------------- END ------------

View File

@ -1,61 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestIsFile(t *testing.T) {
if !IsFile("file.go") {
t.Errorf("IsExist:\n Expect => %v\n Got => %v\n", true, false)
}
if IsFile("testdata") {
t.Errorf("IsExist:\n Expect => %v\n Got => %v\n", false, true)
}
if IsFile("files.go") {
t.Errorf("IsExist:\n Expect => %v\n Got => %v\n", false, true)
}
}
func TestIsExist(t *testing.T) {
Convey("Check if file or directory exists", t, func() {
Convey("Pass a file name that exists", func() {
So(IsExist("file.go"), ShouldEqual, true)
})
Convey("Pass a directory name that exists", func() {
So(IsExist("testdata"), ShouldEqual, true)
})
Convey("Pass a directory name that does not exist", func() {
So(IsExist(".hg"), ShouldEqual, false)
})
})
}
func BenchmarkIsFile(b *testing.B) {
for i := 0; i < b.N; i++ {
IsFile("file.go")
}
}
func BenchmarkIsExist(b *testing.B) {
for i := 0; i < b.N; i++ {
IsExist("file.go")
}
}

View File

@ -1,35 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"testing"
)
func TestHtml2JS(t *testing.T) {
htm := "<div id=\"button\" class=\"btn\">Click me</div>\n\r"
js := string(Html2JS([]byte(htm)))
jsR := `<div id=\"button\" class=\"btn\">Click me</div>\n`
if js != jsR {
t.Errorf("Html2JS:\n Expect => %s\n Got => %s\n", jsR, js)
}
}
func BenchmarkHtml2JS(b *testing.B) {
htm := "<div id=\"button\" class=\"btn\">Click me</div>\n\r"
for i := 0; i < b.N; i++ {
Html2JS([]byte(htm))
}
}

View File

@ -1,111 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"io/ioutil"
"net/http"
"strings"
"testing"
)
var examplePrefix = `<!doctype html>
<html>
<head>
<title>Example Domain</title>
`
func TestHttpGet(t *testing.T) {
// 200.
rc, err := HttpGet(&http.Client{}, "http://example.com", nil)
if err != nil {
t.Fatalf("HttpGet:\n Expect => %v\n Got => %s\n", nil, err)
}
p, err := ioutil.ReadAll(rc)
if err != nil {
t.Errorf("HttpGet:\n Expect => %v\n Got => %s\n", nil, err)
}
s := string(p)
if !strings.HasPrefix(s, examplePrefix) {
t.Errorf("HttpGet:\n Expect => %s\n Got => %s\n", examplePrefix, s)
}
}
func TestHttpGetBytes(t *testing.T) {
p, err := HttpGetBytes(&http.Client{}, "http://example.com", nil)
if err != nil {
t.Errorf("HttpGetBytes:\n Expect => %v\n Got => %s\n", nil, err)
}
s := string(p)
if !strings.HasPrefix(s, examplePrefix) {
t.Errorf("HttpGet:\n Expect => %s\n Got => %s\n", examplePrefix, s)
}
}
func TestHttpGetJSON(t *testing.T) {
}
type rawFile struct {
name string
rawURL string
data []byte
}
func (rf *rawFile) Name() string {
return rf.name
}
func (rf *rawFile) RawUrl() string {
return rf.rawURL
}
func (rf *rawFile) Data() []byte {
return rf.data
}
func (rf *rawFile) SetData(p []byte) {
rf.data = p
}
func TestFetchFiles(t *testing.T) {
files := []RawFile{
&rawFile{rawURL: "http://example.com"},
&rawFile{rawURL: "http://example.com"},
}
err := FetchFiles(&http.Client{}, files, nil)
if err != nil {
t.Errorf("FetchFiles:\n Expect => %v\n Got => %s\n", nil, err)
} else if len(files[0].Data()) != 1270 {
t.Errorf("FetchFiles:\n Expect => %d\n Got => %d\n", 1270, len(files[0].Data()))
} else if len(files[1].Data()) != 1270 {
t.Errorf("FetchFiles:\n Expect => %d\n Got => %d\n", 1270, len(files[1].Data()))
}
}
func TestFetchFilesCurl(t *testing.T) {
files := []RawFile{
&rawFile{rawURL: "http://example.com"},
&rawFile{rawURL: "http://example.com"},
}
err := FetchFilesCurl(files)
if err != nil {
t.Errorf("FetchFilesCurl:\n Expect => %v\n Got => %s\n", nil, err)
} else if len(files[0].Data()) != 1270 {
t.Errorf("FetchFilesCurl:\n Expect => %d\n Got => %d\n", 1270, len(files[0].Data()))
} else if len(files[1].Data()) != 1270 {
t.Errorf("FetchFilesCurl:\n Expect => %d\n Got => %d\n", 1270, len(files[1].Data()))
}
}

View File

@ -14,11 +14,16 @@
package com
// PowInt is int type of math.Pow function.
// PowInt is int type of math.Pow function.
func PowInt(x int, y int) int {
num := 1
for i := 0; i < y; i++ {
num *= x
if y <= 0 {
return 1
} else {
if y % 2 == 0 {
sqrt := PowInt(x, y/2)
return sqrt * sqrt
} else {
return PowInt(x, y-1) * x
}
}
return num
}

View File

@ -64,9 +64,9 @@ func GetSrcPath(importPath string) (appPath string, err error) {
// it returns error when the variable does not exist.
func HomeDir() (home string, err error) {
if runtime.GOOS == "windows" {
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
if home == "" {
home = os.Getenv("USERPROFILE")
home = os.Getenv("USERPROFILE")
if len(home) == 0 {
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
}
} else {
home = os.Getenv("HOME")

View File

@ -1,67 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"os"
"runtime"
"testing"
)
func TestGetGOPATHs(t *testing.T) {
var gpsR []string
if runtime.GOOS != "windows" {
gpsR = []string{"path/to/gopath1", "path/to/gopath2", "path/to/gopath3"}
os.Setenv("GOPATH", "path/to/gopath1:path/to/gopath2:path/to/gopath3")
} else {
gpsR = []string{"path/to/gopath1", "path/to/gopath2", "path/to/gopath3"}
os.Setenv("GOPATH", "path\\to\\gopath1;path\\to\\gopath2;path\\to\\gopath3")
}
gps := GetGOPATHs()
if !CompareSliceStr(gps, gpsR) {
t.Errorf("GetGOPATHs:\n Expect => %s\n Got => %s\n", gpsR, gps)
}
}
func TestGetSrcPath(t *testing.T) {
}
func TestHomeDir(t *testing.T) {
_, err := HomeDir()
if err != nil {
t.Errorf("HomeDir:\n Expect => %v\n Got => %s\n", nil, err)
}
}
func BenchmarkGetGOPATHs(b *testing.B) {
for i := 0; i < b.N; i++ {
GetGOPATHs()
}
}
func BenchmarkGetSrcPath(b *testing.B) {
for i := 0; i < b.N; i++ {
GetSrcPath("github.com/Unknwon/com")
}
}
func BenchmarkHomeDir(b *testing.B) {
for i := 0; i < b.N; i++ {
HomeDir()
}
}

View File

@ -1,70 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"testing"
)
func TestIsEmail(t *testing.T) {
emails := map[string]bool{
`test@example.com`: true,
`single-character@b.org`: true,
`uncommon_address@test.museum`: true,
`local@sld.UPPER`: true,
`@missing.org`: false,
`missing@.com`: false,
`missing@qq.`: false,
`wrong-ip@127.1.1.1.26`: false,
}
for e, r := range emails {
b := IsEmail(e)
if b != r {
t.Errorf("IsEmail:\n Expect => %v\n Got => %v\n", r, b)
}
}
}
func TestIsUrl(t *testing.T) {
urls := map[string]bool{
"http://www.example.com": true,
"http://example.com": true,
"http://example.com?user=test&password=test": true,
"http://example.com?user=test#login": true,
"ftp://example.com": true,
"https://example.com": true,
"htp://example.com": false,
"http//example.com": false,
"http://example": true,
}
for u, r := range urls {
b := IsUrl(u)
if b != r {
t.Errorf("IsUrl:\n Expect => %v\n Got => %v\n", r, b)
}
}
}
func BenchmarkIsEmail(b *testing.B) {
for i := 0; i < b.N; i++ {
IsEmail("test@example.com")
}
}
func BenchmarkIsUrl(b *testing.B) {
for i := 0; i < b.N; i++ {
IsEmail("http://example.com")
}
}

View File

@ -1,99 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"fmt"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestAppendStr(t *testing.T) {
Convey("Append a string to a slice with no duplicates", t, func() {
s := []string{"a"}
Convey("Append a string that does not exist in slice", func() {
s = AppendStr(s, "b")
So(len(s), ShouldEqual, 2)
})
Convey("Append a string that does exist in slice", func() {
s = AppendStr(s, "b")
So(len(s), ShouldEqual, 2)
})
})
}
func TestCompareSliceStr(t *testing.T) {
Convey("Compares two 'string' type slices with elements and order", t, func() {
Convey("Compare two slices that do have same elements and order", func() {
So(CompareSliceStr(
[]string{"1", "2", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
})
Convey("Compare two slices that do have same elements but does not have same order", func() {
So(!CompareSliceStr(
[]string{"2", "1", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
})
Convey("Compare two slices that have different number of elements", func() {
So(!CompareSliceStr(
[]string{"2", "1"}, []string{"1", "2", "3"}), ShouldBeTrue)
})
})
}
func TestCompareSliceStrU(t *testing.T) {
Convey("Compare two 'string' type slices with elements and ignore the order", t, func() {
Convey("Compare two slices that do have same elements and order", func() {
So(CompareSliceStrU(
[]string{"1", "2", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
})
Convey("Compare two slices that do have same elements but does not have same order", func() {
So(CompareSliceStrU(
[]string{"2", "1", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
})
Convey("Compare two slices that have different number of elements", func() {
So(!CompareSliceStrU(
[]string{"2", "1"}, []string{"1", "2", "3"}), ShouldBeTrue)
})
})
}
func BenchmarkAppendStr(b *testing.B) {
s := []string{"a"}
for i := 0; i < b.N; i++ {
s = AppendStr(s, fmt.Sprint(b.N%3))
}
}
func BenchmarkCompareSliceStr(b *testing.B) {
s1 := []string{"1", "2", "3"}
s2 := []string{"1", "2", "3"}
for i := 0; i < b.N; i++ {
CompareSliceStr(s1, s2)
}
}
func BenchmarkCompareSliceStrU(b *testing.B) {
s1 := []string{"1", "4", "2", "3"}
s2 := []string{"1", "2", "3", "4"}
for i := 0; i < b.N; i++ {
CompareSliceStrU(s1, s2)
}
}

View File

@ -15,53 +15,66 @@
package com
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"io"
r "math/rand"
"strconv"
"strings"
"time"
"unicode"
"unicode/utf8"
)
// AESEncrypt encrypts text and given key with AES.
func AESEncrypt(key, text []byte) ([]byte, error) {
// AESGCMEncrypt encrypts plaintext with the given key using AES in GCM mode.
func AESGCMEncrypt(key, plaintext []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
b := base64.StdEncoding.EncodeToString(text)
ciphertext := make([]byte, aes.BlockSize+len(b))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
return ciphertext, nil
nonce := make([]byte, gcm.NonceSize())
if _, err := rand.Read(nonce); err != nil {
return nil, err
}
ciphertext := gcm.Seal(nil, nonce, plaintext, nil)
return append(nonce, ciphertext...), nil
}
// AESDecrypt decrypts text and given key with AES.
func AESDecrypt(key, text []byte) ([]byte, error) {
// AESGCMDecrypt decrypts ciphertext with the given key using AES in GCM mode.
func AESGCMDecrypt(key, ciphertext []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
if len(text) < aes.BlockSize {
return nil, errors.New("ciphertext too short")
}
iv := text[:aes.BlockSize]
text = text[aes.BlockSize:]
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(text, text)
data, err := base64.StdEncoding.DecodeString(string(text))
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
return data, nil
size := gcm.NonceSize()
if len(ciphertext)-size <= 0 {
return nil, errors.New("Ciphertext is empty")
}
nonce := ciphertext[:size]
ciphertext = ciphertext[size:]
plainText, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, err
}
return plainText, nil
}
// IsLetter returns true if the 'l' is an English letter.
@ -138,3 +151,103 @@ func RandomCreateBytes(n int, alphabets ...byte) []byte {
}
return bytes
}
// ToSnakeCase can convert all upper case characters in a string to
// underscore format.
//
// Some samples.
// "FirstName" => "first_name"
// "HTTPServer" => "http_server"
// "NoHTTPS" => "no_https"
// "GO_PATH" => "go_path"
// "GO PATH" => "go_path" // space is converted to underscore.
// "GO-PATH" => "go_path" // hyphen is converted to underscore.
//
// From https://github.com/huandu/xstrings
func ToSnakeCase(str string) string {
if len(str) == 0 {
return ""
}
buf := &bytes.Buffer{}
var prev, r0, r1 rune
var size int
r0 = '_'
for len(str) > 0 {
prev = r0
r0, size = utf8.DecodeRuneInString(str)
str = str[size:]
switch {
case r0 == utf8.RuneError:
buf.WriteByte(byte(str[0]))
case unicode.IsUpper(r0):
if prev != '_' {
buf.WriteRune('_')
}
buf.WriteRune(unicode.ToLower(r0))
if len(str) == 0 {
break
}
r0, size = utf8.DecodeRuneInString(str)
str = str[size:]
if !unicode.IsUpper(r0) {
buf.WriteRune(r0)
break
}
// find next non-upper-case character and insert `_` properly.
// it's designed to convert `HTTPServer` to `http_server`.
// if there are more than 2 adjacent upper case characters in a word,
// treat them as an abbreviation plus a normal word.
for len(str) > 0 {
r1 = r0
r0, size = utf8.DecodeRuneInString(str)
str = str[size:]
if r0 == utf8.RuneError {
buf.WriteRune(unicode.ToLower(r1))
buf.WriteByte(byte(str[0]))
break
}
if !unicode.IsUpper(r0) {
if r0 == '_' || r0 == ' ' || r0 == '-' {
r0 = '_'
buf.WriteRune(unicode.ToLower(r1))
} else {
buf.WriteRune('_')
buf.WriteRune(unicode.ToLower(r1))
buf.WriteRune(r0)
}
break
}
buf.WriteRune(unicode.ToLower(r1))
}
if len(str) == 0 || r0 == '_' {
buf.WriteRune(unicode.ToLower(r0))
break
}
default:
if r0 == ' ' || r0 == '-' {
r0 = '_'
}
buf.WriteRune(r0)
}
}
return buf.String()
}

View File

@ -1,82 +0,0 @@
// Copyright 2013 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package com
import (
"testing"
)
func TestIsLetter(t *testing.T) {
if IsLetter('1') {
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", false, true)
}
if IsLetter('[') {
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", false, true)
}
if !IsLetter('a') {
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", true, false)
}
if !IsLetter('Z') {
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", true, false)
}
}
func TestExpand(t *testing.T) {
match := map[string]string{
"domain": "gowalker.org",
"subdomain": "github.com",
}
s := "http://{domain}/{subdomain}/{0}/{1}"
sR := "http://gowalker.org/github.com/Unknwon/gowalker"
if Expand(s, match, "Unknwon", "gowalker") != sR {
t.Errorf("Expand:\n Expect => %s\n Got => %s\n", sR, s)
}
}
func TestReverse(t *testing.T) {
if Reverse("abcdefg") != "gfedcba" {
t.Errorf("Reverse:\n Except => %s\n Got =>%s\n", "gfedcba", Reverse("abcdefg"))
}
if Reverse("上善若水厚德载物") != "物载德厚水若善上" {
t.Errorf("Reverse:\n Except => %s\n Got =>%s\n", "物载德厚水若善上", Reverse("上善若水厚德载物"))
}
}
func BenchmarkIsLetter(b *testing.B) {
for i := 0; i < b.N; i++ {
IsLetter('a')
}
}
func BenchmarkExpand(b *testing.B) {
match := map[string]string{
"domain": "gowalker.org",
"subdomain": "github.com",
}
s := "http://{domain}/{subdomain}/{0}/{1}"
for i := 0; i < b.N; i++ {
Expand(s, match, "Unknwon", "gowalker")
}
}
func BenchmarkReverse(b *testing.B) {
s := "abscef中文"
for i := 0; i < b.N; i++ {
Reverse(s)
}
}

View File

@ -1,14 +0,0 @@
sudo: false
language: go
go:
- 1.3
- 1.4
- 1.5
- tip
script: go test -v -cover -race
notifications:
email:
- u@gogs.io

View File

@ -32,7 +32,7 @@ import (
"gopkg.in/macaron.v1"
)
const _VERSION = "0.2.0"
const _VERSION = "0.3.2"
func Version() string {
return _VERSION
@ -145,7 +145,7 @@ func Form(formStruct interface{}, ifacePtr ...interface{}) macaron.Handler {
if parseErr != nil {
errors.Add([]string{}, ERR_DESERIALIZATION, parseErr.Error())
}
mapForm(formStruct, ctx.Req.Form, nil, errors)
errors = mapForm(formStruct, ctx.Req.Form, nil, errors)
validateAndMap(formStruct, ctx, errors, ifacePtr...)
}
}
@ -185,7 +185,7 @@ func MultipartForm(formStruct interface{}, ifacePtr ...interface{}) macaron.Hand
ctx.Req.MultipartForm = form
}
}
mapForm(formStruct, ctx.Req.MultipartForm.Value, ctx.Req.MultipartForm.File, errors)
errors = mapForm(formStruct, ctx.Req.MultipartForm.Value, ctx.Req.MultipartForm.File, errors)
validateAndMap(formStruct, ctx, errors, ifacePtr...)
}
}
@ -243,10 +243,10 @@ func Validate(obj interface{}) macaron.Handler {
}
var (
alphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
alphaDashDotPattern = regexp.MustCompile("[^\\d\\w-_\\.]")
emailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
urlPattern = regexp.MustCompile(`(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?`)
AlphaDashPattern = regexp.MustCompile("[^\\d\\w-_]")
AlphaDashDotPattern = regexp.MustCompile("[^\\d\\w-_\\.]")
EmailPattern = regexp.MustCompile("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[a-zA-Z0-9](?:[\\w-]*[\\w])?")
URLPattern = regexp.MustCompile(`(http|https):\/\/(?:\\S+(?::\\S*)?@)?[\w\-_]+(\.[\w\-_]+)*([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?`)
)
type (
@ -255,7 +255,7 @@ type (
// IsMatch checks if rule matches.
IsMatch func(string) bool
// IsValid applies validation rule to condition.
IsValid func(Errors, string, interface{}) bool
IsValid func(Errors, string, interface{}) (bool, Errors)
}
// RuleMapper represents a validation rule mapper,
// it allwos users to add custom validation rules.
@ -361,12 +361,12 @@ VALIDATE_RULES:
break VALIDATE_RULES
}
case rule == "AlphaDash":
if alphaDashPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
if AlphaDashPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
errors.Add([]string{field.Name}, ERR_ALPHA_DASH, "AlphaDash")
break VALIDATE_RULES
}
case rule == "AlphaDashDot":
if alphaDashDotPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
if AlphaDashDotPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
errors.Add([]string{field.Name}, ERR_ALPHA_DASH_DOT, "AlphaDashDot")
break VALIDATE_RULES
}
@ -414,7 +414,7 @@ VALIDATE_RULES:
break VALIDATE_RULES
}
case rule == "Email":
if !emailPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
if !EmailPattern.MatchString(fmt.Sprintf("%v", fieldValue)) {
errors.Add([]string{field.Name}, ERR_EMAIL, "Email")
break VALIDATE_RULES
}
@ -422,7 +422,7 @@ VALIDATE_RULES:
str := fmt.Sprintf("%v", fieldValue)
if len(str) == 0 {
continue
} else if !urlPattern.MatchString(str) {
} else if !URLPattern.MatchString(str) {
errors.Add([]string{field.Name}, ERR_URL, "Url")
break VALIDATE_RULES
}
@ -449,7 +449,7 @@ VALIDATE_RULES:
case strings.HasPrefix(rule, "Default("):
if reflect.DeepEqual(zero, fieldValue) {
if fieldVal.CanAddr() {
setWithProperType(field.Type.Kind(), rule[8:len(rule)-1], fieldVal, field.Tag.Get("form"), errors)
errors = setWithProperType(field.Type.Kind(), rule[8:len(rule)-1], fieldVal, field.Tag.Get("form"), errors)
} else {
errors.Add([]string{field.Name}, ERR_EXCLUDE, "Default")
break VALIDATE_RULES
@ -457,9 +457,13 @@ VALIDATE_RULES:
}
default:
// Apply custom validation rules.
var isValid bool
for i := range ruleMapper {
if ruleMapper[i].IsMatch(rule) && !ruleMapper[i].IsValid(errors, field.Name, fieldValue) {
break VALIDATE_RULES
if ruleMapper[i].IsMatch(rule) {
isValid, errors = ruleMapper[i].IsValid(errors, field.Name, fieldValue)
if !isValid {
break VALIDATE_RULES
}
}
}
}
@ -493,7 +497,7 @@ func SetNameMapper(nm NameMapper) {
// Takes values from the form data and puts them into a struct
func mapForm(formStruct reflect.Value, form map[string][]string,
formfile map[string][]*multipart.FileHeader, errors Errors) {
formfile map[string][]*multipart.FileHeader, errors Errors) Errors {
if formStruct.Kind() == reflect.Ptr {
formStruct = formStruct.Elem()
@ -506,12 +510,12 @@ func mapForm(formStruct reflect.Value, form map[string][]string,
if typeField.Type.Kind() == reflect.Ptr && typeField.Anonymous {
structField.Set(reflect.New(typeField.Type.Elem()))
mapForm(structField.Elem(), form, formfile, errors)
errors = mapForm(structField.Elem(), form, formfile, errors)
if reflect.DeepEqual(structField.Elem().Interface(), reflect.Zero(structField.Elem().Type()).Interface()) {
structField.Set(reflect.Zero(structField.Type()))
}
} else if typeField.Type.Kind() == reflect.Struct {
mapForm(structField, form, formfile, errors)
errors = mapForm(structField, form, formfile, errors)
}
inputFieldName := parseFormName(typeField.Name, typeField.Tag.Get("form"))
@ -526,11 +530,11 @@ func mapForm(formStruct reflect.Value, form map[string][]string,
sliceOf := structField.Type().Elem().Kind()
slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
for i := 0; i < numElems; i++ {
setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors)
errors = setWithProperType(sliceOf, inputValue[i], slice.Index(i), inputFieldName, errors)
}
formStruct.Field(i).Set(slice)
} else {
setWithProperType(typeField.Type.Kind(), inputValue[0], structField, inputFieldName, errors)
errors = setWithProperType(typeField.Type.Kind(), inputValue[0], structField, inputFieldName, errors)
}
continue
}
@ -551,13 +555,14 @@ func mapForm(formStruct reflect.Value, form map[string][]string,
structField.Set(reflect.ValueOf(inputFile[0]))
}
}
return errors
}
// This sets the value in a struct of an indeterminate type to the
// matching value from the request (via Form middleware) in the
// same type, so that not all deserialized values have to be strings.
// Supported types are string, int, float, and bool.
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors Errors) {
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value, nameInTag string, errors Errors) Errors {
switch valueKind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if val == "" {
@ -582,7 +587,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
case reflect.Bool:
if val == "on" {
structField.SetBool(true)
return
break
}
if val == "" {
@ -617,6 +622,7 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
case reflect.String:
structField.SetString(val)
}
return errors
}
// Don't pass in pointers to bind to. Can lead to bugs.

View File

@ -1,14 +0,0 @@
sudo: false
language: go
go:
- 1.3
- 1.4
- 1.5
- tip
script: go test -v -cover -race
notifications:
email:
- u@gogs.io

View File

@ -50,6 +50,34 @@ type Invoker interface {
Invoke(interface{}) ([]reflect.Value, error)
}
// FastInvoker represents an interface in order to avoid the calling function via reflection.
//
// example:
// type handlerFuncHandler func(http.ResponseWriter, *http.Request) error
// func (f handlerFuncHandler)Invoke([]interface{}) ([]reflect.Value, error){
// ret := f(p[0].(http.ResponseWriter), p[1].(*http.Request))
// return []reflect.Value{reflect.ValueOf(ret)}, nil
// }
//
// type funcHandler func(int, string)
// func (f funcHandler)Invoke([]interface{}) ([]reflect.Value, error){
// f(p[0].(int), p[1].(string))
// return nil, nil
// }
type FastInvoker interface {
// Invoke attempts to call the ordinary functions. If f is a function
// with the appropriate signature, f.Invoke([]interface{}) is a Call that calls f.
// Returns a slice of reflect.Value representing the returned values of the function.
// Returns an error if the injection fails.
Invoke([]interface{}) ([]reflect.Value, error)
}
// IsFastInvoker check interface is FastInvoker
func IsFastInvoker(h interface{}) bool {
_, ok := h.(FastInvoker)
return ok
}
// TypeMapper represents an interface for mapping interface{} values based on type.
type TypeMapper interface {
// Maps the interface{} value based on its immediate type from reflect.TypeOf.
@ -102,18 +130,50 @@ func New() Injector {
// It panics if f is not a function
func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
t := reflect.TypeOf(f)
var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
for i := 0; i < t.NumIn(); i++ {
argType := t.In(i)
val := inj.GetVal(argType)
if !val.IsValid() {
return nil, fmt.Errorf("Value not found for type %v", argType)
}
in[i] = val
switch v := f.(type) {
case FastInvoker:
return inj.fastInvoke(v, t, t.NumIn())
default:
return inj.callInvoke(f, t, t.NumIn())
}
}
func (inj *injector) fastInvoke(f FastInvoker, t reflect.Type, numIn int) ([]reflect.Value, error) {
var in []interface{}
if numIn > 0 {
in = make([]interface{}, numIn) // Panic if t is not kind of Func
var argType reflect.Type
var val reflect.Value
for i := 0; i < numIn; i++ {
argType = t.In(i)
val = inj.GetVal(argType)
if !val.IsValid() {
return nil, fmt.Errorf("Value not found for type %v", argType)
}
in[i] = val.Interface()
}
}
return f.Invoke(in)
}
// callInvoke reflect.Value.Call
func (inj *injector) callInvoke(f interface{}, t reflect.Type, numIn int) ([]reflect.Value, error) {
var in []reflect.Value
if numIn > 0 {
in = make([]reflect.Value, numIn)
var argType reflect.Type
var val reflect.Value
for i := 0; i < numIn; i++ {
argType = t.In(i)
val = inj.GetVal(argType)
if !val.IsValid() {
return nil, fmt.Errorf("Value not found for type %v", argType)
}
in[i] = val
}
}
return reflect.ValueOf(f).Call(in), nil
}

View File

@ -1,2 +0,0 @@
ledis/tmp.db
nodb/tmp.db

View File

@ -1,14 +0,0 @@
sudo: false
language: go
go:
- 1.3
- 1.4
- 1.5
- tip
script: go test -v -cover -race
notifications:
email:
- u@gogs.io

View File

@ -1,4 +1,4 @@
# session [![Build Status](https://travis-ci.org/go-macaron/session.svg?branch=master)](https://travis-ci.org/go-macaron/session) [![](http://gocover.io/_badge/github.com/go-macaron/session)](http://gocover.io/github.com/go-macaron/session)
# session [![Build Status](https://travis-ci.org/go-macaron/session.svg?branch=master)](https://travis-ci.org/go-macaron/session)
Middleware session provides session management for [Macaron](https://github.com/go-macaron/macaron). It can use many session providers, including memory, file, Redis, Memcache, PostgreSQL, MySQL, Couchbase, Ledis and Nodb.
@ -9,7 +9,7 @@ Middleware session provides session management for [Macaron](https://github.com/
## Getting Help
- [API Reference](https://gowalker.org/github.com/go-macaron/session)
- [Documentation](http://go-macaron.com/docs/middlewares/session)
- [Documentation](https://go-macaron.com/docs/middlewares/session)
## Credits

View File

@ -86,7 +86,7 @@ func (s *FileStore) Release() error {
return err
}
return ioutil.WriteFile(s.p.filepath(s.sid), data, os.ModePerm)
return ioutil.WriteFile(s.p.filepath(s.sid), data, 0600)
}
// Flush deletes all session data.
@ -121,7 +121,7 @@ func (p *FileProvider) filepath(sid string) string {
// Read returns raw session store by session ID.
func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
filename := p.filepath(sid)
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil {
if err = os.MkdirAll(path.Dir(filename), 0700); err != nil {
return nil, err
}
p.lock.RLock()
@ -129,7 +129,7 @@ func (p *FileProvider) Read(sid string) (_ RawStore, err error) {
var f *os.File
if com.IsFile(filename) {
f, err = os.OpenFile(filename, os.O_RDWR, os.ModePerm)
f, err = os.OpenFile(filename, os.O_RDONLY, 0600)
} else {
f, err = os.Create(filename)
}
@ -187,15 +187,15 @@ func (p *FileProvider) regenerate(oldsid, sid string) (err error) {
if err != nil {
return err
}
if err = os.MkdirAll(path.Dir(oldname), os.ModePerm); err != nil {
if err = os.MkdirAll(path.Dir(oldname), 0700); err != nil {
return err
}
if err = ioutil.WriteFile(oldname, data, os.ModePerm); err != nil {
if err = ioutil.WriteFile(oldname, data, 0600); err != nil {
return err
}
}
if err = os.MkdirAll(path.Dir(filename), os.ModePerm); err != nil {
if err = os.MkdirAll(path.Dir(filename), 0700); err != nil {
return err
}
if err = os.Rename(oldname, filename); err != nil {

27
vendor/golang.org/x/crypto/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/golang.org/x/crypto/PATENTS generated vendored Normal file
View File

@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

77
vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go generated vendored Normal file
View File

@ -0,0 +1,77 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
2898 / PKCS #5 v2.0.
A key derivation function is useful when encrypting data based on a password
or any other not-fully-random data. It uses a pseudorandom function to derive
a secure encryption key based on the password.
While v2.0 of the standard defines only one pseudorandom function to use,
HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
choose, you can pass the `New` functions from the different SHA packages to
pbkdf2.Key.
*/
package pbkdf2 // import "golang.org/x/crypto/pbkdf2"
import (
"crypto/hmac"
"hash"
)
// Key derives a key from the password, salt and iteration count, returning a
// []byte of length keylen that can be used as cryptographic key. The key is
// derived based on the method described as PBKDF2 with the HMAC variant using
// the supplied hash function.
//
// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
// doing:
//
// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
//
// Remember to get a good random salt. At least 8 bytes is recommended by the
// RFC.
//
// Using a higher iteration count will increase the cost of an exhaustive
// search but will also make derivation proportionally slower.
func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
prf := hmac.New(h, password)
hashLen := prf.Size()
numBlocks := (keyLen + hashLen - 1) / hashLen
var buf [4]byte
dk := make([]byte, 0, numBlocks*hashLen)
U := make([]byte, hashLen)
for block := 1; block <= numBlocks; block++ {
// N.B.: || means concatenation, ^ means XOR
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
// U_1 = PRF(password, salt || uint(i))
prf.Reset()
prf.Write(salt)
buf[0] = byte(block >> 24)
buf[1] = byte(block >> 16)
buf[2] = byte(block >> 8)
buf[3] = byte(block)
prf.Write(buf[:4])
dk = prf.Sum(dk)
T := dk[len(dk)-hashLen:]
copy(U, T)
// U_n = PRF(password, U_(n-1))
for n := 2; n <= iter; n++ {
prf.Reset()
prf.Write(U)
U = U[:0]
U = prf.Sum(U)
for x := range U {
T[x] ^= U[x]
}
}
}
return dk[:keyLen]
}

View File

@ -1,2 +0,0 @@
macaron.sublime-project
macaron.sublime-workspace

View File

@ -1,13 +0,0 @@
sudo: false
language: go
go:
- 1.3
- 1.4
- 1.5
script: go test -v -cover -race
notifications:
email:
- u@gogs.io

14
vendor/gopkg.in/macaron.v1/README.md generated vendored
View File

@ -1,12 +1,10 @@
Macaron [![Build Status](https://travis-ci.org/go-macaron/macaron.svg?branch=v1)](https://travis-ci.org/go-macaron/macaron) [![](http://gocover.io/_badge/github.com/go-macaron/macaron)](http://gocover.io/github.com/go-macaron/macaron)
Macaron [![Build Status](https://travis-ci.org/go-macaron/macaron.svg?branch=v1)](https://travis-ci.org/go-macaron/macaron)
=======================
![Macaron Logo](https://raw.githubusercontent.com/go-macaron/macaron/v1/macaronlogo.png)
Package macaron is a high productive and modular web framework in Go.
##### Current version: 0.8.0
## Getting Started
The minimum requirement of Go is **1.3**.
@ -70,18 +68,18 @@ There are already many [middlewares](https://github.com/go-macaron) to simplify
## Use Cases
- [Gogs](http://gogs.io): A painless self-hosted Git Service
- [Peach](http://peachdocs.org): A modern web documentation server
- [Gogs](https://gogs.io): A painless self-hosted Git Service
- [Peach](https://peachdocs.org): A modern web documentation server
- [Go Walker](https://gowalker.org): Go online API documentation
- [Switch](http://gopm.io): Gopm registry
- [Switch](https://gopm.io): Gopm registry
- [YouGam](http://yougam.com): Online Forum
- [Critical Stack Intel](https://intel.criticalstack.com/): A 100% free intel marketplace from Critical Stack, Inc.
## Getting Help
- [API Reference](https://gowalker.org/gopkg.in/macaron.v1)
- [Documentation](http://go-macaron.com)
- [FAQs](http://go-macaron.com/docs/faqs)
- [Documentation](https://go-macaron.com)
- [FAQs](https://go-macaron.com/docs/faqs)
- [![Join the chat at https://gitter.im/Unknwon/macaron](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-macaron/macaron?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Credits

View File

@ -15,7 +15,7 @@
package macaron
import (
"crypto/md5"
"crypto/sha256"
"encoding/hex"
"html/template"
"io"
@ -32,8 +32,8 @@ import (
"time"
"github.com/Unknwon/com"
"github.com/go-macaron/inject"
"golang.org/x/crypto/pbkdf2"
)
// Locale reprents a localization interface.
@ -72,6 +72,14 @@ func (r *Request) Body() *RequestBody {
return &RequestBody{r.Request.Body}
}
// ContextInvoker is an inject.FastInvoker wrapper of func(ctx *Context).
type ContextInvoker func(ctx *Context)
func (invoke ContextInvoker) Invoke(params []interface{}) ([]reflect.Value, error) {
invoke(params[0].(*Context))
return nil, nil
}
// Context represents the runtime context of current request of Macaron instance.
// It is the integration of most frequently used middlewares and helper methods.
type Context struct {
@ -84,7 +92,7 @@ type Context struct {
Req Request
Resp ResponseWriter
params Params
Render // Not nil only if you use macaran.Render middleware.
Render
Locale
Data map[string]interface{}
}
@ -145,9 +153,6 @@ func (ctx *Context) RemoteAddr() string {
}
func (ctx *Context) renderHTML(status int, setName, tplName string, data ...interface{}) {
if ctx.Render == nil {
panic("renderer middleware hasn't been registered")
}
if len(data) <= 0 {
ctx.Render.HTMLSet(status, setName, tplName, ctx.Data)
} else if len(data) == 1 {
@ -159,7 +164,7 @@ func (ctx *Context) renderHTML(status int, setName, tplName string, data ...inte
// HTML calls Render.HTML but allows less arguments.
func (ctx *Context) HTML(status int, name string, data ...interface{}) {
ctx.renderHTML(status, _DEFAULT_TPL_SET_NAME, name, data...)
ctx.renderHTML(status, DEFAULT_TPL_SET_NAME, name, data...)
}
// HTML calls Render.HTMLSet but allows less arguments.
@ -221,6 +226,12 @@ func (ctx *Context) QueryEscape(name string) string {
return template.HTMLEscapeString(ctx.Query(name))
}
// QueryBool returns query result in bool type.
func (ctx *Context) QueryBool(name string) bool {
v, _ := strconv.ParseBool(ctx.Query(name))
return v
}
// QueryInt returns query result in int type.
func (ctx *Context) QueryInt(name string) int {
return com.StrTo(ctx.Query(name)).MustInt()
@ -353,6 +364,13 @@ func (ctx *Context) SetCookie(name string, value string, others ...interface{})
}
}
if len(others) > 5 {
if v, ok := others[5].(time.Time); ok {
cookie.Expires = v
cookie.RawExpires = v.Format(time.UnixDate)
}
}
ctx.Resp.Header().Add("Set-Cookie", cookie.String())
}
@ -401,30 +419,29 @@ func (ctx *Context) GetSecureCookie(key string) (string, bool) {
// SetSuperSecureCookie sets given cookie value to response header with secret string.
func (ctx *Context) SetSuperSecureCookie(secret, name, value string, others ...interface{}) {
m := md5.Sum([]byte(secret))
secret = hex.EncodeToString(m[:])
text, err := com.AESEncrypt([]byte(secret), []byte(value))
key := pbkdf2.Key([]byte(secret), []byte(secret), 1000, 16, sha256.New)
text, err := com.AESGCMEncrypt(key, []byte(value))
if err != nil {
panic("error encrypting cookie: " + err.Error())
}
ctx.SetCookie(name, hex.EncodeToString(text), others...)
}
// GetSuperSecureCookie returns given cookie value from request header with secret string.
func (ctx *Context) GetSuperSecureCookie(secret, key string) (string, bool) {
val := ctx.GetCookie(key)
func (ctx *Context) GetSuperSecureCookie(secret, name string) (string, bool) {
val := ctx.GetCookie(name)
if val == "" {
return "", false
}
data, err := hex.DecodeString(val)
text, err := hex.DecodeString(val)
if err != nil {
return "", false
}
m := md5.Sum([]byte(secret))
secret = hex.EncodeToString(m[:])
text, err := com.AESDecrypt([]byte(secret), data)
key := pbkdf2.Key([]byte(secret), []byte(secret), 1000, 16, sha256.New)
text, err = com.AESGCMDecrypt(key, text)
return string(text), err == nil
}

18
vendor/gopkg.in/macaron.v1/logger.go generated vendored
View File

@ -19,27 +19,39 @@ import (
"fmt"
"log"
"net/http"
"reflect"
"runtime"
"time"
)
var ColorLog = true
var (
ColorLog = true
LogTimeFormat = "2006-01-02 15:04:05"
)
func init() {
ColorLog = runtime.GOOS != "windows"
}
// LoggerInvoker is an inject.FastInvoker wrapper of func(ctx *Context, log *log.Logger).
type LoggerInvoker func(ctx *Context, log *log.Logger)
func (invoke LoggerInvoker) Invoke(params []interface{}) ([]reflect.Value, error) {
invoke(params[0].(*Context), params[1].(*log.Logger))
return nil, nil
}
// Logger returns a middleware handler that logs the request as it goes in and the response as it goes out.
func Logger() Handler {
return func(ctx *Context, log *log.Logger) {
start := time.Now()
log.Printf("Started %s %s for %s", ctx.Req.Method, ctx.Req.RequestURI, ctx.RemoteAddr())
log.Printf("%s: Started %s %s for %s", time.Now().Format(LogTimeFormat), ctx.Req.Method, ctx.Req.RequestURI, ctx.RemoteAddr())
rw := ctx.Resp.(ResponseWriter)
ctx.Next()
content := fmt.Sprintf("Completed %s %v %s in %v", ctx.Req.RequestURI, rw.Status(), http.StatusText(rw.Status()), time.Since(start))
content := fmt.Sprintf("%s: Completed %s %v %s in %v", time.Now().Format(LogTimeFormat), ctx.Req.RequestURI, rw.Status(), http.StatusText(rw.Status()), time.Since(start))
if ColorLog {
switch rw.Status() {
case 200, 201, 202:

View File

@ -24,6 +24,7 @@ import (
"os"
"reflect"
"strings"
"sync"
"github.com/Unknwon/com"
"gopkg.in/ini.v1"
@ -31,7 +32,7 @@ import (
"github.com/go-macaron/inject"
)
const _VERSION = "0.8.0.1013"
const _VERSION = "1.2.1.0213"
func Version() string {
return _VERSION
@ -42,20 +43,63 @@ func Version() string {
// and panics if an argument could not be fullfilled via dependency injection.
type Handler interface{}
// validateHandler makes sure a handler is a callable function,
// and panics if it is not.
func validateHandler(h Handler) {
// handlerFuncInvoker is an inject.FastInvoker wrapper of func(http.ResponseWriter, *http.Request).
type handlerFuncInvoker func(http.ResponseWriter, *http.Request)
func (invoke handlerFuncInvoker) Invoke(params []interface{}) ([]reflect.Value, error) {
invoke(params[0].(http.ResponseWriter), params[1].(*http.Request))
return nil, nil
}
// internalServerErrorInvoker is an inject.FastInvoker wrapper of func(rw http.ResponseWriter, err error).
type internalServerErrorInvoker func(rw http.ResponseWriter, err error)
func (invoke internalServerErrorInvoker) Invoke(params []interface{}) ([]reflect.Value, error) {
invoke(params[0].(http.ResponseWriter), params[1].(error))
return nil, nil
}
// validateAndWrapHandler makes sure a handler is a callable function, it panics if not.
// When the handler is also potential to be any built-in inject.FastInvoker,
// it wraps the handler automatically to have some performance gain.
func validateAndWrapHandler(h Handler) Handler {
if reflect.TypeOf(h).Kind() != reflect.Func {
panic("Macaron handler must be a callable function")
}
if !inject.IsFastInvoker(h) {
switch v := h.(type) {
case func(*Context):
return ContextInvoker(v)
case func(*Context, *log.Logger):
return LoggerInvoker(v)
case func(http.ResponseWriter, *http.Request):
return handlerFuncInvoker(v)
case func(http.ResponseWriter, error):
return internalServerErrorInvoker(v)
}
}
return h
}
// validateHandlers makes sure handlers are callable functions,
// and panics if any of them is not.
func validateHandlers(handlers []Handler) {
for _, h := range handlers {
validateHandler(h)
// validateAndWrapHandlers preforms validation and wrapping for each input handler.
// It accepts an optional wrapper function to perform custom wrapping on handlers.
func validateAndWrapHandlers(handlers []Handler, wrappers ...func(Handler) Handler) []Handler {
var wrapper func(Handler) Handler
if len(wrappers) > 0 {
wrapper = wrappers[0]
}
wrappedHandlers := make([]Handler, len(handlers))
for i, h := range handlers {
h = validateAndWrapHandler(h)
if wrapper != nil && !inject.IsFastInvoker(h) {
h = wrapper(h)
}
wrappedHandlers[i] = h
}
return wrappedHandlers
}
// Macaron represents the top level web application.
@ -100,7 +144,7 @@ func New() *Macaron {
}
// Classic creates a classic Macaron with some basic default middleware:
// mocaron.Logger, mocaron.Recovery and mocaron.Static.
// macaron.Logger, macaron.Recovery and macaron.Static.
func Classic() *Macaron {
m := New()
m.Use(Logger())
@ -122,7 +166,7 @@ func (m *Macaron) Handlers(handlers ...Handler) {
// Action sets the handler that will be called after all the middleware has been invoked.
// This is set to macaron.Router in a macaron.Classic().
func (m *Macaron) Action(handler Handler) {
validateHandler(handler)
handler = validateAndWrapHandler(handler)
m.action = handler
}
@ -138,7 +182,7 @@ func (m *Macaron) Before(handler BeforeHandler) {
// and panics if the handler is not a callable func.
// Middleware Handlers are invoked in the order that they are added.
func (m *Macaron) Use(handler Handler) {
validateHandler(handler)
handler = validateAndWrapHandler(handler)
m.handlers = append(m.handlers, handler)
}
@ -151,6 +195,7 @@ func (m *Macaron) createContext(rw http.ResponseWriter, req *http.Request) *Cont
Router: m.Router,
Req: Request{req},
Resp: NewResponseWriter(rw),
Render: &DummyRender{rw},
Data: make(map[string]interface{}),
}
c.SetParent(m)
@ -208,7 +253,7 @@ func (m *Macaron) Run(args ...interface{}) {
addr := host + ":" + com.ToStr(port)
logger := m.GetVal(reflect.TypeOf(m.logger)).Interface().(*log.Logger)
logger.Printf("listening on %s (%s)\n", addr, Env)
logger.Printf("listening on %s (%s)\n", addr, safeEnv())
logger.Fatalln(http.ListenAndServe(addr, m))
}
@ -234,7 +279,8 @@ const (
var (
// Env is the environment that Macaron is executing in.
// The MACARON_ENV is read on initialization to set this variable.
Env = DEV
Env = DEV
envLock sync.Mutex
// Path of work directory.
Root string
@ -247,11 +293,21 @@ var (
)
func setENV(e string) {
envLock.Lock()
defer envLock.Unlock()
if len(e) > 0 {
Env = e
}
}
func safeEnv() string {
envLock.Lock()
defer envLock.Unlock()
return Env
}
func init() {
setENV(os.Getenv("MACARON_ENV"))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 87 KiB

196
vendor/gopkg.in/macaron.v1/render.go generated vendored
View File

@ -21,6 +21,7 @@ import (
"encoding/xml"
"fmt"
"html/template"
"io"
"io/ioutil"
"net/http"
"os"
@ -72,6 +73,7 @@ type (
// TemplateFileSystem represents a interface of template file system that able to list all files.
TemplateFileSystem interface {
ListFiles() []TemplateFile
Get(string) (io.Reader, error)
}
// Delims represents a set of Left and Right delimiters for HTML template rendering
@ -86,6 +88,8 @@ type (
RenderOptions struct {
// Directory to load templates. Default is "templates".
Directory string
// Addtional directories to overwite templates.
AppendDirectories []string
// Layout template name. Will not render a layout if "". Default is to "".
Layout string
// Extensions to parse template files from. Defaults are [".tmpl", ".html"].
@ -172,8 +176,32 @@ func NewTemplateFileSystem(opt RenderOptions, omitData bool) TplFileSystem {
fs := TplFileSystem{}
fs.files = make([]TemplateFile, 0, 10)
if err := filepath.Walk(opt.Directory, func(path string, info os.FileInfo, err error) error {
r, err := filepath.Rel(opt.Directory, path)
// Directories are composed in reverse order because later one overwrites previous ones,
// so once found, we can directly jump out of the loop.
dirs := make([]string, 0, len(opt.AppendDirectories)+1)
for i := len(opt.AppendDirectories) - 1; i >= 0; i-- {
dirs = append(dirs, opt.AppendDirectories[i])
}
dirs = append(dirs, opt.Directory)
var err error
for i := range dirs {
// Skip ones that does not exists for symlink test,
// but allow non-symlink ones added after start.
if !com.IsExist(dirs[i]) {
continue
}
dirs[i], err = filepath.EvalSymlinks(dirs[i])
if err != nil {
panic("EvalSymlinks(" + dirs[i] + "): " + err.Error())
}
}
lastDir := dirs[len(dirs)-1]
// We still walk the last (original) directory because it's non-sense we load templates not exist in original directory.
if err = filepath.Walk(lastDir, func(path string, info os.FileInfo, err error) error {
r, err := filepath.Rel(lastDir, path)
if err != nil {
return err
}
@ -181,19 +209,31 @@ func NewTemplateFileSystem(opt RenderOptions, omitData bool) TplFileSystem {
ext := GetExt(r)
for _, extension := range opt.Extensions {
if ext == extension {
var data []byte
if !omitData {
if ext != extension {
continue
}
var data []byte
if !omitData {
// Loop over candidates of directory, break out once found.
// The file always exists because it's inside the walk function,
// and read original file is the worst case.
for i := range dirs {
path = filepath.Join(dirs[i], r)
if !com.IsFile(path) {
continue
}
data, err = ioutil.ReadFile(path)
if err != nil {
return err
}
break
}
name := filepath.ToSlash((r[0 : len(r)-len(ext)]))
fs.files = append(fs.files, NewTplFile(name, data, ext))
break
}
name := filepath.ToSlash((r[0 : len(r)-len(ext)]))
fs.files = append(fs.files, NewTplFile(name, data, ext))
}
return nil
@ -208,6 +248,15 @@ func (fs TplFileSystem) ListFiles() []TemplateFile {
return fs.files
}
func (fs TplFileSystem) Get(name string) (io.Reader, error) {
for i := range fs.files {
if fs.files[i].Name()+fs.files[i].Ext() == name {
return bytes.NewReader(fs.files[i].Data()), nil
}
}
return nil, fmt.Errorf("file '%s' not found", name)
}
func PrepareCharset(charset string) string {
if len(charset) != 0 {
return "; charset=" + charset
@ -225,8 +274,7 @@ func GetExt(s string) string {
}
func compile(opt RenderOptions) *template.Template {
dir := opt.Directory
t := template.New(dir)
t := template.New(opt.Directory)
t.Delims(opt.Delims.Left, opt.Delims.Right)
// Parse an initial template in case we don't have any.
template.Must(t.Parse("Macaron"))
@ -248,24 +296,25 @@ func compile(opt RenderOptions) *template.Template {
}
const (
_DEFAULT_TPL_SET_NAME = "DEFAULT"
DEFAULT_TPL_SET_NAME = "DEFAULT"
)
// templateSet represents a template set of type *template.Template.
type templateSet struct {
// TemplateSet represents a template set of type *template.Template.
type TemplateSet struct {
lock sync.RWMutex
sets map[string]*template.Template
dirs map[string]string
}
func newTemplateSet() *templateSet {
return &templateSet{
// NewTemplateSet initializes a new empty template set.
func NewTemplateSet() *TemplateSet {
return &TemplateSet{
sets: make(map[string]*template.Template),
dirs: make(map[string]string),
}
}
func (ts *templateSet) Set(name string, opt *RenderOptions) *template.Template {
func (ts *TemplateSet) Set(name string, opt *RenderOptions) *template.Template {
t := compile(*opt)
ts.lock.Lock()
@ -276,14 +325,14 @@ func (ts *templateSet) Set(name string, opt *RenderOptions) *template.Template {
return t
}
func (ts *templateSet) Get(name string) *template.Template {
func (ts *TemplateSet) Get(name string) *template.Template {
ts.lock.RLock()
defer ts.lock.RUnlock()
return ts.sets[name]
}
func (ts *templateSet) GetDir(name string) string {
func (ts *TemplateSet) GetDir(name string) string {
ts.lock.RLock()
defer ts.lock.RUnlock()
@ -332,8 +381,8 @@ func ParseTplSet(tplSet string) (tplName string, tplDir string) {
func renderHandler(opt RenderOptions, tplSets []string) Handler {
cs := PrepareCharset(opt.Charset)
ts := newTemplateSet()
ts.Set(_DEFAULT_TPL_SET_NAME, &opt)
ts := NewTemplateSet()
ts.Set(DEFAULT_TPL_SET_NAME, &opt)
var tmpOpt RenderOptions
for _, tplSet := range tplSets {
@ -346,7 +395,7 @@ func renderHandler(opt RenderOptions, tplSets []string) Handler {
return func(ctx *Context) {
r := &TplRender{
ResponseWriter: ctx.Resp,
templateSet: ts,
TemplateSet: ts,
Opt: &opt,
CompiledCharset: cs,
}
@ -379,7 +428,7 @@ func Renderers(options RenderOptions, tplSets ...string) Handler {
type TplRender struct {
http.ResponseWriter
*templateSet
*TemplateSet
Opt *RenderOptions
CompiledCharset string
@ -486,11 +535,11 @@ func (r *TplRender) addYield(t *template.Template, tplName string, data interfac
}
func (r *TplRender) renderBytes(setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) (*bytes.Buffer, error) {
t := r.templateSet.Get(setName)
t := r.TemplateSet.Get(setName)
if Env == DEV {
opt := *r.Opt
opt.Directory = r.templateSet.GetDir(setName)
t = r.templateSet.Set(setName, &opt)
opt.Directory = r.TemplateSet.GetDir(setName)
t = r.TemplateSet.Set(setName, &opt)
}
if t == nil {
return nil, fmt.Errorf("html/template: template \"%s\" is undefined", tplName)
@ -523,12 +572,14 @@ func (r *TplRender) renderHTML(status int, setName, tplName string, data interfa
r.Header().Set(_CONTENT_TYPE, r.Opt.HTMLContentType+r.CompiledCharset)
r.WriteHeader(status)
out.WriteTo(r)
if _, err := out.WriteTo(r); err != nil {
out.Reset()
}
bufpool.Put(out)
}
func (r *TplRender) HTML(status int, name string, data interface{}, htmlOpt ...HTMLOptions) {
r.renderHTML(status, _DEFAULT_TPL_SET_NAME, name, data, htmlOpt...)
r.renderHTML(status, DEFAULT_TPL_SET_NAME, name, data, htmlOpt...)
}
func (r *TplRender) HTMLSet(status int, setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) {
@ -544,7 +595,7 @@ func (r *TplRender) HTMLSetBytes(setName, tplName string, data interface{}, html
}
func (r *TplRender) HTMLBytes(name string, data interface{}, htmlOpt ...HTMLOptions) ([]byte, error) {
return r.HTMLSetBytes(_DEFAULT_TPL_SET_NAME, name, data, htmlOpt...)
return r.HTMLSetBytes(DEFAULT_TPL_SET_NAME, name, data, htmlOpt...)
}
func (r *TplRender) HTMLSetString(setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) (string, error) {
@ -581,13 +632,94 @@ func (r *TplRender) prepareHTMLOptions(htmlOpt []HTMLOptions) HTMLOptions {
func (r *TplRender) SetTemplatePath(setName, dir string) {
if len(setName) == 0 {
setName = _DEFAULT_TPL_SET_NAME
setName = DEFAULT_TPL_SET_NAME
}
opt := *r.Opt
opt.Directory = dir
r.templateSet.Set(setName, &opt)
r.TemplateSet.Set(setName, &opt)
}
func (r *TplRender) HasTemplateSet(name string) bool {
return r.templateSet.Get(name) != nil
return r.TemplateSet.Get(name) != nil
}
// DummyRender is used when user does not choose any real render to use.
// This way, we can print out friendly message which asks them to register one,
// instead of ugly and confusing 'nil pointer' panic.
type DummyRender struct {
http.ResponseWriter
}
func renderNotRegistered() {
panic("middleware render hasn't been registered")
}
func (r *DummyRender) SetResponseWriter(http.ResponseWriter) {
renderNotRegistered()
}
func (r *DummyRender) JSON(int, interface{}) {
renderNotRegistered()
}
func (r *DummyRender) JSONString(interface{}) (string, error) {
renderNotRegistered()
return "", nil
}
func (r *DummyRender) RawData(int, []byte) {
renderNotRegistered()
}
func (r *DummyRender) PlainText(int, []byte) {
renderNotRegistered()
}
func (r *DummyRender) HTML(int, string, interface{}, ...HTMLOptions) {
renderNotRegistered()
}
func (r *DummyRender) HTMLSet(int, string, string, interface{}, ...HTMLOptions) {
renderNotRegistered()
}
func (r *DummyRender) HTMLSetString(string, string, interface{}, ...HTMLOptions) (string, error) {
renderNotRegistered()
return "", nil
}
func (r *DummyRender) HTMLString(string, interface{}, ...HTMLOptions) (string, error) {
renderNotRegistered()
return "", nil
}
func (r *DummyRender) HTMLSetBytes(string, string, interface{}, ...HTMLOptions) ([]byte, error) {
renderNotRegistered()
return nil, nil
}
func (r *DummyRender) HTMLBytes(string, interface{}, ...HTMLOptions) ([]byte, error) {
renderNotRegistered()
return nil, nil
}
func (r *DummyRender) XML(int, interface{}) {
renderNotRegistered()
}
func (r *DummyRender) Error(int, ...string) {
renderNotRegistered()
}
func (r *DummyRender) Status(int) {
renderNotRegistered()
}
func (r *DummyRender) SetTemplatePath(string, string) {
renderNotRegistered()
}
func (r *DummyRender) HasTemplateSet(string) bool {
renderNotRegistered()
return false
}

22
vendor/gopkg.in/macaron.v1/router.go generated vendored
View File

@ -82,6 +82,9 @@ type Router struct {
groups []group
notFound http.HandlerFunc
internalServerError func(*Context, error)
// handlerWrapper is used to wrap arbitrary function from Handler to inject.FastInvoker.
handlerWrapper func(Handler) Handler
}
func NewRouter() *Router {
@ -173,7 +176,7 @@ func (r *Router) Handle(method string, pattern string, handlers []Handler) *Rout
h = append(h, handlers...)
handlers = h
}
validateHandlers(handlers)
handlers = validateAndWrapHandlers(handlers, r.handlerWrapper)
return r.handle(method, pattern, func(resp http.ResponseWriter, req *http.Request, params Params) {
c := r.m.createContext(resp, req)
@ -251,23 +254,25 @@ func (r *Router) Combo(pattern string, h ...Handler) *ComboRouter {
return &ComboRouter{r, pattern, h, map[string]bool{}, nil}
}
// Configurable http.HandlerFunc which is called when no matching route is
// NotFound configurates http.HandlerFunc which is called when no matching route is
// found. If it is not set, http.NotFound is used.
// Be sure to set 404 response code in your handler.
func (r *Router) NotFound(handlers ...Handler) {
validateHandlers(handlers)
handlers = validateAndWrapHandlers(handlers)
r.notFound = func(rw http.ResponseWriter, req *http.Request) {
c := r.m.createContext(rw, req)
c.handlers = append(r.m.handlers, handlers...)
c.handlers = make([]Handler, 0, len(r.m.handlers)+len(handlers))
c.handlers = append(c.handlers, r.m.handlers...)
c.handlers = append(c.handlers, handlers...)
c.run()
}
}
// Configurable handler which is called when route handler returns
// InternalServerError configurates handler which is called when route handler returns
// error. If it is not set, default handler is used.
// Be sure to set 500 response code in your handler.
func (r *Router) InternalServerError(handlers ...Handler) {
validateHandlers(handlers)
handlers = validateAndWrapHandlers(handlers)
r.internalServerError = func(c *Context, err error) {
c.index = 0
c.handlers = handlers
@ -276,6 +281,11 @@ func (r *Router) InternalServerError(handlers ...Handler) {
}
}
// SetHandlerWrapper sets handlerWrapper for the router.
func (r *Router) SetHandlerWrapper(f func(Handler) Handler) {
r.handlerWrapper = f
}
func (r *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if t, ok := r.routers[req.Method]; ok {
h, p, ok := t.Match(req.URL.Path)

15
vendor/gopkg.in/macaron.v1/static.go generated vendored
View File

@ -16,6 +16,7 @@
package macaron
import (
"encoding/base64"
"log"
"net/http"
"path"
@ -35,6 +36,9 @@ type StaticOptions struct {
// Expires defines which user-defined function to use for producing a HTTP Expires Header
// https://developers.google.com/speed/docs/insights/LeverageBrowserCaching
Expires func() string
// ETag defines if we should add an ETag header
// https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#validating-cached-responses-with-etags
ETag bool
// FileSystem is the interface for supporting any implmentation of file system.
FileSystem http.FileSystem
}
@ -172,10 +176,21 @@ func staticHandler(ctx *Context, log *log.Logger, opt StaticOptions) bool {
ctx.Resp.Header().Set("Expires", opt.Expires())
}
if opt.ETag {
tag := GenerateETag(string(fi.Size()), fi.Name(), fi.ModTime().UTC().Format(http.TimeFormat))
ctx.Resp.Header().Set("ETag", tag)
}
http.ServeContent(ctx.Resp, ctx.Req.Request, file, fi.ModTime(), f)
return true
}
// GenerateETag generates an ETag based on size, filename and file modification time
func GenerateETag(fileSize, fileName, modTime string) string {
etag := fileSize + fileName + modTime
return base64.StdEncoding.EncodeToString([]byte(etag))
}
// Static returns a middleware handler that serves static files in the given directory.
func Static(directory string, staticOpt ...StaticOptions) Handler {
opt := prepareStaticOptions(directory, staticOpt)

36
vendor/vendor.json vendored
View File

@ -6,6 +6,12 @@
"path": "appengine/cloudsql",
"revision": ""
},
{
"checksumSHA1": "7HXb3cry6luicWeJM9Uxwzfo9Rs=",
"path": "github.com/Unknwon/com",
"revision": "0db4a625e949e956314d7d1adea9bf82384cc10c",
"revisionTime": "2017-02-13T07:20:14Z"
},
{
"checksumSHA1": "6nleggdedlS1mdzSnu1xf1Pnd+8=",
"path": "github.com/aws/aws-sdk-go",
@ -358,6 +364,24 @@
"version": "v1.21.1",
"versionExact": "v1.21.1"
},
{
"checksumSHA1": "OkqfwXeTVoiIxNMDA7HKvmrCDw8=",
"path": "github.com/go-macaron/binding",
"revision": "48920167fa152d02f228cfbece7e0f1e452d200a",
"revisionTime": "2016-12-22T07:05:54Z"
},
{
"checksumSHA1": "y0olVbiMQ6/UOa/eh52XYnies90=",
"path": "github.com/go-macaron/inject",
"revision": "d8a0b8677191f4380287cfebd08e462217bac7ad",
"revisionTime": "2016-06-27T17:00:12Z"
},
{
"checksumSHA1": "gO0dj0NqsmBTkf4D0JzJDtOEx+U=",
"path": "github.com/go-macaron/session",
"revision": "b8e286a0dba8f4999042d6b258daf51b31d08938",
"revisionTime": "2017-03-20T17:22:09Z"
},
{
"checksumSHA1": "42vkdsxNaLyPu+FktCzZ/8zsNSE=",
"path": "github.com/go-sql-driver/mysql",
@ -452,6 +476,12 @@
"revision": "5db88ed452e937f2fd557de6f4f1af7f2eabed0b",
"revisionTime": "2016-08-23T18:01:44Z"
},
{
"checksumSHA1": "1MGpGDQqnUoRpv7VEcQrXOBydXE=",
"path": "golang.org/x/crypto/pbkdf2",
"revision": "3543873453996aaab2fc6b3928a35fc5ca2b5afb",
"revisionTime": "2017-04-18T16:44:36Z"
},
{
"checksumSHA1": "WHc3uByvGaMcnSoI21fhzYgbOgg=",
"path": "golang.org/x/net/context/ctxhttp",
@ -487,6 +517,12 @@
"path": "gopkg.in/gomail.v2",
"revision": "81ebce5c23dfd25c6c67194b37d3dd3f338c98b1",
"revisionTime": "2016-04-11T21:29:32Z"
},
{
"checksumSHA1": "1HJvJZheB5NNl3i1R9zZJpiJ1G0=",
"path": "gopkg.in/macaron.v1",
"revision": "a325110f8b392bce3e5cdeb8c44bf98078ada3be",
"revisionTime": "2017-02-13T09:12:08Z"
}
],
"rootPath": "github.com/grafana/grafana"