update vendor

This commit is contained in:
deepzz0
2017-07-11 23:50:01 +08:00
parent e1ec5cd08a
commit c18d9c0bef
107 changed files with 8347 additions and 126 deletions

24
vendor/github.com/qiniu/x/.gitignore generated vendored Normal file
View File

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

10
vendor/github.com/qiniu/x/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,10 @@
language: go
install:
- export QINIU_SRC=$HOME/gopath/src
- mkdir -p $QINIU_SRC/qiniupkg.com
- mv $QINIU_SRC/github.com/qiniu/x $QINIU_SRC/qiniupkg.com/x
- export TRAVIS_BUILD_DIR=$QINIU_SRC/qiniupkg.com/x
- cd $TRAVIS_BUILD_DIR
- go get golang.org/x/net/context
- go get github.com/stretchr/testify/assert

27
vendor/github.com/qiniu/x/README.md generated vendored Normal file
View File

@@ -0,0 +1,27 @@
qiniupkg.com/x
===============
[![Build Status](https://travis-ci.org/qiniu/x.svg?branch=develop)](https://travis-ci.org/qiniu/x) [![GoDoc](https://godoc.org/qiniupkg.com/x?status.svg)](https://godoc.org/qiniupkg.com/x)
# 下载
```
go get qiniupkg.com/x
```
# 使用文档
* [qiniupkg.com/x/bytes.v7](http://godoc.org/qiniupkg.com/x/bytes.v7)
* [qiniupkg.com/x/cmdline.v7](http://godoc.org/qiniupkg.com/x/cmdline.v7)
* [qiniupkg.com/x/config.v7](http://godoc.org/qiniupkg.com/x/config.v7)
* [qiniupkg.com/x/ctype.v7](http://godoc.org/qiniupkg.com/x/ctype.v7)
* [qiniupkg.com/x/jsonutil.v7](http://godoc.org/qiniupkg.com/x/jsonutil.v7)
* [qiniupkg.com/x/log.v7](http://godoc.org/qiniupkg.com/x/log.v7)
* [qiniupkg.com/x/mockhttp.v7](http://godoc.org/qiniupkg.com/x/mockhttp.v7)
* [qiniupkg.com/x/reqid.v7](http://godoc.org/qiniupkg.com/x/reqid.v7)
* [qiniupkg.com/x/rpc.v7](http://godoc.org/qiniupkg.com/x/rpc.v7)
* [qiniupkg.com/x/rpc.v7/gob](http://godoc.org/qiniupkg.com/x/rpc.v7/gob)
* [qiniupkg.com/x/ts.v7](http://godoc.org/qiniupkg.com/x/ts.v7)
* [qiniupkg.com/x/url.v7](http://godoc.org/qiniupkg.com/x/url.v7)
* [qiniupkg.com/x/xlog.v7](http://godoc.org/qiniupkg.com/x/xlog.v7)

4
vendor/github.com/qiniu/x/bytes.v7/README.md generated vendored Normal file
View File

@@ -0,0 +1,4 @@
qiniupkg.com/x/bytes.v7
=====
Extension module of golang bytes processing

177
vendor/github.com/qiniu/x/bytes.v7/bytes.go generated vendored Normal file
View File

@@ -0,0 +1,177 @@
package bytes
import (
"io"
"syscall"
)
// ---------------------------------------------------
type Reader struct {
b []byte
off int
}
func NewReader(val []byte) *Reader {
return &Reader{val, 0}
}
func (r *Reader) Len() int {
if r.off >= len(r.b) {
return 0
}
return len(r.b) - r.off
}
func (r *Reader) Bytes() []byte {
return r.b[r.off:]
}
func (r *Reader) SeekToBegin() (err error) {
r.off = 0
return
}
func (r *Reader) Seek(offset int64, whence int) (ret int64, err error) {
switch whence {
case 0:
case 1:
offset += int64(r.off)
case 2:
offset += int64(len(r.b))
default:
err = syscall.EINVAL
return
}
if offset < 0 {
err = syscall.EINVAL
return
}
if offset >= int64(len(r.b)) {
r.off = len(r.b)
} else {
r.off = int(offset)
}
ret = int64(r.off)
return
}
func (r *Reader) Read(val []byte) (n int, err error) {
n = copy(val, r.b[r.off:])
if n == 0 && len(val) != 0 {
err = io.EOF
return
}
r.off += n
return
}
func (r *Reader) Close() (err error) {
return
}
// ---------------------------------------------------
type Writer struct {
b []byte
n int
}
func NewWriter(buff []byte) *Writer {
return &Writer{buff, 0}
}
func (p *Writer) Write(val []byte) (n int, err error) {
n = copy(p.b[p.n:], val)
if n == 0 && len(val) > 0 {
err = io.EOF
return
}
p.n += n
return
}
func (p *Writer) Len() int {
return p.n
}
func (p *Writer) Bytes() []byte {
return p.b[:p.n]
}
func (p *Writer) Reset() {
p.n = 0
}
// ---------------------------------------------------
type Buffer struct {
b []byte
}
func NewBuffer() *Buffer {
return new(Buffer)
}
func (p *Buffer) ReadAt(buf []byte, off int64) (n int, err error) {
ioff := int(off)
if len(p.b) <= ioff {
return 0, io.EOF
}
n = copy(buf, p.b[ioff:])
if n != len(buf) {
err = io.EOF
}
return
}
func (p *Buffer) WriteAt(buf []byte, off int64) (n int, err error) {
ioff := int(off)
iend := ioff + len(buf)
if len(p.b) < iend {
if len(p.b) == ioff {
p.b = append(p.b, buf...)
return len(buf), nil
}
zero := make([]byte, iend-len(p.b))
p.b = append(p.b, zero...)
}
copy(p.b[ioff:], buf)
return len(buf), nil
}
func (p *Buffer) WriteStringAt(buf string, off int64) (n int, err error) {
ioff := int(off)
iend := ioff + len(buf)
if len(p.b) < iend {
if len(p.b) == ioff {
p.b = append(p.b, buf...)
return len(buf), nil
}
zero := make([]byte, iend-len(p.b))
p.b = append(p.b, zero...)
}
copy(p.b[ioff:], buf)
return len(buf), nil
}
func (p *Buffer) Truncate(fsize int64) (err error) {
size := int(fsize)
if len(p.b) < size {
zero := make([]byte, size-len(p.b))
p.b = append(p.b, zero...)
} else {
p.b = p.b[:size]
}
return nil
}
func (p *Buffer) Buffer() []byte {
return p.b
}
func (p *Buffer) Len() int {
return len(p.b)
}
// ---------------------------------------------------

60
vendor/github.com/qiniu/x/bytes.v7/bytes_test.go generated vendored Normal file
View File

@@ -0,0 +1,60 @@
package bytes
import (
"io"
"testing"
)
// ---------------------------------------------------
func TestBuffer(t *testing.T) {
b := NewBuffer()
n, err := b.WriteStringAt("Hello", 4)
if n != 5 || err != nil {
t.Fatal("WriteStringAt failed:", n, err)
}
if b.Len() != 9 {
t.Fatal("Buffer.Len invalid (9 is required):", b.Len())
}
buf := make([]byte, 10)
n, err = b.ReadAt(buf, 50)
if n != 0 || err != io.EOF {
t.Fatal("ReadAt failed:", n, err)
}
n, err = b.ReadAt(buf, 6)
if n != 3 || err != io.EOF || string(buf[:n]) != "llo" {
t.Fatal("ReadAt failed:", n, err, string(buf[:n]))
}
n, err = b.WriteAt([]byte("Hi h"), 1)
if n != 4 || err != nil {
t.Fatal("WriteAt failed:", n, err)
}
if b.Len() != 9 {
t.Fatal("Buffer.Len invalid (9 is required):", b.Len())
}
n, err = b.ReadAt(buf, 0)
if n != 9 || err != io.EOF || string(buf[:n]) != "\x00Hi hello" {
t.Fatal("ReadAt failed:", n, err)
}
n, err = b.WriteStringAt("LO world!", 7)
if n != 9 || err != nil {
t.Fatal("WriteStringAt failed:", n, err)
}
if b.Len() != 16 {
t.Fatal("Buffer.Len invalid (16 is required):", b.Len())
}
buf = make([]byte, 17)
n, err = b.ReadAt(buf, 0)
if n != 16 || err != io.EOF || string(buf[:n]) != "\x00Hi helLO world!" {
t.Fatal("ReadAt failed:", n, err, string(buf[:n]))
}
}
// ---------------------------------------------------

34
vendor/github.com/qiniu/x/bytes.v7/doc.go generated vendored Normal file
View File

@@ -0,0 +1,34 @@
/*
包 qiniupkg.com/x/bytes.v7 提供了 byte slice 相关的功能扩展
NewReader 创建一个 byte slice 的只读流:
var slice []byte
...
r := bytes.NewReader(slice)
...
r.Seek(0, 0) // r.SeekToBegin()
...
和标准库的 bytes.NewReader 不同的是,这里的 Reader 支持 Seek。
NewWriter 创建一个有上限容量的写流:
slice := make([]byte, 1024)
w := bytes.NewWriter(slice)
...
writtenData := w.Bytes()
如果我们向 w 里面写入超过 1024 字节的数据,那么多余的数据会被丢弃。
NewBuffer 创建一个可随机读写的内存文件,支持 ReadAt/WriteAt 方法,而不是 Read/Write:
b := bytes.NewBuffer()
b.Truncate(100)
b.WriteAt([]byte("hello"), 100)
slice := make([]byte, 105)
n, err := b.ReadAt(slice, 0)
...
*/
package bytes

54
vendor/github.com/qiniu/x/bytes.v7/replace.go generated vendored Normal file
View File

@@ -0,0 +1,54 @@
package bytes
import (
"bytes"
)
// ---------------------------------------------------
func ReplaceAt(b []byte, off, nsrc int, dest []byte) []byte {
ndelta := len(dest) - nsrc
if ndelta < 0 {
left := b[off+nsrc:]
off += copy(b[off:], dest)
off += copy(b[off:], left)
return b[:off]
}
if ndelta > 0 {
b = append(b, dest[:ndelta]...)
copy(b[off+len(dest):], b[off+nsrc:])
copy(b[off:], dest)
} else {
copy(b[off:], dest)
}
return b
}
func ReplaceOne(b []byte, from int, src, dest []byte) ([]byte, int) {
pos := bytes.Index(b[from:], src)
if pos < 0 {
return b, -1
}
from += pos
return ReplaceAt(b, from, len(src), dest), from + len(dest)
}
func Replace(b []byte, src, dest []byte, n int) []byte {
from := 0
for n != 0 {
b, from = ReplaceOne(b, from, src, dest)
if from < 0 {
break
}
n--
}
return b
}
// ---------------------------------------------------

54
vendor/github.com/qiniu/x/bytes.v7/replace_test.go generated vendored Normal file
View File

@@ -0,0 +1,54 @@
package bytes
import (
"strings"
"testing"
)
type replaceCase struct {
s string
src string
dest string
n int
}
func stringReplace(b string, src, dest string, n int) string {
return string(Replace([]byte(b), []byte(src), []byte(dest), n))
}
func TestReplace(t *testing.T) {
cases := []replaceCase{
{"hello, world!", "world", "xsw", -1},
{"hello, world world world", "world", "xsw", 1},
{"hello, world world world", "world", "xsw", 2},
{"hello, world world world", "world", "xsw", -1},
{"hello, xsw!", "xsw", "world", -1},
{"hello, xsw xsw xsw", "xsw", "world", 1},
{"hello, xsw xsw xsw", "xsw", "world", 2},
{"hello, xsw xsw xsw", "xsw", "world", -1},
}
for _, c := range cases {
ret := stringReplace(c.s, c.src, c.dest, c.n)
expected := strings.Replace(c.s, c.src, c.dest, c.n)
if ret != expected {
t.Fatal("Replace failed:", c, "ret:", ret, "expected:", expected)
}
}
}
func stringInsertAt(b string, off int, text string) string {
return string(ReplaceAt([]byte(b), off, 0, []byte(text)))
}
func TestInsertAt(t *testing.T) {
ret := stringInsertAt("helloworld", 5, ", ")
if ret != "hello, world" {
t.Fatal("InsertAt failed:", ret)
}
}

View File

@@ -0,0 +1,63 @@
// This package provide a method to read and replace http.Request's body.
package seekable
import (
"errors"
"io"
"io/ioutil"
"net/http"
"qiniupkg.com/x/bytes.v7"
)
// ---------------------------------------------------
type Seekabler interface {
Bytes() []byte
Read(val []byte) (n int, err error)
SeekToBegin() error
}
type SeekableCloser interface {
Seekabler
io.Closer
}
// ---------------------------------------------------
type readCloser struct {
Seekabler
io.Closer
}
var ErrNoBody = errors.New("no body")
func New(req *http.Request) (r SeekableCloser, err error) {
if req.Body == nil {
return nil, ErrNoBody
}
var ok bool
if r, ok = req.Body.(SeekableCloser); ok {
return
}
b, err2 := ReadAll(req)
if err2 != nil {
return nil, err2
}
r = bytes.NewReader(b)
req.Body = readCloser{r, req.Body}
return
}
func ReadAll(req *http.Request) (b []byte, err error) {
if req.ContentLength > 0 {
b = make([]byte, int(req.ContentLength))
_, err = io.ReadFull(req.Body, b)
return
} else if req.ContentLength == 0 {
return nil, ErrNoBody
}
return ioutil.ReadAll(req.Body)
}
// ---------------------------------------------------

View File

@@ -0,0 +1,43 @@
package seekable
import (
"bytes"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSeekable_EOFIfReqAlreadyParsed(t *testing.T) {
body := "a=1"
req, err := http.NewRequest("POST", "/a", bytes.NewBufferString(body))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Content-Length", "3")
req.ParseForm()
_, err = New(req)
assert.Equal(t, err.Error(), "EOF")
}
func TestSeekable_WorkaroundForEOF(t *testing.T) {
body := "a=1"
req, err := http.NewRequest("POST", "/a", bytes.NewBufferString(body))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Content-Length", "3")
_, _ = New(req)
req.ParseForm()
assert.Equal(t, req.FormValue("a"), "1")
_, err = New(req)
assert.NoError(t, err)
}
func TestSeekable(t *testing.T) {
body := "a=1"
req, err := http.NewRequest("POST", "/a", bytes.NewBufferString(body))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Content-Length", "3")
_, err = New(req)
assert.NoError(t, err)
}

264
vendor/github.com/qiniu/x/cmdline.v7/cmdline.go generated vendored Normal file
View File

@@ -0,0 +1,264 @@
package cmdline
import (
"errors"
"strings"
. "qiniupkg.com/x/ctype.v7"
)
/* ---------------------------------------------------------------------------
Shell 基础规则:
* 多行字符串:用 '...' 或 "..."。其中 " 会自动转义 $(var),而 ' 不会。
* 普通字符串:用 [ \t] 分隔。转义符以 \ 开头。
* 外部命令:`...`。
七牛规则:
* 外部命令: `...` 或 |...| 。
* 多行字符串:用 '...' 或 ```\n...``` 或 ===\n...=== 不转义。用 "...",支持以 \ 开头的转义,也支持外部命令。
* 普通字符串:用 [ \t] 分隔。转义符以 \ 开头,同时也支持外部命令。
* 关于 $(var) 支持:每个命令自己执行 $(var) 的展开。不统一执行的原因是,在不同上下文需要不同的转义方式。
样例:
post http://rs.qiniu.com/delete/`base64 Bucket:Key`
auth `qbox AccessKey SecretKey`
ret 200
post http://rs.qiniu.com/batch
auth qboxtest
form op=/delete/`base64 Bucket:Key`&op=/delete/`base64 Bucket2:Key2`
ret 200
post http://rs.qiniu.com/batch
auth qboxtest
form op=/delete/`base64 Bucket:Key`&op=/delete/`base64 Bucket:NotExistKey`
ret 298
json '[
{"code": 200}, {"code": 612}
]'
equal $(code1) 200
// -------------------------------------------------------------------------*/
var (
EOF = errors.New("end of file")
ErrUnsupportedFeatureSubCmd = errors.New("unsupported feature: sub command")
ErrUnsupportedFeatureMultiCmds = errors.New("unsupported feature: multi commands")
ErrInvalidEscapeChar = errors.New("invalid escape char")
ErrIncompleteStringExpectQuot = errors.New("incomplete string, expect \"")
ErrIncompleteStringExpectSquot = errors.New("incomplete string, expect '")
ErrIncompleteStringExpectBacktick = errors.New("incomplete string, expect ` or |")
)
var (
errEOL = errors.New("end of line")
)
// ---------------------------------------------------------------------------
func Skip(str string, typeMask uint32) string {
for i := 0; i < len(str); i++ {
if !Is(typeMask, rune(str[i])) {
return str[i:]
}
}
return ""
}
func Find(str string, typeMask uint32) (n int) {
for n = 0; n < len(str); n++ {
if Is(typeMask, rune(str[n])) {
break
}
}
return
}
// ---------------------------------------------------------------------------
// EOL = \r\n? | \n
//
func requireEOL(code string) (hasEOL bool, codeNext string) {
if strings.HasPrefix(code, "\r") {
if strings.HasPrefix(code[1:], "\n") {
return true, code[2:]
}
} else if !strings.HasPrefix(code, "\n") {
return false, code
}
return true, code[1:]
}
// ---------------------------------------------------------------------------
type Parser struct {
ExecSub func(code string) (string, error)
Escape func(c byte) string
comment bool
}
func NewParser() *Parser {
return &Parser{
ExecSub: defaultExecSub,
Escape: defaultEscape,
}
}
func defaultExecSub(code string) (string, error) {
return "", ErrUnsupportedFeatureSubCmd
}
// ---------------------------------------------------------------------------
const (
endOfLine = EOL | SEMICOLON // [\r\n;]
blanks = SPACE_BAR | TAB
blankAndEOLs = SPACE_BAR | TAB | endOfLine
)
const (
endMask_QuotString = RDIV | BACKTICK | OR | QUOT // [\\`|"]
endMask_NonquotString = RDIV | BACKTICK | OR | blankAndEOLs // [\\`| \t\r\n;]
)
func (p *Parser) parseString(
code string, endMask uint32) (item string, ok bool, codeNext string, err error) {
codeNext = code
for {
n := Find(codeNext, endMask)
if n > 0 {
item += codeNext[:n]
ok = true
}
if len(codeNext) == n {
codeNext = ""
if endMask == endMask_QuotString {
err = ErrIncompleteStringExpectQuot
} else {
err = EOF
}
return
}
switch codeNext[n] {
case '\\':
if len(codeNext) == n+1 {
err = ErrInvalidEscapeChar
return
}
item += p.Escape(codeNext[n+1])
codeNext = codeNext[n+2:]
case '`', '|':
c := codeNext[n]
codeNext = codeNext[n+1:]
len := strings.IndexByte(codeNext, c)
if len < 0 {
err = ErrIncompleteStringExpectBacktick
return
}
if !p.comment {
valSub, errSub := p.ExecSub(codeNext[:len])
if errSub != nil {
err = errors.New("Exec `" + codeNext[:len] + "` failed: " + errSub.Error())
return
}
item += valSub
}
codeNext = codeNext[len+1:]
case '"':
ok = true
codeNext = codeNext[n+1:]
return
default:
if Is(endOfLine, rune(codeNext[n])) {
err = errEOL
}
codeNext = codeNext[n+1:]
return
}
ok = true
}
return
}
func (p *Parser) parseItem(
code string, skipMask uint32) (item string, ok bool, codeNext string, err error) {
codeNext = Skip(code, skipMask)
if len(codeNext) == 0 {
err = EOF
return
}
switch codeNext[0] {
case '"':
return p.parseString(codeNext[1:], endMask_QuotString)
case '\'':
codeNext = codeNext[1:]
len := strings.IndexByte(codeNext, '\'')
if len < 0 {
err = ErrIncompleteStringExpectSquot
return
}
return codeNext[:len], true, codeNext[len+1:], nil
default:
if strings.HasPrefix(codeNext, "```") || strings.HasPrefix(codeNext, "===") {
endMark := codeNext[:3]
_, codeNext = requireEOL(codeNext[3:])
len := strings.Index(codeNext, endMark)
if len < 0 {
err = errors.New("incomplete string, expect " + endMark)
return
}
return codeNext[:len], true, codeNext[len+3:], nil
}
return p.parseString(codeNext, endMask_NonquotString)
}
}
func (p *Parser) ParseCmd(cmdline string) (cmd []string, err error) {
cmd, _, err = p.ParseCode(cmdline)
if err == EOF && len(cmd) > 0 {
return cmd, nil
}
if err == nil {
err = ErrUnsupportedFeatureMultiCmds
}
return
}
func (p *Parser) ParseCode(code string) (cmd []string, codeNext string, err error) {
item, ok, codeNext, err := p.parseItem(code, blankAndEOLs)
if !ok {
return
}
p.comment = strings.HasPrefix(item, "#")
cmd = append(cmd, item)
for err == nil {
item, ok, codeNext, err = p.parseItem(codeNext, blanks)
if ok {
cmd = append(cmd, item)
}
}
if err == errEOL {
err = nil
}
if p.comment {
cmd = nil
}
return
}
// ---------------------------------------------------------------------------

173
vendor/github.com/qiniu/x/cmdline.v7/cmdline_test.go generated vendored Normal file
View File

@@ -0,0 +1,173 @@
package cmdline
import (
"reflect"
"testing"
)
// ---------------------------------------------------------------------------
func equalErr(err error, errExp interface{}) bool {
if err == nil || errExp == nil {
return err == nil && errExp == nil
}
return err.Error() == errExp.(string)
}
// ---------------------------------------------------------------------------
func TestComment(t *testing.T) {
execSub := false
ctx := Parser{
ExecSub: func(code string) (string, error) {
execSub = true
return "[" + code + "]", nil
},
Escape: func(c byte) string {
return string(c)
},
}
cmd, codeNext, err := ctx.ParseCode("#abc `calc $(a)+$(b)`")
if err != EOF || codeNext != "" {
t.Fatal("ParseCode: eof is expected")
}
if execSub {
t.Fatal("don't execSub")
}
if len(cmd) != 0 {
t.Fatal("len(cmd) != 0")
}
}
// ---------------------------------------------------------------------------
type caseParse struct {
code string
cmd []string
codeNext string
err interface{}
}
func TestParse(t *testing.T) {
cases := []caseParse{
{
code: ";b",
cmd: []string{"b"},
codeNext: "",
err: "end of file",
},
{
code: ";b;abc",
cmd: []string{"b"},
codeNext: "abc",
err: nil,
},
{
code: "a`b`\\c",
cmd: []string{"a[b]c"},
codeNext: "",
err: "end of file",
},
{
code: "a`b`c 'c\\n`123`' \"c\\n\"",
cmd: []string{"a[b]c", "c\\n`123`", "cn"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest 'mac AccessKey SecretKey'",
cmd: []string{"auth", "qboxtest", "mac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "post http://rs.qiniu.com/delete/`base64 Bucket:Key`",
cmd: []string{"post", "http://rs.qiniu.com/delete/[base64 Bucket:Key]"},
codeNext: "",
err: "end of file",
},
{
code: "post http://rs.qiniu.com/delete `base64 Bucket:Key`",
cmd: []string{"post", "http://rs.qiniu.com/delete", "[base64 Bucket:Key]"},
codeNext: "",
err: "end of file",
},
{
code: "post http://rs.qiniu.com/delete/|base64 Bucket:Key|",
cmd: []string{"post", "http://rs.qiniu.com/delete/[base64 Bucket:Key]"},
codeNext: "",
err: "end of file",
},
{
code: `json '[
{"code": 200}, {"code": 612}
]'`,
cmd: []string{"json", `[
{"code": 200}, {"code": 612}
]`},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ```\nmac AccessKey SecretKey```",
cmd: []string{"auth", "qboxtest", "mac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ===\nmac AccessKey SecretKey```",
cmd: []string{"auth", "qboxtest"},
codeNext: "mac AccessKey SecretKey```",
err: "incomplete string, expect ===",
},
{
code: "auth qboxtest ===\rmac AccessKey SecretKey===",
cmd: []string{"auth", "qboxtest", "mac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ===\n\rmac AccessKey SecretKey===",
cmd: []string{"auth", "qboxtest", "\rmac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ===\r\n\nmac AccessKey SecretKey===",
cmd: []string{"auth", "qboxtest", "\nmac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ===mac AccessKey SecretKey===",
cmd: []string{"auth", "qboxtest", "mac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
}
ctx := Parser{
ExecSub: func(code string) (string, error) {
return "[" + code + "]", nil
},
Escape: func(c byte) string {
return string(c)
},
}
for _, c := range cases {
cmd, codeNext, err := ctx.ParseCode(c.code)
if !equalErr(err, c.err) {
t.Fatal("Parse failed:", c, err)
}
if !reflect.DeepEqual(cmd, c.cmd) || codeNext != c.codeNext {
t.Fatal("Parse failed:", c, cmd, codeNext)
}
}
}
// ---------------------------------------------------------------------------

98
vendor/github.com/qiniu/x/cmdline.v7/escape.go generated vendored Normal file
View File

@@ -0,0 +1,98 @@
package cmdline
// ---------------------------------------------------------------------------
const (
escTableBaseChar = '0'
escTableLen = ('z' - escTableBaseChar + 1)
)
var escTable = []byte{
0, // 0 [48]
49, // 1 [49]
50, // 2 [50]
51, // 3 [51]
52, // 4 [52]
53, // 5 [53]
54, // 6 [54]
55, // 7 [55]
56, // 8 [56]
57, // 9 [57]
58, // : [58]
59, // ; [59]
60, // < [60]
61, // = [61]
62, // > [62]
63, // ? [63]
64, // @ [64]
65, // A [65]
66, // B [66]
67, // C [67]
68, // D [68]
69, // E [69]
70, // F [70]
71, // G [71]
72, // H [72]
73, // I [73]
74, // J [74]
75, // K [75]
76, // L [76]
77, // M [77]
78, // N [78]
79, // O [79]
80, // P [80]
81, // Q [81]
82, // R [82]
83, // S [83]
84, // T [84]
85, // U [85]
86, // V [86]
87, // W [87]
88, // X [88]
89, // Y [89]
90, // Z [90]
91, // [ [91]
92, // \ [92]
93, // ] [93]
94, // ^ [94]
95, // _ [95]
96, // ` [96]
97, // a [97]
98, // b [98]
99, // c [99]
100, // d [100]
101, // e [101]
102, // f [102]
103, // g [103]
104, // h [104]
105, // i [105]
106, // j [106]
107, // k [107]
108, // l [108]
109, // m [109]
'\n', // n [110]
111, // o [111]
112, // p [112]
113, // q [113]
'\r', // r [114]
115, // s [115]
'\t', // t [116]
117, // u [117]
118, // v [118]
119, // w [119]
120, // x [120]
121, // y [121]
122, // z [122]
123, // { [123]
}
func defaultEscape(c byte) string {
if c - escTableBaseChar < escTableLen {
c = escTable[c - escTableBaseChar]
}
return string(c)
}
// ---------------------------------------------------------------------------

41
vendor/github.com/qiniu/x/cmdline.v7/escape_test.go generated vendored Normal file
View File

@@ -0,0 +1,41 @@
package cmdline
import (
"testing"
)
// ---------------------------------------------------------------------------
func TestEscape(t *testing.T) {
for i := 0; i < escTableBaseChar; i++ {
checkEscapeChar(t, i, i)
}
table := make([]int, escTableLen)
for i := 0; i < escTableLen; i++ {
table[i] = escTableBaseChar + i
}
table['0'-escTableBaseChar] = 0
table['r'-escTableBaseChar] = '\r'
table['t'-escTableBaseChar] = '\t'
table['n'-escTableBaseChar] = '\n'
for i := 0; i < escTableLen; i++ {
checkEscapeChar(t, escTableBaseChar+i, table[i])
}
for i := int(escTableBaseChar + escTableLen); i < 256; i++ {
checkEscapeChar(t, i, i)
}
}
func checkEscapeChar(t *testing.T, i, exp int) {
ret := defaultEscape(byte(i))
if ret != string(exp) {
t.Fatal("escapeChar failed:", i)
}
}
// ---------------------------------------------------------------------------

41
vendor/github.com/qiniu/x/config.v7/getdir.go generated vendored Normal file
View File

@@ -0,0 +1,41 @@
package config
import (
"errors"
"os"
)
var homeEnvNames = [][]string{
{"HOME"},
{"HOMEDRIVE", "HOMEPATH"},
}
var (
ErrHomeNotFound = errors.New("$HOME not found")
)
func getEnv(name []string) (v string) {
if len(name) == 1 {
return os.Getenv(name[0])
}
for _, k := range name {
v += os.Getenv(k)
}
return
}
func GetDir(app string) (dir string, err error) {
for _, name := range homeEnvNames {
home := getEnv(name)
if home == "" {
continue
}
dir = home + "/." + app
err = os.MkdirAll(dir, 0777)
return
}
return "", ErrHomeNotFound
}

116
vendor/github.com/qiniu/x/config.v7/load_conf.go generated vendored Normal file
View File

@@ -0,0 +1,116 @@
package config
import (
"bytes"
"encoding/json"
"flag"
"io/ioutil"
"qiniupkg.com/x/log.v7"
)
var (
confName *string
)
func Init(cflag, app, default_conf string) {
confDir, _ := GetDir(app)
confName = flag.String(cflag, confDir+"/"+default_conf, "the config file")
}
func GetPath() string {
if confName != nil {
return *confName
}
return ""
}
func Load(conf interface{}) (err error) {
if !flag.Parsed() {
flag.Parse()
}
log.Info("Use the config file of ", *confName)
return LoadEx(conf, *confName)
}
func LoadEx(conf interface{}, confName string) (err error) {
data, err := ioutil.ReadFile(confName)
if err != nil {
log.Error("Load conf failed:", err)
return
}
data = trimComments(data)
err = json.Unmarshal(data, conf)
if err != nil {
log.Error("Parse conf failed:", err)
}
return
}
func LoadFile(conf interface{}, confName string) (err error) {
data, err := ioutil.ReadFile(confName)
if err != nil {
return
}
data = trimComments(data)
return json.Unmarshal(data, conf)
}
func LoadBytes(conf interface{}, data []byte) (err error) {
return json.Unmarshal(trimComments(data), conf)
}
func LoadString(conf interface{}, data string) (err error) {
return json.Unmarshal(trimComments([]byte(data)), conf)
}
func trimComments(data []byte) (data1 []byte) {
var line []byte
data1 = data[:0]
for {
pos := bytes.IndexByte(data, '\n')
if pos < 0 {
line = data
} else {
line = data[:pos+1]
}
data1 = append(data1, trimCommentsLine(line)...)
if pos < 0 {
return
}
data = data[pos+1:]
}
}
func trimCommentsLine(line []byte) []byte {
n := len(line)
quoteCount := 0
for i := 0; i < n; i++ {
c := line[i]
switch c {
case '\\':
i++
case '"':
quoteCount++
case '#':
if (quoteCount&1) == 0 {
return line[:i]
}
}
}
return line
}

59
vendor/github.com/qiniu/x/config.v7/load_conf_test.go generated vendored Normal file
View File

@@ -0,0 +1,59 @@
package config_test
import (
"bytes"
"encoding/json"
"testing"
"qiniupkg.com/x/config.v7"
)
func TestTrimComments(t *testing.T) {
confData := `{
"debug_level": 0, # 调试级别
"rs_host": "http://localhost:15001", #RS服务
"limit": 5, #限制数
"retryTimes": 56,
"quote0": "###",
"quote": "quo\\\"\\#",
"ant": "ant\\#" #123
}`
confDataExp := `{
"debug_level": 0,
"rs_host": "http://localhost:15001",
"limit": 5,
"retryTimes": 56,
"quote0": "###",
"quote": "quo\\\"\\#",
"ant": "ant\\#"
}`
var (
conf, confExp interface{}
)
err := config.LoadString(&conf, confData)
if err != nil {
t.Fatal("config.LoadString(conf) failed:", err)
}
err = config.LoadString(&confExp, confDataExp)
if err != nil {
t.Fatal("config.LoadString(confExp) failed:", err)
}
b, err := json.Marshal(conf)
if err != nil {
t.Fatal("json.Marshal failed:", err)
}
bExp, err := json.Marshal(confExp)
if err != nil {
t.Fatal("json.Marshal(exp) failed:", err)
}
if !bytes.Equal(b, bExp) {
t.Fatal("b != bExp")
}
}

237
vendor/github.com/qiniu/x/ctype.v7/ctype.go generated vendored Normal file
View File

@@ -0,0 +1,237 @@
package ctype
const (
UPPER = 0x01 /* upper case letter[A-Z] */
LOWER = 0x02 /* lower case letter[a-z] */
DIGIT = 0x04 /* digit[0-9] */
UNDERLINE = 0x08 /* underline[_] */
XDIGIT = 0x10 /* xdigit[0-9a-fA-F] */
EOL = 0x20 /* [\r\n] */
ADD = 0x40 /* [+] */
SUB = 0x80 /* [-] */
MUL = 0x100 /* [*] */
DIV = 0x200 /* [/] */
LT = 0x400 /* [<] */
GT = 0x800 /* [>] */
EQ = 0x1000 /* [=] */
RDIV = 0x2000 /* [\\], right-division, anti-slash */
DOT = 0x4000 /* [.] */
COLON = 0x8000 /* [:], colon */
PERCENT = 0x10000 /* [%] */
AND = 0x20000 /* [&] */
OR = 0x40000 /* [|] */
SPACE_BAR = 0x80000 /* [ ] */
LCAP_R = 0x100000 /* [r] */
LCAP_T = 0x200000 /* [t] */
LCAP_N = 0x400000 /* [n] */
LCAP_W = 0x800000 /* [w] */
COMMA = 0x1000000 /* [,] */
SEMICOLON = 0x2000000 /* [;] */
TAB = 0x4000000 /* [\t] */
QUOT = 0x8000000 /* ["] */
BACKTICK = 0x10000000 /* [`] */
)
const (
BLANK = SPACE_BAR
TSPACE = TAB | EOL
SPACE = SPACE_BAR | TSPACE
PATH_SEP = DIV | RDIV
ALPHA = UPPER | LOWER
SYMBOL_FIRST_CHAR = ALPHA
SYMBOL_NEXT_CHAR = SYMBOL_FIRST_CHAR | DIGIT
CSYMBOL_FIRST_CHAR = ALPHA | UNDERLINE
CSYMBOL_NEXT_CHAR = CSYMBOL_FIRST_CHAR | DIGIT
XMLSYMBOL_FIRST_CHAR = CSYMBOL_FIRST_CHAR
XMLSYMBOL_NEXT_CHAR = CSYMBOL_NEXT_CHAR | SUB
DOMAIN_CHAR = ALPHA | DIGIT | SUB | ADD | DOT
BASE64 = ALPHA | DIGIT | ADD | DIV // [a-zA-Z0-9+/]
URLSAFE_BASE64 = ALPHA | DIGIT | SUB | UNDERLINE // [a-zA-Z0-9\-_]
)
// -----------------------------------------------------------
var table = []uint32{
0, // [0]
0, // [1]
0, // [2]
0, // [3]
0, // [4]
0, // [5]
0, // [6]
0, // [7]
0, // [8]
TAB, // [9]
EOL, // [10]
0, // [11]
0, // [12]
EOL, // [13]
0, // [14]
0, // [15]
0, // [16]
0, // [17]
0, // [18]
0, // [19]
0, // [20]
0, // [21]
0, // [22]
0, // [23]
0, // [24]
0, // [25]
0, // [26]
0, // [27]
0, // [28]
0, // [29]
0, // [30]
0, // [31]
SPACE_BAR, // [32]
0, // ! [33]
QUOT, // " [34]
0, // # [35]
0, // $ [36]
PERCENT, // % [37]
AND, // & [38]
0, // ' [39]
0, // ( [40]
0, // ) [41]
MUL, // * [42]
ADD, // + [43]
COMMA, // , [44]
SUB, // - [45]
DOT, // . [46]
DIV, // / [47]
DIGIT | XDIGIT, // 0 [48]
DIGIT | XDIGIT, // 1 [49]
DIGIT | XDIGIT, // 2 [50]
DIGIT | XDIGIT, // 3 [51]
DIGIT | XDIGIT, // 4 [52]
DIGIT | XDIGIT, // 5 [53]
DIGIT | XDIGIT, // 6 [54]
DIGIT | XDIGIT, // 7 [55]
DIGIT | XDIGIT, // 8 [56]
DIGIT | XDIGIT, // 9 [57]
COLON, // : [58]
SEMICOLON, // ; [59]
LT, // < [60]
EQ, // = [61]
GT, // > [62]
0, // ? [63]
0, // @ [64]
UPPER | XDIGIT, // A [65]
UPPER | XDIGIT, // B [66]
UPPER | XDIGIT, // C [67]
UPPER | XDIGIT, // D [68]
UPPER | XDIGIT, // E [69]
UPPER | XDIGIT, // F [70]
UPPER, // G [71]
UPPER, // H [72]
UPPER, // I [73]
UPPER, // J [74]
UPPER, // K [75]
UPPER, // L [76]
UPPER, // M [77]
UPPER, // N [78]
UPPER, // O [79]
UPPER, // P [80]
UPPER, // Q [81]
UPPER, // R [82]
UPPER, // S [83]
UPPER, // T [84]
UPPER, // U [85]
UPPER, // V [86]
UPPER, // W [87]
UPPER, // X [88]
UPPER, // Y [89]
UPPER, // Z [90]
0, // [ [91]
RDIV, // \ [92]
0, // ] [93]
0, // ^ [94]
UNDERLINE, // _ [95]
BACKTICK, // ` [96]
LOWER | XDIGIT, // a [97]
LOWER | XDIGIT, // b [98]
LOWER | XDIGIT, // c [99]
LOWER | XDIGIT, // d [100]
LOWER | XDIGIT, // e [101]
LOWER | XDIGIT, // f [102]
LOWER, // g [103]
LOWER, // h [104]
LOWER, // i [105]
LOWER, // j [106]
LOWER, // k [107]
LOWER, // l [108]
LOWER, // m [109]
LCAP_N | LOWER, // n [110]
LOWER, // o [111]
LOWER, // p [112]
LOWER, // q [113]
LCAP_R | LOWER, // r [114]
LOWER, // s [115]
LCAP_T | LOWER, // t [116]
LOWER, // u [117]
LOWER, // v [118]
LCAP_W | LOWER, // w [119]
LOWER, // x [120]
LOWER, // y [121]
LOWER, // z [122]
0, // { [123]
OR, // | [124]
0, // } [125]
0, // ~ [126]
0, // del [127]
}
// -----------------------------------------------------------
func Is(typeMask uint32, c rune) bool {
if uint(c) < uint(len(table)) {
return (typeMask & table[c]) != 0
}
return false
}
func IsType(typeMask uint32, str string) bool {
if str == "" {
return false
}
for _, c := range str {
if !Is(typeMask, c) {
return false
}
}
return true
}
func IsTypeEx(typeFirst, typeNext uint32, str string) bool {
if str == "" {
return false
}
for i, c := range str {
if i > 0 {
if !Is(typeNext, c) {
return false
}
} else {
if !Is(typeFirst, c) {
return false
}
}
}
return true
}
func IsCSymbol(str string) bool {
return IsTypeEx(CSYMBOL_FIRST_CHAR, CSYMBOL_NEXT_CHAR, str)
}
func IsXmlSymbol(str string) bool {
return IsTypeEx(XMLSYMBOL_FIRST_CHAR, XMLSYMBOL_NEXT_CHAR, str)
}
// -----------------------------------------------------------

72
vendor/github.com/qiniu/x/ctype.v7/ctype_test.go generated vendored Normal file
View File

@@ -0,0 +1,72 @@
package ctype
import (
"testing"
)
type testCase struct {
c rune
mask uint32
is bool
}
type stringTestCase struct {
str string
maskFirst uint32
maskNext uint32
is bool
}
var isCases = []testCase{
{'-', DOMAIN_CHAR, true},
{'.', DOMAIN_CHAR, true},
{'_', DOMAIN_CHAR, false},
{'+', DOMAIN_CHAR, true},
{'a', DOMAIN_CHAR, true},
{'A', DOMAIN_CHAR, true},
{'0', DOMAIN_CHAR, true},
{':', DOMAIN_CHAR, false},
{'1', ALPHA, false},
{'a', ALPHA, true},
{'A', ALPHA, true},
}
var strCases = []stringTestCase{
{"", CSYMBOL_FIRST_CHAR, CSYMBOL_NEXT_CHAR, false},
{"123", CSYMBOL_FIRST_CHAR, CSYMBOL_NEXT_CHAR, false},
{"_", CSYMBOL_FIRST_CHAR, CSYMBOL_NEXT_CHAR, true},
{"_123", CSYMBOL_FIRST_CHAR, CSYMBOL_NEXT_CHAR, true},
{"x_123", CSYMBOL_FIRST_CHAR, CSYMBOL_NEXT_CHAR, true},
{"x_", CSYMBOL_FIRST_CHAR, CSYMBOL_NEXT_CHAR, true},
{"_x", CSYMBOL_FIRST_CHAR, CSYMBOL_NEXT_CHAR, true},
{"", CSYMBOL_FIRST_CHAR, CSYMBOL_FIRST_CHAR, false},
{"x_123", CSYMBOL_FIRST_CHAR, CSYMBOL_FIRST_CHAR, false},
{"x_", CSYMBOL_FIRST_CHAR, CSYMBOL_FIRST_CHAR, true},
{"_x", CSYMBOL_FIRST_CHAR, CSYMBOL_FIRST_CHAR, true},
{"_", CSYMBOL_FIRST_CHAR, CSYMBOL_FIRST_CHAR, true},
}
func TestIs(t *testing.T) {
for _, a := range isCases {
f := Is(a.mask, a.c)
if f != a.is {
t.Fatal("case:", a, "result:", f)
}
}
}
func TestIsTypeEx(t *testing.T) {
for _, a := range strCases {
f := IsTypeEx(a.maskFirst, a.maskNext, a.str)
if f != a.is {
t.Fatal("case:", a, "result:", f)
}
if a.maskFirst == a.maskNext {
f = IsType(a.maskFirst, a.str)
if f != a.is {
t.Fatal("case:", a, "result:", f)
}
}
}
}

9
vendor/github.com/qiniu/x/doc.go generated vendored Normal file
View File

@@ -0,0 +1,9 @@
package x
import (
_ "qiniupkg.com/x/bytes.v7"
_ "qiniupkg.com/x/ctype.v7"
_ "qiniupkg.com/x/rpc.v7"
_ "qiniupkg.com/x/url.v7"
)

146
vendor/github.com/qiniu/x/errors.v7/error_info.go generated vendored Normal file
View File

@@ -0,0 +1,146 @@
package errors
import (
"errors"
"fmt"
"runtime"
"strconv"
"strings"
)
const (
prefix = " ==> "
)
// --------------------------------------------------------------------
func New(msg string) error {
return errors.New(msg)
}
// --------------------------------------------------------------------
type appendDetailer interface {
AppendErrorDetail(b []byte) []byte
}
func appendErrorDetail(b []byte, err error) []byte {
if e, ok := err.(appendDetailer); ok {
return e.AppendErrorDetail(b)
}
b = append(b, prefix...)
return append(b, err.Error()...)
}
// --------------------------------------------------------------------
type errorDetailer interface {
ErrorDetail() string
}
func Detail(err error) string {
if e, ok := err.(errorDetailer); ok {
return e.ErrorDetail()
}
return err.Error()
}
// --------------------------------------------------------------------
type summaryErr interface {
SummaryErr() error
}
func Err(err error) error {
if e, ok := err.(summaryErr); ok {
return e.SummaryErr()
}
return err
}
// --------------------------------------------------------------------
type ErrorInfo struct {
err error
why error
cmd []interface{}
pc uintptr
}
func shortFile(file string) string {
pos := strings.LastIndex(file, "/src/")
if pos != -1 {
return file[pos+5:]
}
return file
}
func Info(err error, cmd ...interface{}) *ErrorInfo {
pc, _, _, ok := runtime.Caller(1)
if !ok {
pc = 0
}
return &ErrorInfo{cmd: cmd, err: Err(err), pc: pc}
}
func InfoEx(calldepth int, err error, cmd ...interface{}) *ErrorInfo {
pc, _, _, ok := runtime.Caller(calldepth+1)
if !ok {
pc = 0
}
return &ErrorInfo{cmd: cmd, err: Err(err), pc: pc}
}
func (r *ErrorInfo) Detail(err error) *ErrorInfo {
r.why = err
return r
}
func (r *ErrorInfo) NestedObject() interface{} {
return r.err
}
func (r *ErrorInfo) SummaryErr() error {
return r.err
}
func (r *ErrorInfo) Error() string {
return r.err.Error()
}
func (r *ErrorInfo) ErrorDetail() string {
b := make([]byte, 1, 64)
b[0] = '\n'
b = r.AppendErrorDetail(b)
return string(b)
}
func (r *ErrorInfo) AppendErrorDetail(b []byte) []byte {
b = append(b, prefix...)
if r.pc != 0 {
f := runtime.FuncForPC(r.pc)
if f != nil {
file, line := f.FileLine(r.pc)
b = append(b, shortFile(file)...)
b = append(b, ':')
b = append(b, strconv.Itoa(line)...)
b = append(b, ':', ' ')
fnName := f.Name()
fnName = fnName[strings.LastIndex(fnName, "/")+1:]
fnName = fnName[strings.Index(fnName, ".")+1:]
b = append(b, '[')
b = append(b, fnName...)
b = append(b, ']', ' ')
}
}
b = append(b, Detail(r.err)...)
b = append(b, ' ', '~', ' ')
b = append(b, fmt.Sprintln(r.cmd...)...)
if r.why != nil {
b = appendErrorDetail(b, r.why)
}
return b
}
// --------------------------------------------------------------------

30
vendor/github.com/qiniu/x/errors.v7/error_info_test.go generated vendored Normal file
View File

@@ -0,0 +1,30 @@
package errors
import (
"errors"
"syscall"
"testing"
)
func MysqlError(err error, cmd ...interface{}) error {
return InfoEx(1, syscall.EINVAL, cmd...).Detail(err)
}
func (r *ErrorInfo) makeError() error {
err := errors.New("detail error")
return MysqlError(err, "do sth failed")
}
func TestErrorsInfo(t *testing.T) {
err := new(ErrorInfo).makeError()
msg := Detail(err)
if msg != `
==> qiniupkg.com/x/errors.v7/error_info_test.go:17: [(*ErrorInfo).makeError] invalid argument ~ do sth failed
==> detail error` {
t.Fatal("TestErrorsInfo failed")
}
}

View File

@@ -0,0 +1,19 @@
package jsonutil
import (
"encoding/json"
"reflect"
"unsafe"
)
// ----------------------------------------------------------
func Unmarshal(data string, v interface{}) error {
sh := *(*reflect.StringHeader)(unsafe.Pointer(&data))
arr := (*[1<<30]byte)(unsafe.Pointer(sh.Data))
return json.Unmarshal(arr[:sh.Len], v)
}
// ----------------------------------------------------------

View File

@@ -0,0 +1,19 @@
package jsonutil
import (
"testing"
)
func Test(t *testing.T) {
var ret struct {
Id string `json:"id"`
}
err := Unmarshal(`{"id": "123"}`, &ret)
if err != nil {
t.Fatal("Unmarshal failed:", err)
}
if ret.Id != "123" {
t.Fatal("Unmarshal uncorrect:", ret.Id)
}
}

4
vendor/github.com/qiniu/x/log.v7/README.md generated vendored Normal file
View File

@@ -0,0 +1,4 @@
log
===
Extension module of golang logging

521
vendor/github.com/qiniu/x/log.v7/logext.go generated vendored Normal file
View File

@@ -0,0 +1,521 @@
package log
import (
"bytes"
"fmt"
"io"
"os"
"runtime"
"strings"
"sync"
"time"
)
// These flags define which text to prefix to each log entry generated by the Logger.
const (
// Bits or'ed together to control what's printed. There is no control over the
// order they appear (the order listed here) or the format they present (as
// described in the comments). A colon appears after these items:
// 2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
Ldate = 1 << iota // the date: 2009/0123
Ltime // the time: 01:23:23
Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
Llongfile // full file name and line number: /a/b/c/d.go:23
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
Lmodule // module name
Llevel // level: 0(Debug), 1(Info), 2(Warn), 3(Error), 4(Panic), 5(Fatal)
LstdFlags = Ldate | Ltime | Lmicroseconds // initial values for the standard logger
Ldefault = Lmodule | Llevel | Lshortfile | LstdFlags
) // [prefix][time][level][module][shortfile|longfile]
const (
Ldebug = iota
Linfo
Lwarn
Lerror
Lpanic
Lfatal
)
var levels = []string{
"[DEBUG]",
"[INFO]",
"[WARN]",
"[ERROR]",
"[PANIC]",
"[FATAL]",
}
// A Logger represents an active logging object that generates lines of
// output to an io.Writer. Each logging operation makes a single call to
// the Writer's Write method. A Logger can be used simultaneously from
// multiple goroutines; it guarantees to serialize access to the Writer.
type Logger struct {
mu sync.Mutex // ensures atomic writes; protects the following fields
prefix string // prefix to write at beginning of each line
flag int // properties
Level int // debug level
out io.Writer // destination for output
buf bytes.Buffer // for accumulating text to write
levelStats [6]int64
}
// New creates a new Logger.
// The out variable sets the destination to which log data will be written.
// The prefix appears at the beginning of each generated log line.
// The flag argument defines the logging properties.
func New(out io.Writer, prefix string, flag int) *Logger {
return &Logger{out: out, prefix: prefix, Level: 1, flag: flag}
}
var Std = New(os.Stderr, "", Ldefault)
// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
// Knows the buffer has capacity.
func itoa(buf *bytes.Buffer, i int, wid int) {
var u uint = uint(i)
if u == 0 && wid <= 1 {
buf.WriteByte('0')
return
}
// Assemble decimal in reverse order.
var b [32]byte
bp := len(b)
for ; u > 0 || wid > 0; u /= 10 {
bp--
wid--
b[bp] = byte(u%10) + '0'
}
// avoid slicing b to avoid an allocation.
for bp < len(b) {
buf.WriteByte(b[bp])
bp++
}
}
func shortFile(file string, flag int) string {
sep := "/"
if (flag & Lmodule) != 0 {
sep = "/src/"
}
pos := strings.LastIndex(file, sep)
if pos != -1 {
return file[pos+5:]
}
return file
}
func (l *Logger) formatHeader(buf *bytes.Buffer, t time.Time, file string, line int, lvl int, reqId string) {
if l.prefix != "" {
buf.WriteString(l.prefix)
}
if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
if l.flag&Ldate != 0 {
year, month, day := t.Date()
itoa(buf, year, 4)
buf.WriteByte('/')
itoa(buf, int(month), 2)
buf.WriteByte('/')
itoa(buf, day, 2)
buf.WriteByte(' ')
}
if l.flag&(Ltime|Lmicroseconds) != 0 {
hour, min, sec := t.Clock()
itoa(buf, hour, 2)
buf.WriteByte(':')
itoa(buf, min, 2)
buf.WriteByte(':')
itoa(buf, sec, 2)
if l.flag&Lmicroseconds != 0 {
buf.WriteByte('.')
itoa(buf, t.Nanosecond()/1e3, 6)
}
buf.WriteByte(' ')
}
}
if reqId != "" {
buf.WriteByte('[')
buf.WriteString(reqId)
buf.WriteByte(']')
}
if l.flag&Llevel != 0 {
buf.WriteString(levels[lvl])
}
if l.flag&(Lshortfile|Llongfile) != 0 {
if l.flag&Lshortfile != 0 {
file = shortFile(file, l.flag)
}
buf.WriteByte(' ')
buf.WriteString(file)
buf.WriteByte(':')
itoa(buf, line, -1)
buf.WriteString(": ")
}
}
// Output writes the output for a logging event. The string s contains
// the text to print after the prefix specified by the flags of the
// Logger. A newline is appended if the last character of s is not
// already a newline. Calldepth is used to recover the PC and is
// provided for generality, although at the moment on all pre-defined
// paths it will be 2.
func (l *Logger) Output(reqId string, lvl int, calldepth int, s string) error {
if lvl < l.Level {
return nil
}
now := time.Now() // get this early.
var file string
var line int
l.mu.Lock()
defer l.mu.Unlock()
if l.flag&(Lshortfile|Llongfile|Lmodule) != 0 {
// release lock while getting caller info - it's expensive.
l.mu.Unlock()
var ok bool
_, file, line, ok = runtime.Caller(calldepth)
if !ok {
file = "???"
line = 0
}
l.mu.Lock()
}
l.levelStats[lvl]++
l.buf.Reset()
l.formatHeader(&l.buf, now, file, line, lvl, reqId)
l.buf.WriteString(s)
if len(s) > 0 && s[len(s)-1] != '\n' {
l.buf.WriteByte('\n')
}
_, err := l.out.Write(l.buf.Bytes())
return err
}
// -----------------------------------------
// Printf calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Printf(format string, v ...interface{}) {
l.Output("", Linfo, 2, fmt.Sprintf(format, v...))
}
// Print calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Print(v ...interface{}) { l.Output("", Linfo, 2, fmt.Sprint(v...)) }
// Println calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Println.
func (l *Logger) Println(v ...interface{}) { l.Output("", Linfo, 2, fmt.Sprintln(v...)) }
// -----------------------------------------
func (l *Logger) Debugf(format string, v ...interface{}) {
if Ldebug < l.Level {
return
}
l.Output("", Ldebug, 2, fmt.Sprintf(format, v...))
}
func (l *Logger) Debug(v ...interface{}) {
if Ldebug < l.Level {
return
}
l.Output("", Ldebug, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
func (l *Logger) Infof(format string, v ...interface{}) {
if Linfo < l.Level {
return
}
l.Output("", Linfo, 2, fmt.Sprintf(format, v...))
}
func (l *Logger) Info(v ...interface{}) {
if Linfo < l.Level {
return
}
l.Output("", Linfo, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
func (l *Logger) Warnf(format string, v ...interface{}) {
l.Output("", Lwarn, 2, fmt.Sprintf(format, v...))
}
func (l *Logger) Warn(v ...interface{}) { l.Output("", Lwarn, 2, fmt.Sprintln(v...)) }
// -----------------------------------------
func (l *Logger) Errorf(format string, v ...interface{}) {
l.Output("", Lerror, 2, fmt.Sprintf(format, v...))
}
func (l *Logger) Error(v ...interface{}) { l.Output("", Lerror, 2, fmt.Sprintln(v...)) }
// -----------------------------------------
func (l *Logger) Fatal(v ...interface{}) {
l.Output("", Lfatal, 2, fmt.Sprint(v...))
os.Exit(1)
}
// Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
func (l *Logger) Fatalf(format string, v ...interface{}) {
l.Output("", Lfatal, 2, fmt.Sprintf(format, v...))
os.Exit(1)
}
// Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).
func (l *Logger) Fatalln(v ...interface{}) {
l.Output("", Lfatal, 2, fmt.Sprintln(v...))
os.Exit(1)
}
// -----------------------------------------
// Panic is equivalent to l.Print() followed by a call to panic().
func (l *Logger) Panic(v ...interface{}) {
s := fmt.Sprint(v...)
l.Output("", Lpanic, 2, s)
panic(s)
}
// Panicf is equivalent to l.Printf() followed by a call to panic().
func (l *Logger) Panicf(format string, v ...interface{}) {
s := fmt.Sprintf(format, v...)
l.Output("", Lpanic, 2, s)
panic(s)
}
// Panicln is equivalent to l.Println() followed by a call to panic().
func (l *Logger) Panicln(v ...interface{}) {
s := fmt.Sprintln(v...)
l.Output("", Lpanic, 2, s)
panic(s)
}
// -----------------------------------------
func (l *Logger) Stack(v ...interface{}) {
s := fmt.Sprint(v...)
s += "\n"
buf := make([]byte, 1024*1024)
n := runtime.Stack(buf, true)
s += string(buf[:n])
s += "\n"
l.Output("", Lerror, 2, s)
}
func (l *Logger) SingleStack(v ...interface{}) {
s := fmt.Sprint(v...)
s += "\n"
buf := make([]byte, 1024*1024)
n := runtime.Stack(buf, false)
s += string(buf[:n])
s += "\n"
l.Output("", Lerror, 2, s)
}
// -----------------------------------------
func (l *Logger) Stat() (stats []int64) {
l.mu.Lock()
v := l.levelStats
l.mu.Unlock()
return v[:]
}
// Flags returns the output flags for the logger.
func (l *Logger) Flags() int {
l.mu.Lock()
defer l.mu.Unlock()
return l.flag
}
// SetFlags sets the output flags for the logger.
func (l *Logger) SetFlags(flag int) {
l.mu.Lock()
defer l.mu.Unlock()
l.flag = flag
}
// Prefix returns the output prefix for the logger.
func (l *Logger) Prefix() string {
l.mu.Lock()
defer l.mu.Unlock()
return l.prefix
}
// SetPrefix sets the output prefix for the logger.
func (l *Logger) SetPrefix(prefix string) {
l.mu.Lock()
defer l.mu.Unlock()
l.prefix = prefix
}
// SetOutputLevel sets the output level for the logger.
func (l *Logger) SetOutputLevel(lvl int) {
l.mu.Lock()
defer l.mu.Unlock()
l.Level = lvl
}
// SetOutput sets the output destination for the standard logger.
func SetOutput(w io.Writer) {
Std.mu.Lock()
defer Std.mu.Unlock()
Std.out = w
}
// Flags returns the output flags for the standard logger.
func Flags() int {
return Std.Flags()
}
// SetFlags sets the output flags for the standard logger.
func SetFlags(flag int) {
Std.SetFlags(flag)
}
// Prefix returns the output prefix for the standard logger.
func Prefix() string {
return Std.Prefix()
}
// SetPrefix sets the output prefix for the standard logger.
func SetPrefix(prefix string) {
Std.SetPrefix(prefix)
}
func SetOutputLevel(lvl int) {
Std.SetOutputLevel(lvl)
}
func GetOutputLevel() int {
return Std.Level
}
// -----------------------------------------
// Print calls Output to print to the standard logger.
// Arguments are handled in the manner of fmt.Print.
func Print(v ...interface{}) {
Std.Output("", Linfo, 2, fmt.Sprint(v...))
}
// Printf calls Output to print to the standard logger.
// Arguments are handled in the manner of fmt.Printf.
func Printf(format string, v ...interface{}) {
Std.Output("", Linfo, 2, fmt.Sprintf(format, v...))
}
// Println calls Output to print to the standard logger.
// Arguments are handled in the manner of fmt.Println.
func Println(v ...interface{}) {
Std.Output("", Linfo, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
func Debugf(format string, v ...interface{}) {
if Ldebug < Std.Level {
return
}
Std.Output("", Ldebug, 2, fmt.Sprintf(format, v...))
}
func Debug(v ...interface{}) {
if Ldebug < Std.Level {
return
}
Std.Output("", Ldebug, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
func Infof(format string, v ...interface{}) {
if Linfo < Std.Level {
return
}
Std.Output("", Linfo, 2, fmt.Sprintf(format, v...))
}
func Info(v ...interface{}) {
if Linfo < Std.Level {
return
}
Std.Output("", Linfo, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
func Warnf(format string, v ...interface{}) {
Std.Output("", Lwarn, 2, fmt.Sprintf(format, v...))
}
func Warn(v ...interface{}) { Std.Output("", Lwarn, 2, fmt.Sprintln(v...)) }
// -----------------------------------------
func Errorf(format string, v ...interface{}) {
Std.Output("", Lerror, 2, fmt.Sprintf(format, v...))
}
func Error(v ...interface{}) { Std.Output("", Lerror, 2, fmt.Sprintln(v...)) }
// -----------------------------------------
// Fatal is equivalent to Print() followed by a call to os.Exit(1).
func Fatal(v ...interface{}) {
Std.Output("", Lfatal, 2, fmt.Sprint(v...))
os.Exit(1)
}
// Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
func Fatalf(format string, v ...interface{}) {
Std.Output("", Lfatal, 2, fmt.Sprintf(format, v...))
os.Exit(1)
}
// Fatalln is equivalent to Println() followed by a call to os.Exit(1).
func Fatalln(v ...interface{}) {
Std.Output("", Lfatal, 2, fmt.Sprintln(v...))
os.Exit(1)
}
// -----------------------------------------
// Panic is equivalent to Print() followed by a call to panic().
func Panic(v ...interface{}) {
s := fmt.Sprint(v...)
Std.Output("", Lpanic, 2, s)
panic(s)
}
// Panicf is equivalent to Printf() followed by a call to panic().
func Panicf(format string, v ...interface{}) {
s := fmt.Sprintf(format, v...)
Std.Output("", Lpanic, 2, s)
panic(s)
}
// Panicln is equivalent to Println() followed by a call to panic().
func Panicln(v ...interface{}) {
s := fmt.Sprintln(v...)
Std.Output("", Lpanic, 2, s)
panic(s)
}
// -----------------------------------------
func Stack(v ...interface{}) {
Std.Stack(v...)
}
func SingleStack(v ...interface{}) {
Std.SingleStack(v...)
}

79
vendor/github.com/qiniu/x/log.v7/logext_test.go generated vendored Normal file
View File

@@ -0,0 +1,79 @@
package log
import (
"bytes"
"regexp"
"testing"
"github.com/stretchr/testify/assert"
)
func TestLog(t *testing.T) {
// keep Std clean
std := Std
SetOutputLevel(Ldebug)
Debugf("Debug: foo\n")
Debug("Debug: foo")
Infof("Info: foo\n")
Info("Info: foo")
Warnf("Warn: foo\n")
Warn("Warn: foo")
Errorf("Error: foo\n")
Error("Error: foo")
SetOutputLevel(Linfo)
Debugf("Debug: foo\n")
Debug("Debug: foo")
Infof("Info: foo\n")
Info("Info: foo")
Warnf("Warn: foo\n")
Warn("Warn: foo")
Errorf("Error: foo\n")
Error("Error: foo")
Std = std
}
func TestLog_Time(t *testing.T) {
// keep Std clean
std := Std
out := bytes.Buffer{}
Std = New(&out, Std.Prefix(), Std.Flags())
assert.Equal(t, Std.Level, Linfo)
Info("test")
outStr := out.String()
assert.True(t, regexp.MustCompile(`^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}.\d{6}$`).MatchString(outStr[:26]))
assert.Equal(t, outStr[26:], " [INFO] qiniupkg.com/x/log.v7/logext_test.go:53: test\n")
Std = std
}
func TestLog_Level(t *testing.T) {
// keep Std clean
std := Std
out := bytes.Buffer{}
Std = New(&out, Std.Prefix(), Std.Flags())
SetOutputLevel(Lwarn)
assert.Equal(t, Std.Level, Lwarn)
Debug("test")
assert.Equal(t, out.String(), "")
Info("test")
assert.Equal(t, out.String(), "")
Warn("test")
outStr := out.String()
assert.Equal(t, outStr[26:], " [WARN] qiniupkg.com/x/log.v7/logext_test.go:74: test\n")
Std = std
}

110
vendor/github.com/qiniu/x/mockhttp.v7/mockhttp.go generated vendored Normal file
View File

@@ -0,0 +1,110 @@
package mockhttp
import (
"errors"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"strconv"
"qiniupkg.com/x/log.v7"
)
var (
ErrServerNotFound = errors.New("server not found")
)
// --------------------------------------------------------------------
type mockServerRequestBody struct {
reader io.Reader
closeSignal bool
}
func (r *mockServerRequestBody) Read(p []byte) (int, error) {
if r.closeSignal || r.reader == nil {
return 0, io.EOF
}
return r.reader.Read(p)
}
func (r *mockServerRequestBody) Close() error {
r.closeSignal = true
if c, ok := r.reader.(io.Closer); ok {
return c.Close()
}
return nil
}
// --------------------------------------------------------------------
// type Transport
type Transport struct {
route map[string]http.Handler
}
func NewTransport() *Transport {
return &Transport{
route: make(map[string]http.Handler),
}
}
func (p *Transport) ListenAndServe(host string, h http.Handler) {
if h == nil {
h = http.DefaultServeMux
}
p.route[host] = h
}
func (p *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
h := p.route[req.URL.Host]
if h == nil {
log.Warn("Server not found:", req.Host)
return nil, ErrServerNotFound
}
cp := *req
cp.URL.Scheme = ""
cp.URL.Host = ""
cp.RemoteAddr = "127.0.0.1:8000"
cp.Body = &mockServerRequestBody{req.Body, false}
req = &cp
rw := httptest.NewRecorder()
h.ServeHTTP(rw, req)
req.Body.Close()
ctlen := int64(-1)
if v := rw.HeaderMap.Get("Content-Length"); v != "" {
ctlen, _ = strconv.ParseInt(v, 10, 64)
}
return &http.Response{
Status: "",
StatusCode: rw.Code,
Header: rw.HeaderMap,
Body: ioutil.NopCloser(rw.Body),
ContentLength: ctlen,
TransferEncoding: nil,
Close: false,
Trailer: nil,
Request: req,
}, nil
}
// --------------------------------------------------------------------
var DefaultTransport = NewTransport()
var DefaultClient = &http.Client{Transport: DefaultTransport}
func ListenAndServe(host string, h http.Handler) {
DefaultTransport.ListenAndServe(host, h)
}
// --------------------------------------------------------------------

114
vendor/github.com/qiniu/x/mockhttp.v7/mockhttp_test.go generated vendored Normal file
View File

@@ -0,0 +1,114 @@
package mockhttp_test
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strconv"
"strings"
"testing"
"qiniupkg.com/x/mockhttp.v7"
"qiniupkg.com/x/rpc.v7"
)
// --------------------------------------------------------------------
func reply(w http.ResponseWriter, code int, data interface{}) {
msg, _ := json.Marshal(data)
h := w.Header()
h.Set("Content-Length", strconv.Itoa(len(msg)))
h.Set("Content-Type", "application/json")
w.WriteHeader(code)
w.Write(msg)
}
// --------------------------------------------------------------------
type FooRet struct {
A int `json:"a"`
B string `json:"b"`
C string `json:"c"`
}
type HandleRet map[string]string
type FooServer struct{}
func (p *FooServer) foo(w http.ResponseWriter, req *http.Request) {
reply(w, 200, &FooRet{1, req.Host, req.URL.Path})
}
func (p *FooServer) handle(w http.ResponseWriter, req *http.Request) {
reply(w, 200, HandleRet{"foo": "1", "bar": "2"})
}
func (p *FooServer) postDump(w http.ResponseWriter, req *http.Request) {
req.Body.Close()
io.Copy(w, req.Body)
}
func (p *FooServer) RegisterHandlers(mux *http.ServeMux) {
mux.HandleFunc("/foo", func(w http.ResponseWriter, req *http.Request) { p.foo(w, req) })
mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { p.handle(w, req) })
mux.HandleFunc("/dump", func(w http.ResponseWriter, req *http.Request) { p.postDump(w, req) })
}
// --------------------------------------------------------------------
func TestBasic(t *testing.T) {
server := new(FooServer)
server.RegisterHandlers(http.DefaultServeMux)
mockhttp.ListenAndServe("foo.com", nil)
c := rpc.Client{mockhttp.DefaultClient}
{
var foo FooRet
err := c.Call(nil, &foo, "POST", "http://foo.com/foo")
if err != nil {
t.Fatal("call foo failed:", err)
}
if foo.A != 1 || foo.B != "foo.com" || foo.C != "/foo" {
t.Fatal("call foo: invalid ret")
}
fmt.Println(foo)
}
{
var ret map[string]string
err := c.Call(nil, &ret, "POST", "http://foo.com/bar")
if err != nil {
t.Fatal("call foo failed:", err)
}
if ret["foo"] != "1" || ret["bar"] != "2" {
t.Fatal("call bar: invalid ret")
}
fmt.Println(ret)
}
{
resp, err := c.Post("http://foo.com/dump", "", nil)
if err != nil {
t.Fatal("post foo failed:", err)
}
resp.Body.Close()
resp, err = c.Post("http://foo.com/dump", "", strings.NewReader("abc"))
if err != nil {
t.Fatal("post foo failed:", err)
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatal("ioutil.ReadAll:", err)
}
if len(b) != 0 {
t.Fatal("body should be empty:", string(b))
}
}
}
// --------------------------------------------------------------------

52
vendor/github.com/qiniu/x/reqid.v7/reqid.go generated vendored Normal file
View File

@@ -0,0 +1,52 @@
package reqid
import (
"encoding/binary"
"encoding/base64"
"net/http"
"time"
. "golang.org/x/net/context"
)
// --------------------------------------------------------------------
var pid = uint32(time.Now().UnixNano() % 4294967291)
func genReqId() string {
var b [12]byte
binary.LittleEndian.PutUint32(b[:], pid)
binary.LittleEndian.PutUint64(b[4:], uint64(time.Now().UnixNano()))
return base64.URLEncoding.EncodeToString(b[:])
}
// --------------------------------------------------------------------
type key int // key is unexported and used for Context
const (
reqidKey key = 0
)
func NewContext(ctx Context, reqid string) Context {
return WithValue(ctx, reqidKey, reqid)
}
func NewContextWith(ctx Context, w http.ResponseWriter, req *http.Request) Context {
reqid := req.Header.Get("X-Reqid")
if reqid == "" {
reqid = genReqId()
req.Header.Set("X-Reqid", reqid)
}
h := w.Header()
h.Set("X-Reqid", reqid)
return WithValue(ctx, reqidKey, reqid)
}
func FromContext(ctx Context) (reqid string, ok bool) {
reqid, ok = ctx.Value(reqidKey).(string)
return
}
// --------------------------------------------------------------------

107
vendor/github.com/qiniu/x/rpc.v7/gob/gobrpc_client.go generated vendored Normal file
View File

@@ -0,0 +1,107 @@
package gob
import (
"bytes"
"encoding/gob"
"io"
"io/ioutil"
"net/http"
"strconv"
"qiniupkg.com/x/rpc.v7"
. "golang.org/x/net/context"
)
// ---------------------------------------------------------------------------
func Register(value interface{}) {
gob.Register(value)
}
func RegisterName(name string, value interface{}) {
gob.RegisterName(name, value)
}
// ---------------------------------------------------------------------------
func ResponseError(resp *http.Response) (err error) {
e := &rpc.ErrorInfo{
Reqid: resp.Header.Get("X-Reqid"),
Code: resp.StatusCode,
}
if resp.StatusCode > 299 {
e.Err = resp.Header.Get("X-Err")
if errno := resp.Header.Get("X-Errno"); errno != "" {
v, err2 := strconv.ParseInt(errno, 10, 32)
if err2 != nil {
e.Err = err2.Error()
}
e.Errno = int(v)
}
}
return e
}
func CallRet(ctx Context, ret interface{}, resp *http.Response) (err error) {
defer func() {
io.Copy(ioutil.Discard, resp.Body)
resp.Body.Close()
}()
if resp.StatusCode/100 == 2 {
if ret != nil && resp.ContentLength != 0 {
err = gob.NewDecoder(resp.Body).Decode(ret)
if err != nil {
return
}
}
if resp.StatusCode == 200 {
return nil
}
}
return ResponseError(resp)
}
// ---------------------------------------------------------------------------
type Client struct {
rpc.Client
}
var (
DefaultClient = Client{rpc.DefaultClient}
)
func (r Client) Call(
ctx Context, ret interface{}, method, url1 string) (err error) {
resp, err := r.DoRequestWith(ctx, method, url1, "application/gob", nil, 0)
if err != nil {
return err
}
return CallRet(ctx, ret, resp)
}
func (r Client) CallWithGob(
ctx Context, ret interface{}, method, url1 string, params interface{}) (err error) {
var b bytes.Buffer
err = gob.NewEncoder(&b).Encode(params)
if err != nil {
return err
}
resp, err := r.DoRequestWith(ctx, method, url1, "application/gob", &b, b.Len())
if err != nil {
return err
}
return CallRet(ctx, ret, resp)
}
// ---------------------------------------------------------------------------

344
vendor/github.com/qiniu/x/rpc.v7/rpc_client.go generated vendored Normal file
View File

@@ -0,0 +1,344 @@
package rpc
import (
"bytes"
"encoding/json"
"errors"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
"qiniupkg.com/x/reqid.v7"
. "golang.org/x/net/context"
)
var (
UserAgent = "Golang qiniu/rpc package"
)
var (
ErrInvalidRequestURL = errors.New("invalid request url")
)
// --------------------------------------------------------------------
type Client struct {
*http.Client
}
var (
DefaultClient = Client{&http.Client{Transport: http.DefaultTransport}}
)
// --------------------------------------------------------------------
func newRequest(method, url1 string, body io.Reader) (req *http.Request, err error) {
var host string
// url1 = "-H <Host> http://<ip>[:<port>]/<path>"
//
if strings.HasPrefix(url1, "-H") {
url2 := strings.TrimLeft(url1[2:], " \t")
pos := strings.Index(url2, " ")
if pos <= 0 {
return nil, ErrInvalidRequestURL
}
host = url2[:pos]
url1 = strings.TrimLeft(url2[pos+1:], " \t")
}
req, err = http.NewRequest(method, url1, body)
if err != nil {
return
}
if host != "" {
req.Host = host
}
return
}
func (r Client) DoRequest(ctx Context, method, url string) (resp *http.Response, err error) {
req, err := newRequest(method, url, nil)
if err != nil {
return
}
return r.Do(ctx, req)
}
func (r Client) DoRequestWith(
ctx Context, method, url1 string,
bodyType string, body io.Reader, bodyLength int) (resp *http.Response, err error) {
req, err := newRequest(method, url1, body)
if err != nil {
return
}
req.Header.Set("Content-Type", bodyType)
req.ContentLength = int64(bodyLength)
return r.Do(ctx, req)
}
func (r Client) DoRequestWith64(
ctx Context, method, url1 string,
bodyType string, body io.Reader, bodyLength int64) (resp *http.Response, err error) {
req, err := newRequest(method, url1, body)
if err != nil {
return
}
req.Header.Set("Content-Type", bodyType)
req.ContentLength = bodyLength
return r.Do(ctx, req)
}
func (r Client) DoRequestWithForm(
ctx Context, method, url1 string, data map[string][]string) (resp *http.Response, err error) {
msg := url.Values(data).Encode()
if method == "GET" || method == "HEAD" || method == "DELETE" {
if strings.ContainsRune(url1, '?') {
url1 += "&"
} else {
url1 += "?"
}
return r.DoRequest(ctx, method, url1 + msg)
}
return r.DoRequestWith(
ctx, method, url1, "application/x-www-form-urlencoded", strings.NewReader(msg), len(msg))
}
func (r Client) DoRequestWithJson(
ctx Context, method, url1 string, data interface{}) (resp *http.Response, err error) {
msg, err := json.Marshal(data)
if err != nil {
return
}
return r.DoRequestWith(
ctx, method, url1, "application/json", bytes.NewReader(msg), len(msg))
}
func (r Client) Do(ctx Context, req *http.Request) (resp *http.Response, err error) {
if ctx == nil {
ctx = Background()
}
if reqid, ok := reqid.FromContext(ctx); ok {
req.Header.Set("X-Reqid", reqid)
}
if _, ok := req.Header["User-Agent"]; !ok {
req.Header.Set("User-Agent", UserAgent)
}
transport := r.Transport // don't change r.Transport
if transport == nil {
transport = http.DefaultTransport
}
// avoid cancel() is called before Do(req), but isn't accurate
select {
case <-ctx.Done():
err = ctx.Err()
return
default:
}
if tr, ok := getRequestCanceler(transport); ok { // support CancelRequest
reqC := make(chan bool, 1)
go func() {
resp, err = r.Client.Do(req)
reqC <- true
}()
select {
case <-reqC:
case <-ctx.Done():
tr.CancelRequest(req)
<-reqC
err = ctx.Err()
}
} else {
resp, err = r.Client.Do(req)
}
return
}
// --------------------------------------------------------------------
type ErrorInfo struct {
Err string `json:"error,omitempty"`
Key string `json:"key,omitempty"`
Reqid string `json:"reqid,omitempty"`
Errno int `json:"errno,omitempty"`
Code int `json:"code"`
}
func (r *ErrorInfo) ErrorDetail() string {
msg, _ := json.Marshal(r)
return string(msg)
}
func (r *ErrorInfo) Error() string {
return r.Err
}
func (r *ErrorInfo) RpcError() (code, errno int, key, err string) {
return r.Code, r.Errno, r.Key, r.Err
}
func (r *ErrorInfo) HttpCode() int {
return r.Code
}
// --------------------------------------------------------------------
func parseError(e *ErrorInfo, r io.Reader) {
body, err1 := ioutil.ReadAll(r)
if err1 != nil {
e.Err = err1.Error()
return
}
var ret struct {
Err string `json:"error"`
Key string `json:"key"`
Errno int `json:"errno"`
}
if json.Unmarshal(body, &ret) == nil && ret.Err != "" {
// qiniu error msg style returns here
e.Err, e.Key, e.Errno = ret.Err, ret.Key, ret.Errno
return
}
e.Err = string(body)
}
func ResponseError(resp *http.Response) (err error) {
e := &ErrorInfo{
Reqid: resp.Header.Get("X-Reqid"),
Code: resp.StatusCode,
}
if resp.StatusCode > 299 {
if resp.ContentLength != 0 {
ct, ok := resp.Header["Content-Type"]
if ok && strings.HasPrefix(ct[0], "application/json") {
parseError(e, resp.Body)
}
}
}
return e
}
func CallRet(ctx Context, ret interface{}, resp *http.Response) (err error) {
defer func() {
io.Copy(ioutil.Discard, resp.Body)
resp.Body.Close()
}()
if resp.StatusCode/100 == 2 {
if ret != nil && resp.ContentLength != 0 {
err = json.NewDecoder(resp.Body).Decode(ret)
if err != nil {
return
}
}
if resp.StatusCode == 200 {
return nil
}
}
return ResponseError(resp)
}
func (r Client) CallWithForm(
ctx Context, ret interface{}, method, url1 string, param map[string][]string) (err error) {
resp, err := r.DoRequestWithForm(ctx, method, url1, param)
if err != nil {
return err
}
return CallRet(ctx, ret, resp)
}
func (r Client) CallWithJson(
ctx Context, ret interface{}, method, url1 string, param interface{}) (err error) {
resp, err := r.DoRequestWithJson(ctx, method, url1, param)
if err != nil {
return err
}
return CallRet(ctx, ret, resp)
}
func (r Client) CallWith(
ctx Context, ret interface{}, method, url1, bodyType string, body io.Reader, bodyLength int) (err error) {
resp, err := r.DoRequestWith(ctx, method, url1, bodyType, body, bodyLength)
if err != nil {
return err
}
return CallRet(ctx, ret, resp)
}
func (r Client) CallWith64(
ctx Context, ret interface{}, method, url1, bodyType string, body io.Reader, bodyLength int64) (err error) {
resp, err := r.DoRequestWith64(ctx, method, url1, bodyType, body, bodyLength)
if err != nil {
return err
}
return CallRet(ctx, ret, resp)
}
func (r Client) Call(
ctx Context, ret interface{}, method, url1 string) (err error) {
resp, err := r.DoRequestWith(ctx, method, url1, "application/x-www-form-urlencoded", nil, 0)
if err != nil {
return err
}
return CallRet(ctx, ret, resp)
}
// ---------------------------------------------------------------------------
type requestCanceler interface {
CancelRequest(req *http.Request)
}
type nestedObjectGetter interface {
NestedObject() interface{}
}
func getRequestCanceler(tp http.RoundTripper) (rc requestCanceler, ok bool) {
if rc, ok = tp.(requestCanceler); ok {
return
}
p := interface{}(tp)
for {
getter, ok1 := p.(nestedObjectGetter)
if !ok1 {
return
}
p = getter.NestedObject()
if rc, ok = p.(requestCanceler); ok {
return
}
}
}
// --------------------------------------------------------------------

66
vendor/github.com/qiniu/x/rpc.v7/rpc_client_test.go generated vendored Normal file
View File

@@ -0,0 +1,66 @@
package rpc
import (
"fmt"
"net/http"
"testing"
)
// --------------------------------------------------------------------
func TestNewRequest(t *testing.T) {
req, err := http.NewRequest("GET", "-H\t abc.com \thttp://127.0.0.1/foo/bar", nil)
if err != nil {
t.Fatal("http.NewRequest failed")
}
if req.Host != "" {
t.Fatal(`http.NewRequest: req.Host != ""`)
}
req, err = newRequest("GET", "-H\t abc.com \thttp://127.0.0.1/foo/bar", nil)
if err != nil {
t.Fatal("newRequest failed:", err)
}
fmt.Println("Host:", req.Host, "path:", req.URL.Path, "url.host:", req.URL.Host)
if req.Host != "abc.com" || req.URL.Path != "/foo/bar" || req.URL.Host != "127.0.0.1" {
t.Fatal(`req.Host != "abc.com" || req.URL.Path != "/foo/bar" || req.URL.Host != "127.0.0.1"`)
}
}
// --------------------------------------------------------------------
type transport struct {
a http.RoundTripper
}
func (p *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
return p.a.RoundTrip(req)
}
func (p *transport) NestedObject() interface{} {
return p.a
}
func Test_getRequestCanceler(t *testing.T) {
p := &transport{a: http.DefaultTransport}
if _, ok := getRequestCanceler(p); !ok {
t.Fatal("getRequestCanceler failed")
}
p2 := &transport{a: p}
if _, ok := getRequestCanceler(p2); !ok {
t.Fatal("getRequestCanceler(p2) failed")
}
p3 := &transport{}
if _, ok := getRequestCanceler(p3); ok {
t.Fatal("getRequestCanceler(p3)?")
}
}
// --------------------------------------------------------------------

79
vendor/github.com/qiniu/x/ts.v7/testing.go generated vendored Normal file
View File

@@ -0,0 +1,79 @@
package ts
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strconv"
"testing"
)
const logStackLevel = 2
func log(skip int, t *testing.T, args ...interface{}) {
_, file, line, _ := runtime.Caller(skip)
_, fname := filepath.Split(file)
args1 := make([]interface{}, len(args)+1)
args1[0] = fname + ":" + strconv.Itoa(line) + ":"
copy(args1[1:], args)
if os.PathSeparator == '/' {
fmt.Fprintln(os.Stdout, args1...)
} else {
t.Log(args1...)
}
}
func logf(skip int, t *testing.T, format string, args ...interface{}) {
_, file, line, _ := runtime.Caller(skip)
_, fname := filepath.Split(file)
args2 := make([]interface{}, len(args)+2)
args2[0] = fname
args2[1] = line
copy(args2[2:], args)
if os.PathSeparator == '/' {
fmt.Fprintf(os.Stderr, "%s:%d: "+format+"\n", args2...)
} else {
t.Logf("%s:%d: "+format, args2...)
}
}
// Log formats its arguments using default formatting, analogous to Print(),
// and records the text in the error log.
func Log(t *testing.T, args ...interface{}) {
log(logStackLevel, t, args...)
}
// Logf formats its arguments according to the format, analogous to Printf(),
// and records the text in the error log.
func Logf(t *testing.T, format string, args ...interface{}) {
logf(logStackLevel, t, format, args...)
}
// Error is equivalent to Log() followed by Fail().
func Error(t *testing.T, args ...interface{}) {
log(logStackLevel, t, args...)
t.Fail()
}
// Errorf is equivalent to Logf() followed by Fail().
func Errorf(t *testing.T, format string, args ...interface{}) {
logf(logStackLevel, t, format, args...)
t.Fail()
}
// Fatal is equivalent to Log() followed by FailNow().
func Fatal(t *testing.T, args ...interface{}) {
log(logStackLevel, t, args...)
t.FailNow()
}
// Fatalf is equivalent to Logf() followed by FailNow().
func Fatalf(t *testing.T, format string, args ...interface{}) {
logf(logStackLevel, t, format, args...)
t.FailNow()
}

208
vendor/github.com/qiniu/x/url.v7/urlescape.go generated vendored Normal file
View File

@@ -0,0 +1,208 @@
package url
import (
"strconv"
)
type Encoding int
const (
EncodePath Encoding = 1 + iota
EncodeUserPassword
EncodeQueryComponent
EncodeFragment
)
type EscapeError string
func (e EscapeError) Error() string {
return "invalid URL escape " + strconv.Quote(string(e))
}
func ishex(c byte) bool {
switch {
case '0' <= c && c <= '9':
return true
case 'a' <= c && c <= 'f':
return true
case 'A' <= c && c <= 'F':
return true
}
return false
}
func unhex(c byte) byte {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
// Return true if the specified character should be escaped when
// appearing in a URL string, according to RFC 3986.
// When 'all' is true the full range of reserved characters are matched.
func shouldEscape(c byte, mode Encoding) bool {
// §2.3 Unreserved characters (alphanum)
if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' {
return false
}
switch c {
case '-', '_', '.', '~': // §2.3 Unreserved characters (mark)
return false
case '$', '&', '+', ',', '/', ':', ';', '=', '?', '@': // §2.2 Reserved characters (reserved)
// Different sections of the URL allow a few of
// the reserved characters to appear unescaped.
switch mode {
case EncodePath: // §3.3
// The RFC allows : @ & = + $ but saves / ; , for assigning
// meaning to individual path segments. This package
// only manipulates the path as a whole, so we allow those
// last two as well. That leaves only ? to escape.
return c == '?'
case EncodeUserPassword: // §3.2.2
// The RFC allows ; : & = + $ , in userinfo, so we must escape only @ and /.
// The parsing of userinfo treats : as special so we must escape that too.
return c == '@' || c == '/' || c == ':'
case EncodeQueryComponent: // §3.4
// The RFC reserves (so we must escape) everything.
return true
case EncodeFragment: // §4.1
// The RFC text is silent but the grammar allows
// everything, so escape nothing.
return false
}
}
// Everything else must be escaped.
return true
}
// QueryUnescape does the inverse transformation of QueryEscape, converting
// %AB into the byte 0xAB and '+' into ' ' (space). It returns an error if
// any % is not followed by two hexadecimal digits.
func QueryUnescape(s string) (string, error) {
return UnescapeEx(s, EncodeQueryComponent)
}
func Unescape(s string) (string, error) {
return UnescapeEx(s, EncodePath)
}
// UnescapeEx unescapes a string; the mode specifies
// which section of the URL string is being unescaped.
func UnescapeEx(s string, mode Encoding) (string, error) {
// Count %, check that they're well-formed.
n := 0
hasPlus := false
for i := 0; i < len(s); {
switch s[i] {
case '%':
n++
if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
s = s[i:]
if len(s) > 3 {
s = s[0:3]
}
return "", EscapeError(s)
}
i += 3
case '+':
hasPlus = mode == EncodeQueryComponent
i++
default:
i++
}
}
if n == 0 && !hasPlus {
return s, nil
}
t := make([]byte, len(s)-2*n)
j := 0
for i := 0; i < len(s); {
switch s[i] {
case '%':
t[j] = unhex(s[i+1])<<4 | unhex(s[i+2])
j++
i += 3
case '+':
if mode == EncodeQueryComponent {
t[j] = ' '
} else {
t[j] = '+'
}
j++
i++
default:
t[j] = s[i]
j++
i++
}
}
return string(t), nil
}
// QueryEscape escapes the string so it can be safely placed
// inside a URL query.
func QueryEscape(s string) string {
return EscapeEx(s, EncodeQueryComponent)
}
func Escape(s string) string {
return EscapeEx(s, EncodePath)
}
func EscapeEx(s string, mode Encoding) string {
spaceCount, hexCount := 0, 0
for i := 0; i < len(s); i++ {
c := s[i]
if shouldEscape(c, mode) {
if c == ' ' && mode == EncodeQueryComponent {
spaceCount++
} else {
hexCount++
}
}
}
if spaceCount == 0 && hexCount == 0 {
return s
}
t := make([]byte, len(s)+2*hexCount)
j := 0
for i := 0; i < len(s); i++ {
switch c := s[i]; {
case c == ' ' && mode == EncodeQueryComponent:
t[j] = '+'
j++
case shouldEscape(c, mode):
t[j] = '%'
t[j+1] = "0123456789ABCDEF"[c>>4]
t[j+2] = "0123456789ABCDEF"[c&15]
j += 3
default:
t[j] = s[i]
j++
}
}
return string(t)
}

211
vendor/github.com/qiniu/x/xlog.v7/xlog.go generated vendored Normal file
View File

@@ -0,0 +1,211 @@
package xlog
import (
"fmt"
"io"
"os"
"runtime"
"qiniupkg.com/x/log.v7"
"qiniupkg.com/x/reqid.v7"
. "golang.org/x/net/context"
)
const (
Ldate = log.Ldate
Ltime = log.Ltime
Lmicroseconds = log.Lmicroseconds
Llongfile = log.Llongfile
Lshortfile = log.Lshortfile
Lmodule = log.Lmodule
Llevel = log.Llevel
LstdFlags = log.LstdFlags
Ldefault = log.Ldefault
)
const (
Ldebug = log.Ldebug
Linfo = log.Linfo
Lwarn = log.Lwarn
Lerror = log.Lerror
Lpanic = log.Lpanic
Lfatal = log.Lfatal
)
// ============================================================================
// type *Logger
type Logger struct {
ReqId string
}
func New(reqId string) *Logger {
return &Logger{reqId}
}
func NewWith(ctx Context) *Logger {
reqId, ok := reqid.FromContext(ctx)
if !ok {
log.Debug("xlog.New: reqid isn't find in context")
}
return &Logger{reqId}
}
func (xlog *Logger) Spawn(child string) *Logger {
return &Logger{xlog.ReqId + "." + child}
}
// ============================================================================
// Print calls Output to print to the standard Logger.
// Arguments are handled in the manner of fmt.Print.
func (xlog *Logger) Print(v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Linfo, 2, fmt.Sprint(v...))
}
// Printf calls Output to print to the standard Logger.
// Arguments are handled in the manner of fmt.Printf.
func (xlog *Logger) Printf(format string, v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Linfo, 2, fmt.Sprintf(format, v...))
}
// Println calls Output to print to the standard Logger.
// Arguments are handled in the manner of fmt.Println.
func (xlog *Logger) Println(v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Linfo, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
func (xlog *Logger) Debugf(format string, v ...interface{}) {
if log.Ldebug < log.Std.Level {
return
}
log.Std.Output(xlog.ReqId, log.Ldebug, 2, fmt.Sprintf(format, v...))
}
func (xlog *Logger) Debug(v ...interface{}) {
if log.Ldebug < log.Std.Level {
return
}
log.Std.Output(xlog.ReqId, log.Ldebug, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
func (xlog *Logger) Infof(format string, v ...interface{}) {
if log.Linfo < log.Std.Level {
return
}
log.Std.Output(xlog.ReqId, log.Linfo, 2, fmt.Sprintf(format, v...))
}
func (xlog *Logger) Info(v ...interface{}) {
if log.Linfo < log.Std.Level {
return
}
log.Std.Output(xlog.ReqId, log.Linfo, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
func (xlog *Logger) Warnf(format string, v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Lwarn, 2, fmt.Sprintf(format, v...))
}
func (xlog *Logger) Warn(v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Lwarn, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
func (xlog *Logger) Errorf(format string, v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Lerror, 2, fmt.Sprintf(format, v...))
}
func (xlog *Logger) Error(v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Lerror, 2, fmt.Sprintln(v...))
}
// -----------------------------------------
// Fatal is equivalent to Print() followed by a call to os.Exit(1).
func (xlog *Logger) Fatal(v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Lfatal, 2, fmt.Sprint(v...))
os.Exit(1)
}
// Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
func (xlog *Logger) Fatalf(format string, v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Lfatal, 2, fmt.Sprintf(format, v...))
os.Exit(1)
}
// Fatalln is equivalent to Println() followed by a call to os.Exit(1).
func (xlog *Logger) Fatalln(v ...interface{}) {
log.Std.Output(xlog.ReqId, log.Lfatal, 2, fmt.Sprintln(v...))
os.Exit(1)
}
// -----------------------------------------
// Panic is equivalent to Print() followed by a call to panic().
func (xlog *Logger) Panic(v ...interface{}) {
s := fmt.Sprint(v...)
log.Std.Output(xlog.ReqId, log.Lpanic, 2, s)
panic(s)
}
// Panicf is equivalent to Printf() followed by a call to panic().
func (xlog *Logger) Panicf(format string, v ...interface{}) {
s := fmt.Sprintf(format, v...)
log.Std.Output(xlog.ReqId, log.Lpanic, 2, s)
panic(s)
}
// Panicln is equivalent to Println() followed by a call to panic().
func (xlog *Logger) Panicln(v ...interface{}) {
s := fmt.Sprintln(v...)
log.Std.Output(xlog.ReqId, log.Lpanic, 2, s)
panic(s)
}
func (xlog *Logger) Stack(v ...interface{}) {
s := fmt.Sprint(v...)
s += "\n"
buf := make([]byte, 1024*1024)
n := runtime.Stack(buf, true)
s += string(buf[:n])
s += "\n"
log.Std.Output(xlog.ReqId, log.Lerror, 2, s)
}
func (xlog *Logger) SingleStack(v ...interface{}) {
s := fmt.Sprint(v...)
s += "\n"
buf := make([]byte, 1024*1024)
n := runtime.Stack(buf, false)
s += string(buf[:n])
s += "\n"
log.Std.Output(xlog.ReqId, log.Lerror, 2, s)
}
// ============================================================================
func SetOutput(w io.Writer) {
log.SetOutput(w)
}
func SetFlags(flag int) {
log.SetFlags(flag)
}
func SetOutputLevel(lvl int) {
log.SetOutputLevel(lvl)
}
// ============================================================================