<commit_before>// Copyright 2011 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 http_test

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	. "net/http"
	"net/http/httptest"
	"reflect"
	"strconv"
	"strings"
	"testing"
)

var sniffTests = []struct {
	desc        string
	data        []byte
	contentType string
}{
	// Some nonsense.
	{"Empty", []byte{}, "text/plain; charset=utf-8"},
	{"Binary", []byte{1, 2, 3}, "application/octet-stream"},

	{"HTML document #1", []byte(`<HtMl><bOdY>blah blah blah</body></html>`), "text/html; charset=utf-8"},
	{"HTML document #2", []byte(`<HTML></HTML>`), "text/html; charset=utf-8"},
	{"HTML document #3 (leading whitespace)", []byte(`   <!DOCTYPE HTML>...`), "text/html; charset=utf-8"},
	{"HTML document #4 (leading CRLF)", []byte("\r\n..."), "text/html; charset=utf-8"},

	{"Plain text", []byte(`This is not HTML. It has ☃ though.`), "text/plain; charset=utf-8"},

	{"XML", []byte("\n<?xml!"), "text/xml; charset=utf-8"},

	// Image types.
	{"GIF 87a", []byte(`GIF87a`), "image/gif"},
	{"GIF 89a", []byte(`GIF89a...`), "image/gif"},

	{"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
}

func TestDetectContentType(t *testing.T) {
	for _, tt := range sniffTests {
		ct := DetectContentType(tt.data)
		if ct != tt.contentType {
			t.Errorf("%v: DetectContentType = %q, want %q", tt.desc, ct, tt.contentType)
		}
	}
}

func TestServerContentType_h1(t *testing.T) { testServerContentType(t, false) }
func TestServerContentType_h2(t *testing.T) { testServerContentType(t, true) }

func testServerContentType(t *testing.T, h2 bool) {
	defer afterTest(t)
	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
		i, _ := strconv.Atoi(r.FormValue("i"))
		tt := sniffTests[i]
		n, err := w.Write(tt.data)
		if n != len(tt.data) || err != nil {
			log.Fatalf("%v: Write(%q) = %v, %v want %d, nil", tt.desc, tt.data, n, err, len(tt.data))
		}
	}))
	defer cst.close()

	for i, tt := range sniffTests {
		resp, err := cst.c.Get(cst.ts.URL + "/?i=" + strconv.Itoa(i))
		if err != nil {
			t.Errorf("%v: %v", tt.desc, err)
			continue
		}
		if ct := resp.Header.Get("Content-Type"); ct != tt.contentType {
			t.Errorf("%v: Content-Type = %q, want %q", tt.desc, ct, tt.contentType)
		}
		data, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			t.Errorf("%v: reading body: %v", tt.desc, err)
		} else if !bytes.Equal(data, tt.data) {
			t.Errorf("%v: data is %q, want %q", tt.desc, data, tt.data)
		}
		resp.Body.Close()
	}
}

// Issue 5953: shouldn't sniff if the handler set a Content-Type header,
// even if it's the empty string.
func TestServerIssue5953(t *testing.T) {
	defer afterTest(t)
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		w.Header()["Content-Type"] = []string{""}
		fmt.Fprintf(w, "hi")
	}))
	defer ts.Close()

	resp, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}

	got := resp.Header["Content-Type"]
	want := []string{""}
	if !reflect.DeepEqual(got, want) {
		t.Errorf("Content-Type = %q; want %q", got, want)
	}
	resp.Body.Close()
}

func TestContentTypeWithCopy_h1(t *testing.T) { testContentTypeWithCopy(t, false) }
func TestContentTypeWithCopy_h2(t *testing.T) { testContentTypeWithCopy(t, true) }

func testContentTypeWithCopy(t *testing.T, h2 bool) {
	defer afterTest(t)

	const (
		input    = "\n\n\t\n"
		expected = "text/html; charset=utf-8"
	)

	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
		// Use io.Copy from a bytes.Buffer to trigger ReadFrom.
		buf := bytes.NewBuffer([]byte(input))
		n, err := io.Copy(w, buf)
		if int(n) != len(input) || err != nil {
			t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
		}
	}))
	defer cst.close()

	resp, err := cst.c.Get(cst.ts.URL)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if ct := resp.Header.Get("Content-Type"); ct != expected {
		t.Errorf("Content-Type = %q, want %q", ct, expected)
	}
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Errorf("reading body: %v", err)
	} else if !bytes.Equal(data, []byte(input)) {
		t.Errorf("data is %q, want %q", data, input)
	}
	resp.Body.Close()
}

func TestSniffWriteSize_h1(t *testing.T) { testSniffWriteSize(t, false) }
func TestSniffWriteSize_h2(t *testing.T) { testSniffWriteSize(t, true) }

func testSniffWriteSize(t *testing.T, h2 bool) {
	defer afterTest(t)
	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
		size, _ := strconv.Atoi(r.FormValue("size"))
		written, err := io.WriteString(w, strings.Repeat("a", size))
		if err != nil {
			t.Errorf("write of %d bytes: %v", size, err)
			return
		}
		if written != size {
			t.Errorf("write of %d bytes wrote %d bytes", size, written)
		}
	}))
	defer cst.close()
	for _, size := range []int{0, 1, 200, 600, 999, 1000, 1023, 1024, 512 << 10, 1 << 20} {
		res, err := cst.c.Get(fmt.Sprintf("%s/?size=%d", cst.ts.URL, size))
		if err != nil {
			t.Fatalf("size %d: %v", size, err)
		}
		if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
			t.Fatalf("size %d: io.Copy of body = %v", size, err)
		}
		if err := res.Body.Close(); err != nil {
			t.Fatalf("size %d: body Close = %v", size, err)
		}
	}
}
<commit_msg>net/http: sniffTest for 5953 set in http2 mode<commit_after>// Copyright 2011 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 http_test

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	. "net/http"
	"reflect"
	"strconv"
	"strings"
	"testing"
)

var sniffTests = []struct {
	desc        string
	data        []byte
	contentType string
}{
	// Some nonsense.
	{"Empty", []byte{}, "text/plain; charset=utf-8"},
	{"Binary", []byte{1, 2, 3}, "application/octet-stream"},

	{"HTML document #1", []byte(`<HtMl><bOdY>blah blah blah</body></html>`), "text/html; charset=utf-8"},
	{"HTML document #2", []byte(`<HTML></HTML>`), "text/html; charset=utf-8"},
	{"HTML document #3 (leading whitespace)", []byte(`   <!DOCTYPE HTML>...`), "text/html; charset=utf-8"},
	{"HTML document #4 (leading CRLF)", []byte("\r\n..."), "text/html; charset=utf-8"},

	{"Plain text", []byte(`This is not HTML. It has ☃ though.`), "text/plain; charset=utf-8"},

	{"XML", []byte("\n<?xml!"), "text/xml; charset=utf-8"},

	// Image types.
	{"GIF 87a", []byte(`GIF87a`), "image/gif"},
	{"GIF 89a", []byte(`GIF89a...`), "image/gif"},

	{"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
}

func TestDetectContentType(t *testing.T) {
	for _, tt := range sniffTests {
		ct := DetectContentType(tt.data)
		if ct != tt.contentType {
			t.Errorf("%v: DetectContentType = %q, want %q", tt.desc, ct, tt.contentType)
		}
	}
}

func TestServerContentType_h1(t *testing.T) { testServerContentType(t, false) }
func TestServerContentType_h2(t *testing.T) { testServerContentType(t, true) }

func testServerContentType(t *testing.T, h2 bool) {
	defer afterTest(t)
	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
		i, _ := strconv.Atoi(r.FormValue("i"))
		tt := sniffTests[i]
		n, err := w.Write(tt.data)
		if n != len(tt.data) || err != nil {
			log.Fatalf("%v: Write(%q) = %v, %v want %d, nil", tt.desc, tt.data, n, err, len(tt.data))
		}
	}))
	defer cst.close()

	for i, tt := range sniffTests {
		resp, err := cst.c.Get(cst.ts.URL + "/?i=" + strconv.Itoa(i))
		if err != nil {
			t.Errorf("%v: %v", tt.desc, err)
			continue
		}
		if ct := resp.Header.Get("Content-Type"); ct != tt.contentType {
			t.Errorf("%v: Content-Type = %q, want %q", tt.desc, ct, tt.contentType)
		}
		data, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			t.Errorf("%v: reading body: %v", tt.desc, err)
		} else if !bytes.Equal(data, tt.data) {
			t.Errorf("%v: data is %q, want %q", tt.desc, data, tt.data)
		}
		resp.Body.Close()
	}
}

// Issue 5953: shouldn't sniff if the handler set a Content-Type header,
// even if it's the empty string.
func TestServerIssue5953_h1(t *testing.T) { testServerIssue5953(t, false) }
func TestServerIssue5953_h2(t *testing.T) { testServerIssue5953(t, true) }

func testServerIssue5953(t *testing.T, h2 bool) {
	defer afterTest(t)
	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
		w.Header()["Content-Type"] = []string{""}
		fmt.Fprintf(w, "hi")
	}))
	defer cst.close()

	resp, err := cst.c.Get(cst.ts.URL)
	if err != nil {
		t.Fatal(err)
	}

	got := resp.Header["Content-Type"]
	want := []string{""}
	if !reflect.DeepEqual(got, want) {
		t.Errorf("Content-Type = %q; want %q", got, want)
	}
	resp.Body.Close()
}

func TestContentTypeWithCopy_h1(t *testing.T) { testContentTypeWithCopy(t, false) }
func TestContentTypeWithCopy_h2(t *testing.T) { testContentTypeWithCopy(t, true) }

func testContentTypeWithCopy(t *testing.T, h2 bool) {
	defer afterTest(t)

	const (
		input    = "\n\n\t\n"
		expected = "text/html; charset=utf-8"
	)

	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
		// Use io.Copy from a bytes.Buffer to trigger ReadFrom.
		buf := bytes.NewBuffer([]byte(input))
		n, err := io.Copy(w, buf)
		if int(n) != len(input) || err != nil {
			t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
		}
	}))
	defer cst.close()

	resp, err := cst.c.Get(cst.ts.URL)
	if err != nil {
		t.Fatalf("Get: %v", err)
	}
	if ct := resp.Header.Get("Content-Type"); ct != expected {
		t.Errorf("Content-Type = %q, want %q", ct, expected)
	}
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Errorf("reading body: %v", err)
	} else if !bytes.Equal(data, []byte(input)) {
		t.Errorf("data is %q, want %q", data, input)
	}
	resp.Body.Close()
}

func TestSniffWriteSize_h1(t *testing.T) { testSniffWriteSize(t, false) }
func TestSniffWriteSize_h2(t *testing.T) { testSniffWriteSize(t, true) }

func testSniffWriteSize(t *testing.T, h2 bool) {
	defer afterTest(t)
	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
		size, _ := strconv.Atoi(r.FormValue("size"))
		written, err := io.WriteString(w, strings.Repeat("a", size))
		if err != nil {
			t.Errorf("write of %d bytes: %v", size, err)
			return
		}
		if written != size {
			t.Errorf("write of %d bytes wrote %d bytes", size, written)
		}
	}))
	defer cst.close()
	for _, size := range []int{0, 1, 200, 600, 999, 1000, 1023, 1024, 512 << 10, 1 << 20} {
		res, err := cst.c.Get(fmt.Sprintf("%s/?size=%d", cst.ts.URL, size))
		if err != nil {
			t.Fatalf("size %d: %v", size, err)
		}
		if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
			t.Fatalf("size %d: io.Copy of body = %v", size, err)
		}
		if err := res.Body.Close(); err != nil {
			t.Fatalf("size %d: body Close = %v", size, err)
		}
	}
}
<|endoftext|>


<commit_before>// Pygments wrapper for golang. Pygments is a syntax highlighter

package pygments

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

var (
	bin = "pygmentize"
)

func Binary(path string) {
	bin = path
}

func Which() string {
	return bin
}

func Highlight(code string, lexer string, format string, enc string) string {

	if _, err := exec.LookPath(bin); err != nil {
		fmt.Println("You do not have " + bin + " installed!")
		os.Exit(0)
	}

	cmd := exec.Command(bin, "-l"+lexer, "-f"+format, "-O encoding="+enc)
	cmd.Stdin = strings.NewReader(code)

	var out bytes.Buffer
	cmd.Stdout = &out

	var stderr bytes.Buffer
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		fmt.Println(stderr.String())
		fmt.Println(err)
		os.Exit(0)
	}

	return out.String()
}
<commit_msg>Make lexer argument optional and guess content if not provided<commit_after>// Pygments wrapper for golang. Pygments is a syntax highlighter

package pygments

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

var (
	bin = "pygmentize"
)

func Binary(path string) {
	bin = path
}

func Which() string {
	return bin
}

func Highlight(code string, lexer string, format string, enc string) string {

	if _, err := exec.LookPath(bin); err != nil {
		fmt.Println("You do not have " + bin + " installed!")
		os.Exit(0)
	}

	// Guess the lexer based on content if a specific one is not provided
	lexerArg := "-g"
	if lexer != "" {
		lexerArg = "-l" + lexer
	}

	cmd := exec.Command(bin, lexerArg, "-f"+format, "-O encoding="+enc)
	cmd.Stdin = strings.NewReader(code)

	var out bytes.Buffer
	cmd.Stdout = &out

	var stderr bytes.Buffer
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		fmt.Println(stderr.String())
		fmt.Println(err)
		os.Exit(0)
	}

	return out.String()
}
<|endoftext|>


<commit_before>package raft

type Entry struct {
	Term int
	Data []byte
}

type log struct {
	ents    []Entry
	commit  int
	applied int
}

func newLog() *log {
	return &log{
		ents:    make([]Entry, 1),
		commit:  0,
		applied: 0,
	}
}

func (l *log) maybeAppend(index, logTerm, commit int, ents ...Entry) bool {
	if l.matchTerm(index, logTerm) {
		l.append(index, ents...)
		l.commit = commit
		return true
	}
	return false
}

func (l *log) append(after int, ents ...Entry) int {
	l.ents = append(l.ents[:after+1], ents...)
	return len(l.ents) - 1
}

func (l *log) lastIndex() int {
	return len(l.ents) - 1
}

func (l *log) term(i int) int {
	if i > l.lastIndex() {
		return -1
	}
	return l.ents[i].Term
}

func (l *log) entries(i int) []Entry {
	if i > l.lastIndex() {
		return nil
	}
	return l.ents[i:]
}

func (l *log) isUpToDate(i, term int) bool {
	e := l.ents[l.lastIndex()]
	return term > e.Term || (term == e.Term && i >= l.lastIndex())
}

func (l *log) matchTerm(i, term int) bool {
	if i > l.lastIndex() {
		return false
	}
	return l.ents[i].Term == term
}

func (l *log) maybeCommit(maxIndex, term int) bool {
	if maxIndex > l.commit && l.term(maxIndex) == term {
		l.commit = maxIndex
		return true
	}
	return false
}

func (l *log) nextEnts() (ents []Entry) {
	if l.commit > l.applied {
		ents = l.ents[l.applied+1 : l.commit+1]
		l.applied = l.commit
	}
	return ents
}
<commit_msg>raft: use log.lastIndex()<commit_after>package raft

type Entry struct {
	Term int
	Data []byte
}

type log struct {
	ents    []Entry
	commit  int
	applied int
}

func newLog() *log {
	return &log{
		ents:    make([]Entry, 1),
		commit:  0,
		applied: 0,
	}
}

func (l *log) maybeAppend(index, logTerm, commit int, ents ...Entry) bool {
	if l.matchTerm(index, logTerm) {
		l.append(index, ents...)
		l.commit = commit
		return true
	}
	return false
}

func (l *log) append(after int, ents ...Entry) int {
	l.ents = append(l.ents[:after+1], ents...)
	return l.lastIndex()
}

func (l *log) lastIndex() int {
	return len(l.ents) - 1
}

func (l *log) term(i int) int {
	if i > l.lastIndex() {
		return -1
	}
	return l.ents[i].Term
}

func (l *log) entries(i int) []Entry {
	if i > l.lastIndex() {
		return nil
	}
	return l.ents[i:]
}

func (l *log) isUpToDate(i, term int) bool {
	e := l.ents[l.lastIndex()]
	return term > e.Term || (term == e.Term && i >= l.lastIndex())
}

func (l *log) matchTerm(i, term int) bool {
	if i > l.lastIndex() {
		return false
	}
	return l.ents[i].Term == term
}

func (l *log) maybeCommit(maxIndex, term int) bool {
	if maxIndex > l.commit && l.term(maxIndex) == term {
		l.commit = maxIndex
		return true
	}
	return false
}

func (l *log) nextEnts() (ents []Entry) {
	if l.commit > l.applied {
		ents = l.ents[l.applied+1 : l.commit+1]
		l.applied = l.commit
	}
	return ents
}
<|endoftext|>


<commit_before>package spot

import (
	"testing"
)

func TestBuildHardUrl(t *testing.T) {

	desc := "Passing in incorrect query param name returns error"
	expected := "HardSearch can only search for artist, track, or album. Found: song"
	params := map[string]string{
		"artist": "Billy Joel",
		"song":   "Big Shot",
	}
	url, err := BuildHardUrl(params, []string{"track"})
	if err.Error() != expected {
		fail(t, desc, expected, err.Error())
	}

	desc = "Normal search returns correct url"
	expected = "https://api.spotify.com/v1/search?q=artist:mariah+carey+track:always+be+my+baby+&type=track"
	params = map[string]string{
		"artist": "Mariah Carey",
		"track":  "always be my baby",
	}
	url, _ = BuildHardUrl(params, []string{"track"})
	if url != expected {
		fail(t, desc, expected, url)
	}

	desc = "Passing in incorrect type returns error"
	expected = "HardSearch can only search by type artist, track, album, or playlist. Found: film"
	url, err = BuildHardUrl(params, []string{"film", "playlist"})
	if err.Error() != expected {
		fail(t, desc, expected, err.Error())
	}

}

func fail(t *testing.T, desc, expected, got string) {
	t.Errorf("Testing %q | Expected: %q, Got %q", desc, expected, got)
}
<commit_msg>normal search with multiple types test<commit_after>package spot

import (
	"fmt"
	"testing"
)

func TestBuildHardUrl(t *testing.T) {

	desc := "Passing in incorrect query param name returns error"
	expected := "HardSearch can only search for artist, track, or album. Found: song"
	params := map[string]string{
		"artist": "Billy Joel",
		"song":   "Big Shot",
	}
	url, err := BuildHardUrl(params, []string{"track"})
	if err.Error() != expected {
		fail(t, desc, expected, err.Error())
	}

	desc = "Normal search returns correct url"
	expected = "https://api.spotify.com/v1/search?q=artist:mariah+carey+track:always+be+my+baby+&type=track"
	params = map[string]string{
		"artist": "Mariah Carey",
		"track":  "always be my baby",
	}
	url, _ = BuildHardUrl(params, []string{"track"})
	if url != expected {
		fail(t, desc, expected, url)
	}

	desc = "Normal search with mutltiple types returns correct url"
	expected = "https://api.spotify.com/v1/search?q=artist:mariah+carey+track:always+be+my+baby+&type=track,album"
	params = map[string]string{
		"artist": "Mariah Carey",
		"track":  "always be my baby",
	}
	url, _ = BuildHardUrl(params, []string{"track", "album"})
	if url != expected {
		fail(t, desc, expected, url)
		fmt.Println(err)
	}

	desc = "Passing in incorrect type returns error"
	expected = "HardSearch can only search by type artist, track, album, or playlist. Found: film"
	url, err = BuildHardUrl(params, []string{"film", "playlist"})
	if err.Error() != expected {
		fail(t, desc, expected, err.Error())
	}

}

func fail(t *testing.T, desc, expected, got string) {
	t.Errorf("Testing %q | Expected: %q, Got %q", desc, expected, got)
}
<|endoftext|>


<commit_before>package tnt

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestSelect(t *testing.T) {
	assert := assert.New(t)

	tarantoolConfig := `
    s = box.schema.space.create('tester', {id = 42})
    s:create_index('primary', {
        type = 'hash',
        parts = {1, 'NUM'}
    })
    t = s:insert({1})
    t = s:insert({2, 'Music'})
    t = s:insert({3, 'Length', 93})
    `

	box, err := NewBox(tarantoolConfig, nil)
	if !assert.NoError(err) {
		return
	}
	defer box.Close()

	// unkwnown user
	conn, err := box.Connect(nil)
	assert.NoError(err)
	assert.NotNil(conn)

	data, err := conn.Execute(&Select{
		Space: 42,
		Key:   3,
	})

	assert.NoError(err)
	assert.Equal([]interface{}{
		[]interface{}{
			uint32(0x3),
			"Length",
			uint32(0x5d),
		},
	}, data)

}

func BenchmarkSelectPack(b *testing.B) {
	d, _ := newPackData(42)

	for i := 0; i < b.N; i += 1 {
		(&Select{
			Key: 3,
		}).Pack(0, d)
	}
}
<commit_msg>checkpoint<commit_after>package tnt

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestSelect(t *testing.T) {
	assert := assert.New(t)

	tarantoolConfig := `
    s = box.schema.space.create('tester', {id = 42})
    s:create_index('primary', {
        type = 'hash',
        parts = {1, 'NUM'}
    })
    t = s:insert({1})
    t = s:insert({2, 'Music'})
    t = s:insert({3, 'Length', 93})
    `

	box, err := NewBox(tarantoolConfig, nil)
	if !assert.NoError(err) {
		return
	}
	defer box.Close()

	// unkwnown user
	conn, err := box.Connect(nil)
	assert.NoError(err)
	assert.NotNil(conn)

	data, err := conn.Execute(&Select{
		Space: 42,
		Key:   3,
	})

	assert.NoError(err)
	assert.Equal([]interface{}{
		[]interface{}{
			uint32(0x3),
			"Length",
			uint32(0x5d),
		},
	}, data)

}

func BenchmarkSelectPack(b *testing.B) {
	d, _ := newPackData(42)

	for i := 0; i < b.N; i += 1 {
		(&Select{Key: 3}).Pack(0, d)
	}
}
<|endoftext|>


<commit_before>package util

import (
	"bytes"
	"io"
)

const (
	defaultReaderBufSize = 4096
	minReaderBufferSize  = 16
)

// Type implementing a robust line reader.
type Reader struct {
	rd  io.Reader
	buf []byte
	err error
	p   int // points to first unscanned byte in buffer
	n   int // points to location after last byte in buffer
	idx int // points to first \n or \r in buffer
}

// Create new reader with default buffer size.
func NewReader(rd io.Reader) *Reader {
	return NewReaderSize(rd, defaultReaderBufSize)
}

// Create new reader with specified buffer size.
func NewReaderSize(rd io.Reader, size int) *Reader {
	if size < minReaderBufferSize {
		size = minReaderBufferSize
	}
	r := Reader{
		buf: make([]byte, size),
		rd:  rd,
		p:   0,
		n:   2,
		idx: 0,
	}
	r.buf[0] = '\r' // in case first line is empty
	r.buf[1] = '\n' //
	return &r
}

// Same as ReadLine(), but returns string instead of []byte.
// Result stays valid.
func (r *Reader) ReadLineString() (line string, err error) {
	b, e := r.ReadLine()
	return string(b), e
}

// Read single line from Reader, without EOL.
// EOL can be any of: \n \r \r\n \n\r.
// Last line without EOL is allowed.
// Result is only valid until next call to ReadLine() or ReadLineString()
func (r *Reader) ReadLine() (line []byte, err error) {

	// Sets r.idx to first \n or \r, or -1 if not found.
	scan := func() {
		end := r.n
		i1 := bytes.IndexByte(r.buf[r.p:end], '\n')
		if i1 >= 0 {
			end = r.p + i1
		}
		i2 := bytes.IndexByte(r.buf[r.p:end], '\r')
		if i2 >= 0 {
			r.idx = r.p + i2
		} else if i1 >= 0 {
			r.idx = r.p + i1
		} else {
			r.idx = -1
		}
	}

	// Fills buffer if no \n or \r found and no error yet,
	// and then rescans for first \n or \r.
	fill := func() {
		if r.idx < 0 && r.err == nil {
			if r.p > 0 {
				// make room
				if r.p < r.n {
					copy(r.buf, r.buf[r.p:r.n])
				}
				r.n -= r.p
				r.p = 0
			}
			var i int
			i, r.err = r.rd.Read(r.buf[r.n:])
			r.n += i
			scan()
		}
	}

	var lines [][]byte
	beginning := true
	for {

		fill()

		// if at beginning of line, skip EOL of previous line
		if beginning {
			var c byte
			for i := 0; i < 2; i++ {
				// 1 or 2 times \r or \n, but not \r\r or \n\n
				if r.idx == r.p && r.buf[r.p] != c {
					c = r.buf[r.p]
					r.p += 1
					scan() // reset r.idx
				} else {
					break
				}
			}
			fill()
			beginning = false
		}

		// if error and no more unscanned data, return saved parts if they exist, else return error
		if r.p == r.n && r.err != nil {
			if len(lines) > 0 {
				return buildline(lines, r.buf[0:0]), nil
			} else {
				return r.buf[0:0], r.err
			}
		}

		if r.p < r.n {
			if r.idx < 0 { // no EOL found
				buf := make([]byte, r.n-r.p)
				copy(buf, r.buf[r.p:r.n])
				lines = append(lines, buf)
				r.p = r.n
			} else { // EOL found
				p := r.p
				r.p = r.idx
				return buildline(lines, r.buf[p:r.p]), nil
			}
		}

	}
	panic("not reached")
}

func buildline(lines [][]byte, last []byte) []byte {
	if len(lines) == 0 {
		return last
	}

	i := len(last)
	for _, line := range lines {
		i += len(line)
	}
	buf := make([]byte, i)
	i = 0
	for _, line := range lines {
		copy(buf[i:], line)
		i += len(line)
	}
	copy(buf[i:], last)
	return buf
}
<commit_msg>ReadLine(): safety in fill()<commit_after>package util

import (
	"bytes"
	"io"
)

const (
	defaultReaderBufSize = 4096
	minReaderBufferSize  = 16
)

// Type implementing a robust line reader.
type Reader struct {
	rd  io.Reader
	buf []byte
	err error
	p   int // points to first unscanned byte in buffer
	n   int // points to location after last byte in buffer
	idx int // points to first \n or \r in buffer
}

// Create new reader with default buffer size.
func NewReader(rd io.Reader) *Reader {
	return NewReaderSize(rd, defaultReaderBufSize)
}

// Create new reader with specified buffer size.
func NewReaderSize(rd io.Reader, size int) *Reader {
	if size < minReaderBufferSize {
		size = minReaderBufferSize
	}
	r := Reader{
		buf: make([]byte, size),
		rd:  rd,
		p:   0,
		n:   2,
		idx: 0,
	}
	r.buf[0] = '\r' // in case first line is empty
	r.buf[1] = '\n' //
	return &r
}

// Same as ReadLine(), but returns string instead of []byte.
// Result stays valid.
func (r *Reader) ReadLineString() (line string, err error) {
	b, e := r.ReadLine()
	return string(b), e
}

// Read single line from Reader, without EOL.
// EOL can be any of: \n \r \r\n \n\r.
// Last line without EOL is allowed.
// Result is only valid until next call to ReadLine() or ReadLineString()
func (r *Reader) ReadLine() (line []byte, err error) {

	// Sets r.idx to first \n or \r, or -1 if not found.
	scan := func() {
		end := r.n
		i1 := bytes.IndexByte(r.buf[r.p:end], '\n')
		if i1 >= 0 {
			end = r.p + i1
		}
		i2 := bytes.IndexByte(r.buf[r.p:end], '\r')
		if i2 >= 0 {
			r.idx = r.p + i2
		} else if i1 >= 0 {
			r.idx = r.p + i1
		} else {
			r.idx = -1
		}
	}

	// Fills buffer if no \n or \r found and no error yet,
	// and then rescans for first \n or \r.
	fill := func() {
		if r.idx < 0 && r.err == nil {
			if r.p > 0 {
				// make room
				if r.p < r.n {
					copy(r.buf, r.buf[r.p:r.n])
				}
				r.n -= r.p
				r.p = 0
			}
			if r.n < len(r.buf) {
				var i int
				i, r.err = r.rd.Read(r.buf[r.n:])
				r.n += i
			}
			scan()
		}
	}

	var lines [][]byte
	beginning := true
	for {

		fill()

		// if at beginning of line, skip EOL of previous line
		if beginning {
			var c byte
			for i := 0; i < 2; i++ {
				// 1 or 2 times \r or \n, but not \r\r or \n\n
				if r.idx == r.p && r.buf[r.p] != c {
					c = r.buf[r.p]
					r.p += 1
					scan() // reset r.idx
				} else {
					break
				}
			}
			fill()
			beginning = false
		}

		// if error and no more unscanned data, return saved parts if they exist, else return error
		if r.p == r.n && r.err != nil {
			if len(lines) > 0 {
				return buildline(lines, r.buf[0:0]), nil
			} else {
				return r.buf[0:0], r.err
			}
		}

		if r.p < r.n {
			if r.idx < 0 { // no EOL found
				buf := make([]byte, r.n-r.p)
				copy(buf, r.buf[r.p:r.n])
				lines = append(lines, buf)
				r.p = r.n
			} else { // EOL found
				p := r.p
				r.p = r.idx
				return buildline(lines, r.buf[p:r.p]), nil
			}
		}

	}
	panic("not reached")
}

func buildline(lines [][]byte, last []byte) []byte {
	if len(lines) == 0 {
		return last
	}

	i := len(last)
	for _, line := range lines {
		i += len(line)
	}
	buf := make([]byte, i)
	i = 0
	for _, line := range lines {
		copy(buf[i:], line)
		i += len(line)
	}
	copy(buf[i:], last)
	return buf
}
<|endoftext|>


<commit_before>package util

import (
	"bytes"
	"io"
)

const (
	defaultReaderBufSize = 4096
	minReaderBufferSize  = 16
)

// Type implementing a robust line reader.
type Reader struct {
	rd  io.Reader
	buf []byte
	err error
	p   int // points to first unscanned byte in buffer
	n   int // points to location after last byte in buffer
}

// Create new reader with default buffer size.
func NewReader(rd io.Reader) *Reader {
	return NewReaderSize(rd, defaultReaderBufSize)
}

// Create new reader with specified buffer size.
func NewReaderSize(rd io.Reader, size int) *Reader {
	if size < minReaderBufferSize {
		size = minReaderBufferSize
	}
	return &Reader{
		buf: make([]byte, size),
		rd:  rd,
	}
}

// Same as ReadLine(), but returns string instead of []byte.
// Result stays valid.
func (r *Reader) ReadLineString() (line string, err error) {
	b, e := r.ReadLine()
	return string(b), e
}

// Read single line from Reader, without EOL.
// EOL can be any of: \n \r \r\n \n\r.
// Last line without EOL is allowed.
// Result is only valid until next call to ReadLine() or ReadLineString()
func (r *Reader) ReadLine() (line []byte, err error) {
	var lines [][]byte
	for {

		// Fill buffer if it is nearly empty, unless error was already received.
		// Part after the '||' is not necessary, but makes it (perhaps) more
		// efficient by avoiding the use of partial saves as much as possble.
		if r.n-r.p < 2 && r.err == nil ||
			r.p < r.n && r.err == nil && bytes.IndexByte(r.buf[r.p:r.n], '\n') < 0 && bytes.IndexByte(r.buf[r.p:r.n], '\r') < 0 {
			if r.p > 0 {
				// make room
				copy(r.buf, r.buf[r.p:r.n])
				r.n -= r.p
				r.p = 0
			}
			var i int
			i, r.err = r.rd.Read(r.buf[r.n:])
			r.n += i
		}

		// if at beginning of line, skip EOL of previous line
		if len(lines) == 0 {
			var c byte
			for i := 0; i < 2; i++ {
				// 1 or 2 times \r or \n, but not \r\r or \n\n
				if r.p < r.n && (r.buf[r.p] == '\n' || r.buf[r.p] == '\r') && r.buf[r.p] != c {
					c = r.buf[r.p]
					r.p += 1
				} else {
					break
				}
			}
		}

		// if error and no more unscanned data, return saved parts if they exist, else return error
		if r.p == r.n && r.err != nil {
			if len(lines) > 0 {
				return buildline(lines, r.buf[0:0]), nil
			} else {
				return r.buf[0:0], r.err
			}
		}

		if r.p < r.n {
			// find next EOL, can start with \n or \r
			i := bytes.IndexByte(r.buf[r.p:r.n], '\n')
			if i < 0 {
				i = r.n
			}
			j := bytes.IndexByte(r.buf[r.p:r.n], '\r')
			if j < 0 {
				j = r.n
			}
			if j < i {
				i = j
			}
			if i == r.n { // no EOL found
				buf := make([]byte, r.n-r.p)
				copy(buf, r.buf[r.p:r.n])
				lines = append(lines, buf)
				r.p = r.n
			} else { // EOL found
				p := r.p
				r.p += i
				return buildline(lines, r.buf[p:r.p]), nil
			}
		}

	}
	panic("not reached")
}

func buildline(lines [][]byte, last []byte) []byte {
	if len(lines) == 0 {
		return last
	}

	i := len(last)
	for _, line := range lines {
		i += len(line)
	}
	buf := make([]byte, i)
	i = 0
	for _, line := range lines {
		copy(buf[i:], line)
		i += len(line)
	}
	copy(buf[i:], last)
	return buf
}
<commit_msg>Bug fix in ReadLine(): don't drop initial empty line<commit_after>package util

import (
	"bytes"
	"io"
)

const (
	defaultReaderBufSize = 4096
	minReaderBufferSize  = 16
)

// Type implementing a robust line reader.
type Reader struct {
	rd  io.Reader
	buf []byte
	err error
	p   int // points to first unscanned byte in buffer
	n   int // points to location after last byte in buffer
}

// Create new reader with default buffer size.
func NewReader(rd io.Reader) *Reader {
	return NewReaderSize(rd, defaultReaderBufSize)
}

// Create new reader with specified buffer size.
func NewReaderSize(rd io.Reader, size int) *Reader {
	if size < minReaderBufferSize {
		size = minReaderBufferSize
	}
	r := Reader{
		buf: make([]byte, size),
		rd:  rd,
		n:   2,
	}
	r.buf[0] = '\r' // in case first line is empty
	r.buf[1] = '\n' //
	return &r
}

// Same as ReadLine(), but returns string instead of []byte.
// Result stays valid.
func (r *Reader) ReadLineString() (line string, err error) {
	b, e := r.ReadLine()
	return string(b), e
}

// Read single line from Reader, without EOL.
// EOL can be any of: \n \r \r\n \n\r.
// Last line without EOL is allowed.
// Result is only valid until next call to ReadLine() or ReadLineString()
func (r *Reader) ReadLine() (line []byte, err error) {
	var lines [][]byte
	beginning := true
	for {

		// Fill buffer if it is nearly empty, unless error was already received.
		// Part after the '||' is not necessary, but makes it (perhaps) more
		// efficient by avoiding the use of partial saves as much as possble.
		if r.n-r.p < 2 && r.err == nil ||
			r.p < r.n && r.err == nil && bytes.IndexByte(r.buf[r.p:r.n], '\n') < 0 && bytes.IndexByte(r.buf[r.p:r.n], '\r') < 0 {
			if r.p > 0 {
				// make room
				copy(r.buf, r.buf[r.p:r.n])
				r.n -= r.p
				r.p = 0
			}
			var i int
			i, r.err = r.rd.Read(r.buf[r.n:])
			r.n += i
		}

		// if at beginning of line, skip EOL of previous line
		if beginning {
			var c byte
			for i := 0; i < 2; i++ {
				// 1 or 2 times \r or \n, but not \r\r or \n\n
				if r.p < r.n && (r.buf[r.p] == '\n' || r.buf[r.p] == '\r') && r.buf[r.p] != c {
					c = r.buf[r.p]
					r.p += 1
				} else {
					break
				}
			}
			beginning = false
		}

		// if error and no more unscanned data, return saved parts if they exist, else return error
		if r.p == r.n && r.err != nil {
			if len(lines) > 0 {
				return buildline(lines, r.buf[0:0]), nil
			} else {
				return r.buf[0:0], r.err
			}
		}

		if r.p < r.n {
			// find next EOL, can start with \n or \r
			i := bytes.IndexByte(r.buf[r.p:r.n], '\n')
			if i < 0 {
				i = r.n
			}
			j := bytes.IndexByte(r.buf[r.p:r.n], '\r')
			if j < 0 {
				j = r.n
			}
			if j < i {
				i = j
			}
			if i == r.n { // no EOL found
				buf := make([]byte, r.n-r.p)
				copy(buf, r.buf[r.p:r.n])
				lines = append(lines, buf)
				r.p = r.n
			} else { // EOL found
				p := r.p
				r.p += i
				return buildline(lines, r.buf[p:r.p]), nil
			}
		}

	}
	panic("not reached")
}

func buildline(lines [][]byte, last []byte) []byte {
	if len(lines) == 0 {
		return last
	}

	i := len(last)
	for _, line := range lines {
		i += len(line)
	}
	buf := make([]byte, i)
	i = 0
	for _, line := range lines {
		copy(buf[i:], line)
		i += len(line)
	}
	copy(buf[i:], last)
	return buf
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/bitly/go-nsq"
	"github.com/bitly/nsq/util"
	"github.com/bmizerany/assert"
	"github.com/mreiferson/go-snappystream"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"testing"
	"time"
)

func TestStats(t *testing.T) {
	log.SetOutput(ioutil.Discard)
	defer log.SetOutput(os.Stdout)

	options := NewNSQDOptions()
	tcpAddr, _, nsqd := mustStartNSQD(options)
	defer nsqd.Exit()

	topicName := "test_stats" + strconv.Itoa(int(time.Now().Unix()))
	topic := nsqd.GetTopic(topicName)
	msg := nsq.NewMessage(<-nsqd.idChan, []byte("test body"))
	topic.PutMessage(msg)

	conn, err := mustConnectNSQD(tcpAddr)
	assert.Equal(t, err, nil)

	identify(t, conn)
	sub(t, conn, topicName, "ch")

	stats := nsqd.getStats()
	assert.Equal(t, len(stats), 1)
	assert.Equal(t, len(stats[0].Channels), 1)
	assert.Equal(t, len(stats[0].Channels[0].Clients), 1)
	log.Printf("stats: %+v", stats)
}

func TestClientAttributes(t *testing.T) {
	log.SetOutput(ioutil.Discard)
	defer log.SetOutput(os.Stdout)

	userAgent := "Test User Agent"

	*verbose = true
	options := NewNSQDOptions()
	options.SnappyEnabled = true
	tcpAddr, httpAddr, nsqd := mustStartNSQD(options)
	defer nsqd.Exit()

	conn, err := mustConnectNSQD(tcpAddr)
	assert.Equal(t, err, nil)

	data := identifyFeatureNegotiation(t, conn, map[string]interface{}{"snappy": true, "user_agent": userAgent})
	r := struct {
		Snappy    bool   `json:"snappy"`
		UserAgent string `json:"user_agent"`
	}{}
	err = json.Unmarshal(data, &r)
	assert.Equal(t, err, nil)
	assert.Equal(t, r.Snappy, true)

	compressConn := snappystream.NewReader(conn, snappystream.SkipVerifyChecksum)

	w := snappystream.NewWriter(conn)

	rw := readWriter{compressConn, w}

	topicName := "test_client_attributes" + strconv.Itoa(int(time.Now().Unix()))
	sub(t, rw, topicName, "ch")

	err = nsq.Ready(1).Write(rw)
	assert.Equal(t, err, nil)

	testUrl := fmt.Sprintf("http://127.0.0.1:%d/stats?format=json", httpAddr.Port)

	statsData, err := util.ApiRequest(testUrl)
	if err != nil {
		t.Fatalf(err.Error())
	}
	client := statsData.Get("topics").GetIndex(0).Get("channels").GetIndex(0).Get("clients").GetIndex(0)
	assert.Equal(t, client.Get("user_agent").MustString(), userAgent)
	assert.Equal(t, client.Get("snappy").MustBool(), true)
}
<commit_msg>nsqd: cleanup TestClientAttributes<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/bitly/go-nsq"
	"github.com/bitly/nsq/util"
	"github.com/bmizerany/assert"
	"github.com/mreiferson/go-snappystream"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"testing"
	"time"
)

func TestStats(t *testing.T) {
	log.SetOutput(ioutil.Discard)
	defer log.SetOutput(os.Stdout)

	options := NewNSQDOptions()
	tcpAddr, _, nsqd := mustStartNSQD(options)
	defer nsqd.Exit()

	topicName := "test_stats" + strconv.Itoa(int(time.Now().Unix()))
	topic := nsqd.GetTopic(topicName)
	msg := nsq.NewMessage(<-nsqd.idChan, []byte("test body"))
	topic.PutMessage(msg)

	conn, err := mustConnectNSQD(tcpAddr)
	assert.Equal(t, err, nil)

	identify(t, conn)
	sub(t, conn, topicName, "ch")

	stats := nsqd.getStats()
	assert.Equal(t, len(stats), 1)
	assert.Equal(t, len(stats[0].Channels), 1)
	assert.Equal(t, len(stats[0].Channels[0].Clients), 1)
	log.Printf("stats: %+v", stats)
}

func TestClientAttributes(t *testing.T) {
	log.SetOutput(ioutil.Discard)
	defer log.SetOutput(os.Stdout)

	userAgent := "Test User Agent"

	*verbose = true
	options := NewNSQDOptions()
	options.SnappyEnabled = true
	tcpAddr, httpAddr, nsqd := mustStartNSQD(options)
	defer nsqd.Exit()

	conn, err := mustConnectNSQD(tcpAddr)
	assert.Equal(t, err, nil)

	data := identifyFeatureNegotiation(t, conn, map[string]interface{}{"snappy": true, "user_agent": userAgent})
	resp := struct {
		Snappy    bool   `json:"snappy"`
		UserAgent string `json:"user_agent"`
	}{}
	err = json.Unmarshal(data, &resp)
	assert.Equal(t, err, nil)
	assert.Equal(t, resp.Snappy, true)

	r := snappystream.NewReader(conn, snappystream.SkipVerifyChecksum)
	w := snappystream.NewWriter(conn)

	topicName := "test_client_attributes" + strconv.Itoa(int(time.Now().Unix()))
	sub(t, readWriter{r, w}, topicName, "ch")

	testUrl := fmt.Sprintf("http://127.0.0.1:%d/stats?format=json", httpAddr.Port)

	statsData, err := util.ApiRequest(testUrl)
	if err != nil {
		t.Fatalf(err.Error())
	}
	client := statsData.Get("topics").GetIndex(0).Get("channels").GetIndex(0).Get("clients").GetIndex(0)
	assert.Equal(t, client.Get("user_agent").MustString(), userAgent)
	assert.Equal(t, client.Get("snappy").MustBool(), true)
}
<|endoftext|>


<commit_before>package oauth1

import (
	"crypto"
	crand "crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"time"
)

// Out-Of-Band mode, used for applications that do not have
// a callback URL, such as mobile phones or command-line
// utilities.
const OOB = "oob"

// Consumer represents a website or application that uses the
// OAuth 1.0a protocol to access protected resources on behalf
// of a User.
type Consumer struct {
	// A value used by the Consumer to identify itself
	// to the Service Provider.
	ConsumerKey string

	// A secret used by the Consumer to establish
	// ownership of the Consumer Key.
	ConsumerSecret string

	// A path to the private pem key used to sign request
	ConsumerPrivateKeyPem string

	// An absolute URL to which the Service Provider will redirect
	// the User back when the Obtaining User Authorization step
	// is completed.
	//
	// If the Consumer is unable to receive callbacks or a callback
	// URL has been established via other means, the parameter
	// value MUST be set to oob (case sensitive), to indicate
	// an out-of-band configuration.
	CallbackURL string

	// The URL used to obtain an unauthorized
	// Request Token.
	RequestTokenURL string

	// The URL used to obtain User authorization
	// for Consumer access.
	AccessTokenURL string

	// The URL used to exchange the User-authorized
	// Request Token for an Access Token.
	AuthorizationURL string
}

func (c *Consumer) RequestToken() (*RequestToken, error) {

	// create the http request to fetch a Request Token.
	requestTokenUrl, _ := url.Parse(c.RequestTokenURL)
	req := http.Request{
		URL:        requestTokenUrl,
		Method:     "POST",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Close:      true,
	}

	// sign the request
	err := c.SignParams(&req, nil, map[string]string{"oauth_callback": c.CallbackURL})
	if err != nil {
		return nil, err
	}

	// make the http request and get the response
	resp, err := http.DefaultClient.Do(&req)
	if err != nil {
		return nil, err
	}

	// parse the Request's Body
	requestToken, err := ParseRequestToken(resp.Body)
	if err != nil {
		return nil, err
	}

	return requestToken, nil
}

// AuthorizeRedirect constructs the request URL that should be used
// to redirect the User to verify User identify and consent.
func (c *Consumer) AuthorizeRedirect(t *RequestToken) (string, error) {
	redirect, err := url.Parse(c.AuthorizationURL)
	if err != nil {
		return "", err
	}

	params := make(url.Values)
	params.Add("oauth_token", t.token)
	redirect.RawQuery = params.Encode()

	u := redirect.String()
	if strings.HasPrefix(u, "https://bitbucket.org/%21api/") {
		u = strings.Replace(u, "/%21api/", "/!api/", -1)
	}

	return u, nil
}

func (c *Consumer) AuthorizeToken(t *RequestToken, verifier string) (*AccessToken, error) {

	// create the http request to fetch a Request Token.
	accessTokenUrl, _ := url.Parse(c.AccessTokenURL)
	req := http.Request{
		URL:        accessTokenUrl,
		Method:     "POST",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Close:      true,
	}

	// sign the request
	err := c.SignParams(&req, t, map[string]string{"oauth_verifier": verifier})
	if err != nil {
		return nil, err
	}

	// make the http request and get the response
	resp, err := http.DefaultClient.Do(&req)
	if err != nil {
		return nil, err
	}

	// parse the Request's Body
	accessToken, err := ParseAccessToken(resp.Body)
	if err != nil {
		return nil, err
	}

	return accessToken, nil
}

// Sign will sign an http.Request using the provided token.
func (c *Consumer) Sign(req *http.Request, token Token) error {
	return c.SignParams(req, token, nil)
}

// Sign will sign an http.Request using the provided token, and additional
// parameters.
func (c *Consumer) SignParams(req *http.Request, token Token, params map[string]string) error {

	// ensure the parameter map is not nil
	if params == nil {
		params = map[string]string{}
	}

	// ensure default parameters are set
	//params["oauth_token"] = token.Token()
	params["oauth_consumer_key"] = c.ConsumerKey
	params["oauth_nonce"] = nonce()
	params["oauth_signature_method"] = "RSA-SHA1"
	params["oauth_timestamp"] = timestamp()
	params["oauth_version"] = "1.0"

	// we'll need to sign any form values?
	if req.Form != nil {
		for k, _ := range req.Form {
			params[k] = req.Form.Get(k)
		}
	}

	// we'll also need to sign any URL parameter
	queryParams := req.URL.Query()
	for k, _ := range queryParams {
		params[k] = queryParams.Get(k)
	}

	//var tokenSecret string
	if token != nil {
		//tokenSecret = token.Secret()
		params["oauth_token"] = token.Token()
	}

	// create the oauth signature
	//key := escape(c.ConsumerSecret) + "&" + escape(tokenSecret)
	key := c.ConsumerPrivateKeyPem
	url := fmt.Sprintf("%s://%s%s", req.URL.Scheme, req.URL.Host, req.URL.Path)
	base := requestString(req.Method, url, params)
	params["oauth_signature"] = sign(base, key)

	//HACK: we were previously including params in the Authorization
	//      header that shouldn't be. so for now, we'll filter
	//authStringParams := map[string]string{}
	//for k,v := range params {
	//	if strings.HasPrefix(k, "oauth_") {
	//		authStringParams[k]=v
	//	}
	//}

	// ensure the http.Request's Header is not nil
	if req.Header == nil {
		req.Header = http.Header{}
	}

	// add the authorization header string
	req.Header.Add("Authorization", authorizationString(params)) //params))

	// ensure the appropriate content-type is set for POST,
	// assuming the field is not populated
	if (req.Method == "POST" || req.Method == "PUT") && len(req.Header.Get("Content-Type")) == 0 {
		req.Header.Set("Content-Type", "application/json")
	}

	return nil
}

// -----------------------------------------------------------------------------
// Private Helper Functions

// Nonce generator, seeded with current time
var nonceGenerator = rand.New(rand.NewSource(time.Now().Unix()))

// Nonce generates a random string. Nonce's are uniquely generated
// for each request.
func nonce() string {
	return strconv.FormatInt(nonceGenerator.Int63(), 10)
}

// Timestamp generates a timestamp, expressed in the number of seconds
// since January 1, 1970 00:00:00 GMT.
func timestamp() string {
	return strconv.FormatInt(time.Now().Unix(), 10)
}

// Generates an RSA SHA1 Signature for an OAuth1.0a request.
func sign(message, key string) string {
	privateKeyBytes, _ := ioutil.ReadFile(key)
	block, _ := pem.Decode(privateKeyBytes)
	privateInterface, _ := x509.ParsePKCS8PrivateKey(block.Bytes)
	privateKey, _ := privateInterface.(*rsa.PrivateKey)

	hashfun := sha1.New()
	hashfun.Write([]byte(message))
	rawsignature := hashfun.Sum(nil)

	cipher, _ := rsa.SignPKCS1v15(crand.Reader, privateKey, crypto.SHA1,
		rawsignature)

	base64signature := make([]byte, base64.StdEncoding.EncodedLen(len(cipher)))
	base64.StdEncoding.Encode(base64signature, cipher)

	return string(base64signature)
}

// Gets the default set of OAuth1.0a headers.
func headers(consumerKey string) map[string]string {
	return map[string]string{
		"oauth_consumer_key":     consumerKey,
		"oauth_nonce":            nonce(),
		"oauth_signature_method": "RSA-SHA1",
		"oauth_timestamp":        timestamp(),
		"oauth_version":          "1.0",
	}
}

func requestString(method string, uri string, params map[string]string) string {

	// loop through params, add keys to map
	var keys []string
	for key, _ := range params {
		keys = append(keys, key)
	}

	// sort the array of header keys
	sort.StringSlice(keys).Sort()

	// create the signed string
	result := method + "&" + escape(uri)

	// loop through sorted params and append to the string
	for pos, key := range keys {
		if pos == 0 {
			result += "&"
		} else {
			result += escape("&")
		}

		result += escape(fmt.Sprintf("%s=%s", key, escape(params[key])))
	}

	return result
}

func authorizationString(params map[string]string) string {

	// loop through params, add keys to map
	var keys []string
	for key, _ := range params {
		keys = append(keys, key)
	}

	// sort the array of header keys
	sort.StringSlice(keys).Sort()

	// create the signed string
	var str string
	var cnt = 0

	// loop through sorted params and append to the string
	for _, key := range keys {

		// we previously encoded all params (url params, form data & oauth params)
		// but for the authorization string we should only encode the oauth params
		if !strings.HasPrefix(key, "oauth_") {
			continue
		}

		if cnt > 0 {
			str += ","
		}

		str += fmt.Sprintf("%s=%q", key, escape(params[key]))
		cnt++
	}

	return fmt.Sprintf("OAuth %s", str)
}

func escape(s string) string {
	t := make([]byte, 0, 3*len(s))
	for i := 0; i < len(s); i++ {
		c := s[i]
		if isEscapable(c) {
			t = append(t, '%')
			t = append(t, "0123456789ABCDEF"[c>>4])
			t = append(t, "0123456789ABCDEF"[c&15])
		} else {
			t = append(t, s[i])
		}
	}
	return string(t)
}

func isEscapable(b byte) bool {
	return !('A' <= b && b <= 'Z' || 'a' <= b && b <= 'z' || '0' <= b && b <= '9' || b == '-' || b == '.' || b == '_' || b == '~')

}
<commit_msg>consumer logs fatal now on missing key file<commit_after>package oauth1

import (
	"crypto"
	crand "crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"net/url"
	"sort"
	"strconv"
	"strings"
	"time"
)

// Out-Of-Band mode, used for applications that do not have
// a callback URL, such as mobile phones or command-line
// utilities.
const OOB = "oob"

// Consumer represents a website or application that uses the
// OAuth 1.0a protocol to access protected resources on behalf
// of a User.
type Consumer struct {
	// A value used by the Consumer to identify itself
	// to the Service Provider.
	ConsumerKey string

	// A secret used by the Consumer to establish
	// ownership of the Consumer Key.
	ConsumerSecret string

	// A path to the private pem key used to sign request
	ConsumerPrivateKeyPem string

	// An absolute URL to which the Service Provider will redirect
	// the User back when the Obtaining User Authorization step
	// is completed.
	//
	// If the Consumer is unable to receive callbacks or a callback
	// URL has been established via other means, the parameter
	// value MUST be set to oob (case sensitive), to indicate
	// an out-of-band configuration.
	CallbackURL string

	// The URL used to obtain an unauthorized
	// Request Token.
	RequestTokenURL string

	// The URL used to obtain User authorization
	// for Consumer access.
	AccessTokenURL string

	// The URL used to exchange the User-authorized
	// Request Token for an Access Token.
	AuthorizationURL string
}

func (c *Consumer) RequestToken() (*RequestToken, error) {

	// create the http request to fetch a Request Token.
	requestTokenUrl, _ := url.Parse(c.RequestTokenURL)
	req := http.Request{
		URL:        requestTokenUrl,
		Method:     "POST",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Close:      true,
	}

	// sign the request
	err := c.SignParams(&req, nil, map[string]string{"oauth_callback": c.CallbackURL})
	if err != nil {
		return nil, err
	}

	// make the http request and get the response
	resp, err := http.DefaultClient.Do(&req)
	if err != nil {
		return nil, err
	}

	// parse the Request's Body
	requestToken, err := ParseRequestToken(resp.Body)
	if err != nil {
		return nil, err
	}

	return requestToken, nil
}

// AuthorizeRedirect constructs the request URL that should be used
// to redirect the User to verify User identify and consent.
func (c *Consumer) AuthorizeRedirect(t *RequestToken) (string, error) {
	redirect, err := url.Parse(c.AuthorizationURL)
	if err != nil {
		return "", err
	}

	params := make(url.Values)
	params.Add("oauth_token", t.token)
	redirect.RawQuery = params.Encode()

	u := redirect.String()
	if strings.HasPrefix(u, "https://bitbucket.org/%21api/") {
		u = strings.Replace(u, "/%21api/", "/!api/", -1)
	}

	return u, nil
}

func (c *Consumer) AuthorizeToken(t *RequestToken, verifier string) (*AccessToken, error) {

	// create the http request to fetch a Request Token.
	accessTokenUrl, _ := url.Parse(c.AccessTokenURL)
	req := http.Request{
		URL:        accessTokenUrl,
		Method:     "POST",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Close:      true,
	}

	// sign the request
	err := c.SignParams(&req, t, map[string]string{"oauth_verifier": verifier})
	if err != nil {
		return nil, err
	}

	// make the http request and get the response
	resp, err := http.DefaultClient.Do(&req)
	if err != nil {
		return nil, err
	}

	// parse the Request's Body
	accessToken, err := ParseAccessToken(resp.Body)
	if err != nil {
		return nil, err
	}

	return accessToken, nil
}

// Sign will sign an http.Request using the provided token.
func (c *Consumer) Sign(req *http.Request, token Token) error {
	return c.SignParams(req, token, nil)
}

// Sign will sign an http.Request using the provided token, and additional
// parameters.
func (c *Consumer) SignParams(req *http.Request, token Token, params map[string]string) error {

	// ensure the parameter map is not nil
	if params == nil {
		params = map[string]string{}
	}

	// ensure default parameters are set
	//params["oauth_token"] = token.Token()
	params["oauth_consumer_key"] = c.ConsumerKey
	params["oauth_nonce"] = nonce()
	params["oauth_signature_method"] = "RSA-SHA1"
	params["oauth_timestamp"] = timestamp()
	params["oauth_version"] = "1.0"

	// we'll need to sign any form values?
	if req.Form != nil {
		for k, _ := range req.Form {
			params[k] = req.Form.Get(k)
		}
	}

	// we'll also need to sign any URL parameter
	queryParams := req.URL.Query()
	for k, _ := range queryParams {
		params[k] = queryParams.Get(k)
	}

	//var tokenSecret string
	if token != nil {
		//tokenSecret = token.Secret()
		params["oauth_token"] = token.Token()
	}

	// create the oauth signature
	//key := escape(c.ConsumerSecret) + "&" + escape(tokenSecret)
	key := c.ConsumerPrivateKeyPem
	url := fmt.Sprintf("%s://%s%s", req.URL.Scheme, req.URL.Host, req.URL.Path)
	base := requestString(req.Method, url, params)
	params["oauth_signature"] = sign(base, key)

	//HACK: we were previously including params in the Authorization
	//      header that shouldn't be. so for now, we'll filter
	//authStringParams := map[string]string{}
	//for k,v := range params {
	//	if strings.HasPrefix(k, "oauth_") {
	//		authStringParams[k]=v
	//	}
	//}

	// ensure the http.Request's Header is not nil
	if req.Header == nil {
		req.Header = http.Header{}
	}

	// add the authorization header string
	req.Header.Add("Authorization", authorizationString(params)) //params))

	// ensure the appropriate content-type is set for POST,
	// assuming the field is not populated
	if (req.Method == "POST" || req.Method == "PUT") && len(req.Header.Get("Content-Type")) == 0 {
		req.Header.Set("Content-Type", "application/json")
	}

	return nil
}

// -----------------------------------------------------------------------------
// Private Helper Functions

// Nonce generator, seeded with current time
var nonceGenerator = rand.New(rand.NewSource(time.Now().Unix()))

// Nonce generates a random string. Nonce's are uniquely generated
// for each request.
func nonce() string {
	return strconv.FormatInt(nonceGenerator.Int63(), 10)
}

// Timestamp generates a timestamp, expressed in the number of seconds
// since January 1, 1970 00:00:00 GMT.
func timestamp() string {
	return strconv.FormatInt(time.Now().Unix(), 10)
}

// Generates an RSA SHA1 Signature for an OAuth1.0a request.
func sign(message, key string) string {
	privateKeyBytes, err := ioutil.ReadFile(key)
	if err != nil {
		log.Fatal("Issue reading key: ", key)
	}
	block, _ := pem.Decode(privateKeyBytes)
	privateInterface, _ := x509.ParsePKCS8PrivateKey(block.Bytes)
	privateKey, _ := privateInterface.(*rsa.PrivateKey)

	hashfun := sha1.New()
	hashfun.Write([]byte(message))
	rawsignature := hashfun.Sum(nil)

	cipher, _ := rsa.SignPKCS1v15(crand.Reader, privateKey, crypto.SHA1,
		rawsignature)

	base64signature := make([]byte, base64.StdEncoding.EncodedLen(len(cipher)))
	base64.StdEncoding.Encode(base64signature, cipher)

	return string(base64signature)
}

// Gets the default set of OAuth1.0a headers.
func headers(consumerKey string) map[string]string {
	return map[string]string{
		"oauth_consumer_key":     consumerKey,
		"oauth_nonce":            nonce(),
		"oauth_signature_method": "RSA-SHA1",
		"oauth_timestamp":        timestamp(),
		"oauth_version":          "1.0",
	}
}

func requestString(method string, uri string, params map[string]string) string {

	// loop through params, add keys to map
	var keys []string
	for key, _ := range params {
		keys = append(keys, key)
	}

	// sort the array of header keys
	sort.StringSlice(keys).Sort()

	// create the signed string
	result := method + "&" + escape(uri)

	// loop through sorted params and append to the string
	for pos, key := range keys {
		if pos == 0 {
			result += "&"
		} else {
			result += escape("&")
		}

		result += escape(fmt.Sprintf("%s=%s", key, escape(params[key])))
	}

	return result
}

func authorizationString(params map[string]string) string {

	// loop through params, add keys to map
	var keys []string
	for key, _ := range params {
		keys = append(keys, key)
	}

	// sort the array of header keys
	sort.StringSlice(keys).Sort()

	// create the signed string
	var str string
	var cnt = 0

	// loop through sorted params and append to the string
	for _, key := range keys {

		// we previously encoded all params (url params, form data & oauth params)
		// but for the authorization string we should only encode the oauth params
		if !strings.HasPrefix(key, "oauth_") {
			continue
		}

		if cnt > 0 {
			str += ","
		}

		str += fmt.Sprintf("%s=%q", key, escape(params[key]))
		cnt++
	}

	return fmt.Sprintf("OAuth %s", str)
}

func escape(s string) string {
	t := make([]byte, 0, 3*len(s))
	for i := 0; i < len(s); i++ {
		c := s[i]
		if isEscapable(c) {
			t = append(t, '%')
			t = append(t, "0123456789ABCDEF"[c>>4])
			t = append(t, "0123456789ABCDEF"[c&15])
		} else {
			t = append(t, s[i])
		}
	}
	return string(t)
}

func isEscapable(b byte) bool {
	return !('A' <= b && b <= 'Z' || 'a' <= b && b <= 'z' || '0' <= b && b <= '9' || b == '-' || b == '.' || b == '_' || b == '~')

}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Jeevanandam M (https://github.com/jeevatkm)
// resty source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

package log

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/go-aah/config"
	"github.com/go-aah/essentials"
)

// Receiver represents aah logger object that statisfy console, file, logging
// and Logging Stats. Each logging operation makes a single call to the
// Writer's Write method. `Receiver` guarantees serialize access and
// it can be used from multiple goroutines like Go standard logger.
type Receiver struct {
	Config *config.Config
	Type   string
	Flags  *[]FlagPart
	Format FormatterFunc

	m          sync.Mutex
	level      Level
	out        io.Writer
	stats      *ReceiverStats
	isFileInfo bool
	isLineInfo bool
	isUTC      bool

	// Console Receiver
	isColor bool

	// File Receiver
	isClosed bool
	rotate   string
	openDay  int
	maxSize  int64
	maxLines int64
}

// Output formats the give log inputs, caller info and writes to console
func (r *Receiver) Output(entry *Entry) error {
	if r.Closed() {
		return ErrWriterIsClosed
	}

	if r.isFileInfo || r.isLineInfo {
		entry.File, entry.Line = fetchCallerInfo(3)
	}

	r.m.Lock()
	defer r.m.Unlock()

	// Check log rotation is required
	if r.isRotateRequired() {
		if err := r.rotateFile(); err != nil {
			return err
		}
	}

	// format the log entry message as per pattern
	buf, err := r.Format(r.Flags, entry, r.isColor)
	if err != nil {
		return err
	}

	// writes bytes into writer
	size, err := r.out.Write(*buf)
	if err != nil {
		return err
	}

	// calculate receiver stats
	if r.stats != nil {
		r.stats.bytes += int64(size)
		r.stats.lines++
	}

	return nil
}

// Stats returns current logger statistics like number of lines written,
// number of bytes written, etc.
func (r *Receiver) Stats() *ReceiverStats {
	return r.stats
}

// Close closes the log writer. It cannot be used after this operation
func (r *Receiver) Close() {
	if r.isClosed {
		return
	}

	if out, ok := r.out.(io.Closer); ok {
		r.isClosed = true
		_ = out.Close()
	}
}

// Closed returns true if the logger was previously closed
func (r *Receiver) Closed() bool {
	return r.isClosed
}

// SetPattern sets the pattern to log entry format
func (r *Receiver) SetPattern(pattern string) error {
	r.m.Lock()
	defer r.m.Unlock()
	flags, err := parseFlag(pattern)
	if err != nil {
		return err
	}
	r.Flags = flags

	return nil
}

func (r *Receiver) isFileReceiver() bool {
	return r.Type == "FILE"
}

// Error logs message as `LevelError`
func (r *Receiver) Error(v ...interface{}) {
	if r.level >= LevelError {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelError,
			Values: v,
		})
	}
}

// Errorf logs message as `LevelError`
func (r *Receiver) Errorf(format string, v ...interface{}) {
	if r.level >= LevelError {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelError,
			Format: format,
			Values: v,
		})
	}
}

// Warn logs message as `LevelWarn`
func (r *Receiver) Warn(v ...interface{}) {
	if r.level >= LevelWarn {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelWarn,
			Values: v,
		})
	}
}

// Warnf logs message as `LevelWarn`
func (r *Receiver) Warnf(format string, v ...interface{}) {
	if r.level >= LevelWarn {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelWarn,
			Format: format,
			Values: v,
		})
	}
}

// Info logs message as `LevelInfo`
func (r *Receiver) Info(v ...interface{}) {
	if r.level >= LevelInfo {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelInfo,
			Values: v,
		})
	}
}

// Infof logs message as `LevelInfo`
func (r *Receiver) Infof(format string, v ...interface{}) {
	if r.level >= LevelInfo {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelInfo,
			Format: format,
			Values: v,
		})
	}
}

// Debug logs message as `LevelDebug`
func (r *Receiver) Debug(v ...interface{}) {
	if r.level >= LevelDebug {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelDebug,
			Values: v,
		})
	}
}

// Debugf logs message as `LevelDebug`
func (r *Receiver) Debugf(format string, v ...interface{}) {
	if r.level >= LevelDebug {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelDebug,
			Format: format,
			Values: v,
		})
	}
}

// Trace logs message as `LevelTrace`
func (r *Receiver) Trace(v ...interface{}) {
	if r.level >= LevelTrace {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelTrace,
			Values: v,
		})
	}
}

// Tracef logs message as `LevelTrace`
func (r *Receiver) Tracef(format string, v ...interface{}) {
	if r.level >= LevelTrace {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelTrace,
			Format: format,
			Values: v,
		})
	}
}

// unexported methods

func (r *Receiver) openFile() error {
	if !r.isFileReceiver() {
		return nil
	}

	name := r.fileName()
	dir := filepath.Dir(name)
	_ = ess.MkDirAll(dir)

	file, err := os.OpenFile(name, os.O_CREATE|os.O_APPEND|os.O_WRONLY, filePermission)
	if err != nil {
		return err
	}

	fileStat, err := file.Stat()
	if err != nil {
		return err

	}

	r.isClosed = false
	r.setOpenDay()
	r.stats.bytes = fileStat.Size()
	r.stats.lines = int64(ess.LineCntr(file))
	r.out = file

	return nil
}

func (r *Receiver) fileName() string {
	return r.Config.StringDefault("file", "aah-log-file.log")
}

func (r *Receiver) backupFileName() string {
	name := r.fileName()
	dir := filepath.Dir(name)
	fileName := filepath.Base(name)
	ext := filepath.Ext(fileName)
	baseName := strings.TrimSuffix(fileName, ext)

	t := time.Now()
	if r.isUTC {
		t = t.UTC()
	}

	return filepath.Join(dir, fmt.Sprintf("%s-%s%s", baseName, t.Format(BackupTimeFormat), ext))
}

func (r *Receiver) setOpenDay() {
	if r.isUTC {
		r.openDay = time.Now().UTC().Day()
	} else {
		r.openDay = time.Now().Day()
	}
}

func (r *Receiver) isRotateRequired() bool {
	if !r.isFileReceiver() {
		return false
	}

	switch r.rotate {
	case "daily":
		if r.isUTC {
			return time.Now().UTC().Day() != r.openDay
		}
		return time.Now().Day() != r.openDay
	case "lines":
		return r.maxLines != 0 && r.stats.lines >= r.maxLines
	case "size":
		return r.maxSize != 0 && r.stats.bytes >= r.maxSize
	}

	return false
}

func (r *Receiver) rotateFile() error {
	if !r.isFileReceiver() {
		return nil
	}

	fileName := r.fileName()
	if _, err := os.Lstat(fileName); err == nil {
		r.Close()
		if err = os.Rename(fileName, r.backupFileName()); err != nil {
			return err
		}
	}

	if err := r.openFile(); err != nil {
		return err
	}

	return nil
}
<commit_msg>file permission supplied for dir creation<commit_after>// Copyright (c) 2016 Jeevanandam M (https://github.com/jeevatkm)
// go-aah/log source code and usage is governed by a MIT style
// license that can be found in the LICENSE file.

package log

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/go-aah/config"
	"github.com/go-aah/essentials"
)

// Receiver represents aah logger object that statisfy console, file, logging
// and Logging Stats. Each logging operation makes a single call to the
// Writer's Write method. `Receiver` guarantees serialize access and
// it can be used from multiple goroutines like Go standard logger.
type Receiver struct {
	Config *config.Config
	Type   string
	Flags  *[]FlagPart
	Format FormatterFunc

	m          sync.Mutex
	level      Level
	out        io.Writer
	stats      *ReceiverStats
	isFileInfo bool
	isLineInfo bool
	isUTC      bool

	// Console Receiver
	isColor bool

	// File Receiver
	isClosed bool
	rotate   string
	openDay  int
	maxSize  int64
	maxLines int64
}

// Output formats the give log inputs, caller info and writes to console
func (r *Receiver) Output(entry *Entry) error {
	if r.Closed() {
		return ErrWriterIsClosed
	}

	if r.isFileInfo || r.isLineInfo {
		entry.File, entry.Line = fetchCallerInfo(3)
	}

	r.m.Lock()
	defer r.m.Unlock()

	// Check log rotation is required
	if r.isRotateRequired() {
		if err := r.rotateFile(); err != nil {
			return err
		}
	}

	// format the log entry message as per pattern
	buf, err := r.Format(r.Flags, entry, r.isColor)
	if err != nil {
		return err
	}

	// writes bytes into writer
	size, err := r.out.Write(*buf)
	if err != nil {
		return err
	}

	// calculate receiver stats
	if r.stats != nil {
		r.stats.bytes += int64(size)
		r.stats.lines++
	}

	return nil
}

// Stats returns current logger statistics like number of lines written,
// number of bytes written, etc.
func (r *Receiver) Stats() *ReceiverStats {
	return r.stats
}

// Close closes the log writer. It cannot be used after this operation
func (r *Receiver) Close() {
	if r.isClosed {
		return
	}

	if out, ok := r.out.(io.Closer); ok {
		r.isClosed = true
		_ = out.Close()
	}
}

// Closed returns true if the logger was previously closed
func (r *Receiver) Closed() bool {
	return r.isClosed
}

// SetPattern sets the pattern to log entry format
func (r *Receiver) SetPattern(pattern string) error {
	r.m.Lock()
	defer r.m.Unlock()
	flags, err := parseFlag(pattern)
	if err != nil {
		return err
	}
	r.Flags = flags

	return nil
}

func (r *Receiver) isFileReceiver() bool {
	return r.Type == "FILE"
}

// Error logs message as `LevelError`
func (r *Receiver) Error(v ...interface{}) {
	if r.level >= LevelError {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelError,
			Values: v,
		})
	}
}

// Errorf logs message as `LevelError`
func (r *Receiver) Errorf(format string, v ...interface{}) {
	if r.level >= LevelError {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelError,
			Format: format,
			Values: v,
		})
	}
}

// Warn logs message as `LevelWarn`
func (r *Receiver) Warn(v ...interface{}) {
	if r.level >= LevelWarn {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelWarn,
			Values: v,
		})
	}
}

// Warnf logs message as `LevelWarn`
func (r *Receiver) Warnf(format string, v ...interface{}) {
	if r.level >= LevelWarn {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelWarn,
			Format: format,
			Values: v,
		})
	}
}

// Info logs message as `LevelInfo`
func (r *Receiver) Info(v ...interface{}) {
	if r.level >= LevelInfo {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelInfo,
			Values: v,
		})
	}
}

// Infof logs message as `LevelInfo`
func (r *Receiver) Infof(format string, v ...interface{}) {
	if r.level >= LevelInfo {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelInfo,
			Format: format,
			Values: v,
		})
	}
}

// Debug logs message as `LevelDebug`
func (r *Receiver) Debug(v ...interface{}) {
	if r.level >= LevelDebug {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelDebug,
			Values: v,
		})
	}
}

// Debugf logs message as `LevelDebug`
func (r *Receiver) Debugf(format string, v ...interface{}) {
	if r.level >= LevelDebug {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelDebug,
			Format: format,
			Values: v,
		})
	}
}

// Trace logs message as `LevelTrace`
func (r *Receiver) Trace(v ...interface{}) {
	if r.level >= LevelTrace {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelTrace,
			Values: v,
		})
	}
}

// Tracef logs message as `LevelTrace`
func (r *Receiver) Tracef(format string, v ...interface{}) {
	if r.level >= LevelTrace {
		_ = r.Output(&Entry{
			Time:   time.Now(),
			Level:  LevelTrace,
			Format: format,
			Values: v,
		})
	}
}

// unexported methods

func (r *Receiver) openFile() error {
	if !r.isFileReceiver() {
		return nil
	}

	name := r.fileName()
	dir := filepath.Dir(name)
	_ = ess.MkDirAll(dir, 0755)

	file, err := os.OpenFile(name, os.O_CREATE|os.O_APPEND|os.O_WRONLY, filePermission)
	if err != nil {
		return err
	}

	fileStat, err := file.Stat()
	if err != nil {
		return err

	}

	r.isClosed = false
	r.setOpenDay()
	r.stats.bytes = fileStat.Size()
	r.stats.lines = int64(ess.LineCntr(file))
	r.out = file

	return nil
}

func (r *Receiver) fileName() string {
	return r.Config.StringDefault("file", "aah-log-file.log")
}

func (r *Receiver) backupFileName() string {
	name := r.fileName()
	dir := filepath.Dir(name)
	fileName := filepath.Base(name)
	ext := filepath.Ext(fileName)
	baseName := strings.TrimSuffix(fileName, ext)

	t := time.Now()
	if r.isUTC {
		t = t.UTC()
	}

	return filepath.Join(dir, fmt.Sprintf("%s-%s%s", baseName, t.Format(BackupTimeFormat), ext))
}

func (r *Receiver) setOpenDay() {
	if r.isUTC {
		r.openDay = time.Now().UTC().Day()
	} else {
		r.openDay = time.Now().Day()
	}
}

func (r *Receiver) isRotateRequired() bool {
	if !r.isFileReceiver() {
		return false
	}

	switch r.rotate {
	case "daily":
		if r.isUTC {
			return time.Now().UTC().Day() != r.openDay
		}
		return time.Now().Day() != r.openDay
	case "lines":
		return r.maxLines != 0 && r.stats.lines >= r.maxLines
	case "size":
		return r.maxSize != 0 && r.stats.bytes >= r.maxSize
	}

	return false
}

func (r *Receiver) rotateFile() error {
	if !r.isFileReceiver() {
		return nil
	}

	fileName := r.fileName()
	if _, err := os.Lstat(fileName); err == nil {
		r.Close()
		if err = os.Rename(fileName, r.backupFileName()); err != nil {
			return err
		}
	}

	if err := r.openFile(); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/guzzlerio/corcel/serialisation/yaml"
	"github.com/guzzlerio/corcel/statistics"
	"github.com/guzzlerio/corcel/test"
	"github.com/guzzlerio/corcel/utils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("ExecutionPlanContexts", func() {

	contextsDebugPath := "/tmp/contexts"
	Describe("Lists", func() {

		BeforeEach(func() {
			if err := os.Remove(contextsDebugPath); err != nil {

			}
		})

		AfterEach(func() {
			if err := os.Remove(contextsDebugPath); err != nil {

			}
		})

		Context("Plan Scope", func() {

			It("Succeeds", func() {

				planBuilder := yaml.NewPlanBuilder()

				planBuilder.
					SetIterations(3).
					WithContext(planBuilder.BuildContext().SetList("People", []map[string]interface{}{
						{"name": "jill", "age": 35},
						{"name": "bob", "age": 52},
						{"name": "carol", "age": 24},
					}).Build()).
					CreateJob().
					CreateStep().
					ToExecuteAction(planBuilder.DummyAction().LogToFile(contextsDebugPath).Build())

				_, err := ExecutePlanBuilder(planBuilder)
				Expect(err).To(BeNil())

				contexts := test.GetExecutionContexts(contextsDebugPath)
				Expect(len(contexts)).To(Equal(3))
				Expect(contexts[0]["$People.name"]).To(Equal("jill"))
				Expect(contexts[1]["$People.name"]).To(Equal("bob"))
				Expect(contexts[2]["$People.name"]).To(Equal("carol"))
			})

		})
	})

	Context("Plan Scope", func() {
		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				WithContext(planBuilder.BuildContext().Set("value:1", "1").Set("value:2", "2").Set("value:3", "3").Build()).
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("something", "$value:1").Build()).
				WithAssertion(planBuilder.ExactAssertion("$value:1", "1")).
				WithAssertion(planBuilder.ExactAssertion("$value:2", "2")).
				WithAssertion(planBuilder.ExactAssertion("$value:3", "3")).
				WithAssertion(planBuilder.ExactAssertion("something", "1"))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})
		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Build()).
				WithAssertion(planBuilder.ExactAssertion("$value:1", "1")).
				WithAssertion(planBuilder.ExactAssertion("$value:2", "2")).
				WithAssertion(planBuilder.ExactAssertion("$value:3", "3"))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(3)))
		})
	})

	Context("Job Scope", func() {
		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				WithContext(planBuilder.BuildContext().Set("value:1", "1").Set("value:2", "2").Set("value:3", "3").Build()).
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Build()).
				WithAssertion(planBuilder.ExactAssertion("$value:1", "1")).
				WithAssertion(planBuilder.ExactAssertion("$value:2", "2")).
				WithAssertion(planBuilder.ExactAssertion("$value:3", "3"))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				WithContext(planBuilder.BuildContext().Set("value:1", "1").Set("value:2", "2").Set("value:3", "3").Build())

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Build()).
				WithAssertion(planBuilder.ExactAssertion("$value:1", "1")).
				WithAssertion(planBuilder.ExactAssertion("$value:2", "2")).
				WithAssertion(planBuilder.ExactAssertion("$value:3", "3"))

			_, err := ExecutePlanBuilder(planBuilder)
			Expect(err).To(BeNil())

			var executionOutput statistics.AggregatorSnapShot
			utils.UnmarshalYamlFromFile("./output.yml", &executionOutput)
			var summary = statistics.CreateSummary(executionOutput)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(3)))
		})
	})

})
<commit_msg>Replaced the ExecutionPlan Context tests with inprocess ones<commit_after>package main

import (
	"os"

	"github.com/guzzlerio/corcel/serialisation/yaml"
	"github.com/guzzlerio/corcel/statistics"
	"github.com/guzzlerio/corcel/test"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("ExecutionPlanContexts", func() {

	contextsDebugPath := "/tmp/contexts"
	Describe("Lists", func() {

		BeforeEach(func() {
			if err := os.Remove(contextsDebugPath); err != nil {

			}
		})

		AfterEach(func() {
			if err := os.Remove(contextsDebugPath); err != nil {

			}
		})

		Context("Plan Scope", func() {

			It("Succeeds", func() {

				planBuilder := yaml.NewPlanBuilder()

				planBuilder.
					SetIterations(3).
					WithContext(planBuilder.BuildContext().SetList("People", []map[string]interface{}{
						{"name": "jill", "age": 35},
						{"name": "bob", "age": 52},
						{"name": "carol", "age": 24},
					}).Build()).
					CreateJob().
					CreateStep().
					ToExecuteAction(planBuilder.DummyAction().LogToFile(contextsDebugPath).Build())

				_, err := ExecutePlanBuilderForApplication(planBuilder)
				Expect(err).To(BeNil())

				contexts := test.GetExecutionContexts(contextsDebugPath)
				Expect(len(contexts)).To(Equal(3))
				Expect(contexts[0]["$People.name"]).To(Equal("jill"))
				Expect(contexts[1]["$People.name"]).To(Equal("bob"))
				Expect(contexts[2]["$People.name"]).To(Equal("carol"))
			})

		})
	})

	Context("Plan Scope", func() {
		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				WithContext(planBuilder.BuildContext().Set("value:1", "1").Set("value:2", "2").Set("value:3", "3").Build()).
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Set("something", "$value:1").Build()).
				WithAssertion(planBuilder.ExactAssertion("$value:1", "1")).
				WithAssertion(planBuilder.ExactAssertion("$value:2", "2")).
				WithAssertion(planBuilder.ExactAssertion("$value:3", "3")).
				WithAssertion(planBuilder.ExactAssertion("something", "1"))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})
		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Build()).
				WithAssertion(planBuilder.ExactAssertion("$value:1", "1")).
				WithAssertion(planBuilder.ExactAssertion("$value:2", "2")).
				WithAssertion(planBuilder.ExactAssertion("$value:3", "3"))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(3)))
		})
	})

	Context("Job Scope", func() {
		It("Succeeds", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				WithContext(planBuilder.BuildContext().Set("value:1", "1").Set("value:2", "2").Set("value:3", "3").Build()).
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Build()).
				WithAssertion(planBuilder.ExactAssertion("$value:1", "1")).
				WithAssertion(planBuilder.ExactAssertion("$value:2", "2")).
				WithAssertion(planBuilder.ExactAssertion("$value:3", "3"))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(0)))
		})

		It("Fails", func() {
			planBuilder := yaml.NewPlanBuilder()

			planBuilder.
				CreateJob().
				WithContext(planBuilder.BuildContext().Set("value:1", "1").Set("value:2", "2").Set("value:3", "3").Build())

			planBuilder.
				CreateJob().
				CreateStep().
				ToExecuteAction(planBuilder.DummyAction().Build()).
				WithAssertion(planBuilder.ExactAssertion("$value:1", "1")).
				WithAssertion(planBuilder.ExactAssertion("$value:2", "2")).
				WithAssertion(planBuilder.ExactAssertion("$value:3", "3"))

			output, err := ExecutePlanBuilderForApplication(planBuilder)
			Expect(err).To(BeNil())

			var summary = statistics.CreateSummary(output)

			Expect(summary.TotalAssertionFailures).To(Equal(int64(3)))
		})
	})

})
<|endoftext|>


<commit_before>package kumoru

import (
	"bytes"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha256"
	"crypto/tls"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"reflect"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
)

const (
	POST   = "POST"
	GET    = "GET"
	HEAD   = "HEAD"
	PUT    = "PUT"
	DELETE = "DELETE"
	PATCH  = "PATCH"
)

type Request *http.Request
type Response *http.Response

type KumoruClient struct {
	SliceData         []interface{}
	BasicAuth         struct{ UserName, Password string }
	BounceToRawString bool
	Client            *http.Client
	Data              map[string]interface{}
	Debug             bool
	EndPoint          *Endpoints
	Errors            []error
	FormData          url.Values
	Header            map[string]string
	Logger            *log.Logger
	Method            string
	QueryData         url.Values
	RawString         string
	Sign              bool
	TargetType        string
	Tokens            *Ktokens
	Transport         *http.Transport
	Url               string
}

// Used to create a new KumoruClient Object.
func New() *KumoruClient {

	config := os.Getenv("KUMORU_CONFIG")

	if config == "" {
		usrHome := os.Getenv("HOME")

		config = usrHome + "/.kumoru/config"

	}

	c, err := LoadCreds(config, "auth")
	if err != nil {
		log.Fatal(err)
	}

	e, err := LoadEndpoints(config, "endpoints")
	if err != nil {
		log.Fatal(err)
	}

	t, err := LoadTokens(config, "tokens")
	if err != nil {
		log.Fatal(err)
	}

	k := &KumoruClient{
		BasicAuth:         struct{ UserName, Password string }{c.UserName, c.Password},
		BounceToRawString: false,
		Client:            &http.Client{},
		Data:              make(map[string]interface{}),
		Debug:             false,
		SliceData:         []interface{}{},
		EndPoint:          &e,
		Errors:            nil,
		FormData:          url.Values{},
		Header:            make(map[string]string),
		Logger:            log.New(),
		QueryData:         url.Values{},
		RawString:         "",
		Sign:              false,
		TargetType:        "form",
		Tokens:            &t,
		Transport:         &http.Transport{},
		Url:               "",
	}

	return k
}

func (k *KumoruClient) SignRequest(enable bool) *KumoruClient {
	k.Sign = enable
	return k
}

func (k *KumoruClient) SetDebug(enable bool) *KumoruClient {
	k.Debug = enable
	return k
}

func (k *KumoruClient) SetLogger(logger *log.Logger) *KumoruClient {
	k.Logger = logger
	return k
}

// Clear KumoruClient data for a new request
func (k *KumoruClient) ClearKumoruClient() {
	k.BounceToRawString = false
	k.Data = make(map[string]interface{})
	k.Errors = nil
	k.FormData = url.Values{}
	k.Header = make(map[string]string)
	k.Method = ""
	k.QueryData = url.Values{}
	k.RawString = ""
	k.Sign = false
	k.TargetType = "form"
	k.Url = ""
	k.SliceData = []interface{}{}
}

func (k *KumoruClient) Get(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = GET
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Patch(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = PATCH
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Put(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = PUT
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Delete(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = DELETE
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Post(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = POST
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Head(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = POST
	k.Url = targetUrl
	k.Errors = nil

	return k
}

// SetHeader headers
// kumoru.New().
// POST("/application/B8658129-701E-432C-BD80-5D0F464EC932").
// SetHeader("Accept", "application/x-www-form-urlencoded")
func (k *KumoruClient) SetHeader(param string, value string) *KumoruClient {
	k.Header[param] = value
	return k
}

func (k *KumoruClient) Param(key string, value string) *KumoruClient {
	k.QueryData.Add(key, value)
	return k
}

// Probably can merge in the initialize section
func (k *KumoruClient) SetBasicAuth(username string, password string) *KumoruClient {
	k.BasicAuth = struct{ UserName, Password string }{username, password}
	return k
}

// Query fucntion forms a query-string in the url of GET method or body of POST method.
// Usage Example:
//
// kumoru.New().
// Get("/applications/").
// Query(`{ query: 'myapp' }`).
// Query(`{ limit: '5' }`).
// End()
//
// kumoru.New().
// Get("/applications/").
// Query("query=myapp&limit=5").
// End()
//
// kumoru.New().
// Get("/applications/").
// Query("query=myapp&limit=5").
// Query(`{ sort: 'asc' }`).
// End()

func (k *KumoruClient) Query(content interface{}) *KumoruClient {
	switch v := reflect.ValueOf(content); v.Kind() {

	case reflect.String:
		k.queryString(v.String())
	case reflect.Struct:
		k.queryStruct(v.Interface())
	default:
	}
	return k
}

func (k *KumoruClient) queryString(content string) *KumoruClient {
	var val map[string]string
	if err := json.Unmarshal([]byte(content), &val); err == nil {
		for key, v := range val {
			k.QueryData.Add(key, v)
		}
	} else {
		if queryVal, err := url.ParseQuery(content); err == nil {
			for key, _ := range queryVal {
				k.QueryData.Add(key, queryVal.Get(key))
			}
		} else {
			k.Errors = append(k.Errors, err)
		}
	}
	return k
}

func (k *KumoruClient) queryStruct(content interface{}) *KumoruClient {
	if marchalContent, err := json.Marshal(content); err != nil {
		k.Errors = append(k.Errors, err)
	} else {
		var val map[string]interface{}
		if err := json.Unmarshal(marchalContent, &val); err != nil {
			k.Errors = append(k.Errors, err)
		} else {
			for key, v := range val {
				key = strings.ToLower(key)
				k.QueryData.Add(key, v.(string))
			}
		}
	}
	return k
}

func (k *KumoruClient) TLSClientConfig(config *tls.Config) *KumoruClient {
	k.Transport.TLSClientConfig = config
	return k
}

// End() or EndBytes() must be called to execute the call otherwise it won't do a thing.
func (k *KumoruClient) End(callback ...func(response Response, body string, errs []error)) (Response, string, []error) {
	var bytesCallback []func(response Response, body []byte, errs []error)
	if len(callback) > 0 {
		bytesCallback = []func(response Response, body []byte, errs []error){
			func(response Response, body []byte, errs []error) {
				callback[0](response, string(body), errs)
			},
		}
	}
	resp, body, errs := k.EndBytes(bytesCallback...)
	bodyString := string(body)
	return resp, bodyString, errs
}

// EndBytes should be used when you want the body as bytes.
func (k *KumoruClient) EndBytes(callback ...func(response Response, body []byte, errs []error)) (Response, []byte, []error) {
	// check whether there is an error. if yes, return all errors
	if len(k.Errors) != 0 {
		return nil, nil, k.Errors
	}

	req, err := k.NewRequest()

	if err != nil {
		k.Errors = append(k.Errors, err)
		return nil, nil, k.Errors
	}

	for key, v := range k.Header {
		req.Header.Set(key, v)
	}

	// Add all querystring from Query func
	q := req.URL.Query()
	for key, v := range k.QueryData {
		for _, vv := range v {
			q.Add(key, vv)
		}
	}
	req.URL.RawQuery = q.Encode()

	// Sign Request
	if !k.Sign {
		if k.BasicAuth != struct{ UserName, Password string }{} {
			req.SetBasicAuth(k.BasicAuth.UserName, k.BasicAuth.Password)
		}
	} else {
		b1 := strings.NewReader(k.RawString)
		date := time.Now()
		signingString := k.Method + "\n"

		b, err := ioutil.ReadAll(b1)

		if err != nil {
			log.Fatal(err)
		}
		if len(b) != 0 {
			data := md5.Sum(b)
			newdata := fmt.Sprintf("content-md5:%x", string(data[:16]))

			req.Header.Set("Content-MD5", newdata)

			signingString += fmt.Sprintf("content-type:%v", req.Header.Get("Content-Type")+"\n")
		}
		u, _ := url.Parse(k.Url)
		signingString += "x-kumoru-date:" + date.String() + "\n" + u.Path
		req.Header.Set("X-Kumoru-Date", date.String())

		h := hmac.New(sha256.New, []byte(k.Tokens.Private))
		h.Write([]byte(signingString))
		digest := fmt.Sprintf("%x", h.Sum(nil))

		req.Header.Set("Authorization", base64.StdEncoding.EncodeToString([]byte(k.Tokens.Public+":"+digest)))
	}

	// Set Transport
	k.Client.Transport = k.Transport

	// Log details of this request
	if k.Debug {
		dump, err := httputil.DumpRequest(req, true)
		if err != nil {
			k.Logger.Println("Error:", err)
		} else {
			k.Logger.Printf("HTTP Request: %s", string(dump))
		}
	}

	// Send request
	resp, err := k.Client.Do(req)
	if err != nil {
		k.Errors = append(k.Errors, err)
		return nil, nil, k.Errors
	}
	defer resp.Body.Close()

	// Log details of this response
	if k.Debug {
		dump, err := httputil.DumpResponse(resp, true)
		if nil != err {
			k.Logger.Println("Error:", err)
		} else {
			k.Logger.Printf("HTTP Response: %s", string(dump))
		}
	}

	body, _ := ioutil.ReadAll(resp.Body)
	// Reset resp.Body so it can be use again
	resp.Body = ioutil.NopCloser(bytes.NewBuffer(body))
	// deep copy response to give it to both return and callback func
	respCallback := *resp
	if len(callback) != 0 {
		callback[0](&respCallback, body, k.Errors)
	}
	return resp, body, nil
}

func changeMapToURLValues(data map[string]interface{}) url.Values {
	var newUrlValues = url.Values{}
	for k, v := range data {
		switch val := v.(type) {
		case string:
			newUrlValues.Add(k, val)
		case []string:
			for _, element := range val {
				newUrlValues.Add(k, element)
			}
		// if a number, change to string
		// json.Number used to protect against a wrong (for GoRequest) default conversion
		// which always converts number to float64.
		// This type is caused by using Decoder.UseNumber()
		case json.Number:
			newUrlValues.Add(k, string(val))
		}
	}
	return newUrlValues
}
<commit_msg>fix signing mismatch<commit_after>package kumoru

import (
	"bytes"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha256"
	"crypto/tls"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"reflect"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
)

const (
	POST   = "POST"
	GET    = "GET"
	HEAD   = "HEAD"
	PUT    = "PUT"
	DELETE = "DELETE"
	PATCH  = "PATCH"
)

type Request *http.Request
type Response *http.Response

type KumoruClient struct {
	SliceData         []interface{}
	BasicAuth         struct{ UserName, Password string }
	BounceToRawString bool
	Client            *http.Client
	Data              map[string]interface{}
	Debug             bool
	EndPoint          *Endpoints
	Errors            []error
	FormData          url.Values
	Header            map[string]string
	Logger            *log.Logger
	Method            string
	QueryData         url.Values
	RawString         string
	Sign              bool
	TargetType        string
	Tokens            *Ktokens
	Transport         *http.Transport
	Url               string
}

// Used to create a new KumoruClient Object.
func New() *KumoruClient {

	config := os.Getenv("KUMORU_CONFIG")

	if config == "" {
		usrHome := os.Getenv("HOME")

		config = usrHome + "/.kumoru/config"

	}

	c, err := LoadCreds(config, "auth")
	if err != nil {
		log.Fatal(err)
	}

	e, err := LoadEndpoints(config, "endpoints")
	if err != nil {
		log.Fatal(err)
	}

	t, err := LoadTokens(config, "tokens")
	if err != nil {
		log.Fatal(err)
	}

	k := &KumoruClient{
		BasicAuth:         struct{ UserName, Password string }{c.UserName, c.Password},
		BounceToRawString: false,
		Client:            &http.Client{},
		Data:              make(map[string]interface{}),
		Debug:             false,
		SliceData:         []interface{}{},
		EndPoint:          &e,
		Errors:            nil,
		FormData:          url.Values{},
		Header:            make(map[string]string),
		Logger:            log.New(),
		QueryData:         url.Values{},
		RawString:         "",
		Sign:              false,
		TargetType:        "form",
		Tokens:            &t,
		Transport:         &http.Transport{},
		Url:               "",
	}

	return k
}

func (k *KumoruClient) SignRequest(enable bool) *KumoruClient {
	k.Sign = enable
	return k
}

func (k *KumoruClient) SetDebug(enable bool) *KumoruClient {
	k.Debug = enable
	return k
}

func (k *KumoruClient) SetLogger(logger *log.Logger) *KumoruClient {
	k.Logger = logger
	return k
}

// Clear KumoruClient data for a new request
func (k *KumoruClient) ClearKumoruClient() {
	k.BounceToRawString = false
	k.Data = make(map[string]interface{})
	k.Errors = nil
	k.FormData = url.Values{}
	k.Header = make(map[string]string)
	k.Method = ""
	k.QueryData = url.Values{}
	k.RawString = ""
	k.Sign = false
	k.TargetType = "form"
	k.Url = ""
	k.SliceData = []interface{}{}
}

func (k *KumoruClient) Get(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = GET
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Patch(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = PATCH
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Put(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = PUT
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Delete(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = DELETE
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Post(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = POST
	k.Url = targetUrl
	k.Errors = nil

	return k
}

func (k *KumoruClient) Head(targetUrl string) *KumoruClient {
	k.ClearKumoruClient()
	k.Method = POST
	k.Url = targetUrl
	k.Errors = nil

	return k
}

// SetHeader headers
// kumoru.New().
// POST("/application/B8658129-701E-432C-BD80-5D0F464EC932").
// SetHeader("Accept", "application/x-www-form-urlencoded")
func (k *KumoruClient) SetHeader(param string, value string) *KumoruClient {
	k.Header[param] = value
	return k
}

func (k *KumoruClient) Param(key string, value string) *KumoruClient {
	k.QueryData.Add(key, value)
	return k
}

// Probably can merge in the initialize section
func (k *KumoruClient) SetBasicAuth(username string, password string) *KumoruClient {
	k.BasicAuth = struct{ UserName, Password string }{username, password}
	return k
}

// Query fucntion forms a query-string in the url of GET method or body of POST method.
// Usage Example:
//
// kumoru.New().
// Get("/applications/").
// Query(`{ query: 'myapp' }`).
// Query(`{ limit: '5' }`).
// End()
//
// kumoru.New().
// Get("/applications/").
// Query("query=myapp&limit=5").
// End()
//
// kumoru.New().
// Get("/applications/").
// Query("query=myapp&limit=5").
// Query(`{ sort: 'asc' }`).
// End()

func (k *KumoruClient) Query(content interface{}) *KumoruClient {
	switch v := reflect.ValueOf(content); v.Kind() {

	case reflect.String:
		k.queryString(v.String())
	case reflect.Struct:
		k.queryStruct(v.Interface())
	default:
	}
	return k
}

func (k *KumoruClient) queryString(content string) *KumoruClient {
	var val map[string]string
	if err := json.Unmarshal([]byte(content), &val); err == nil {
		for key, v := range val {
			k.QueryData.Add(key, v)
		}
	} else {
		if queryVal, err := url.ParseQuery(content); err == nil {
			for key, _ := range queryVal {
				k.QueryData.Add(key, queryVal.Get(key))
			}
		} else {
			k.Errors = append(k.Errors, err)
		}
	}
	return k
}

func (k *KumoruClient) queryStruct(content interface{}) *KumoruClient {
	if marchalContent, err := json.Marshal(content); err != nil {
		k.Errors = append(k.Errors, err)
	} else {
		var val map[string]interface{}
		if err := json.Unmarshal(marchalContent, &val); err != nil {
			k.Errors = append(k.Errors, err)
		} else {
			for key, v := range val {
				key = strings.ToLower(key)
				k.QueryData.Add(key, v.(string))
			}
		}
	}
	return k
}

func (k *KumoruClient) TLSClientConfig(config *tls.Config) *KumoruClient {
	k.Transport.TLSClientConfig = config
	return k
}

// End() or EndBytes() must be called to execute the call otherwise it won't do a thing.
func (k *KumoruClient) End(callback ...func(response Response, body string, errs []error)) (Response, string, []error) {
	var bytesCallback []func(response Response, body []byte, errs []error)
	if len(callback) > 0 {
		bytesCallback = []func(response Response, body []byte, errs []error){
			func(response Response, body []byte, errs []error) {
				callback[0](response, string(body), errs)
			},
		}
	}
	resp, body, errs := k.EndBytes(bytesCallback...)
	bodyString := string(body)
	return resp, bodyString, errs
}

// EndBytes should be used when you want the body as bytes.
func (k *KumoruClient) EndBytes(callback ...func(response Response, body []byte, errs []error)) (Response, []byte, []error) {
	// check whether there is an error. if yes, return all errors
	if len(k.Errors) != 0 {
		return nil, nil, k.Errors
	}

	req, err := k.NewRequest()

	if err != nil {
		k.Errors = append(k.Errors, err)
		return nil, nil, k.Errors
	}

	for key, v := range k.Header {
		req.Header.Set(key, v)
	}

	// Add all querystring from Query func
	q := req.URL.Query()
	for key, v := range k.QueryData {
		for _, vv := range v {
			q.Add(key, vv)
		}
	}
	req.URL.RawQuery = q.Encode()

	// Sign Request
	if !k.Sign {
		if k.BasicAuth != struct{ UserName, Password string }{} {
			req.SetBasicAuth(k.BasicAuth.UserName, k.BasicAuth.Password)
		}
	} else {
		b1 := strings.NewReader(k.RawString)
		date := time.Now()
		signingString := k.Method + "\n"

		b, err := ioutil.ReadAll(b1)

		if err != nil {
			log.Fatal(err)
		}
		if len(b) != 0 {
			data := md5.Sum(b)
			newdata := fmt.Sprintf("content-md5:%x", string(data[:16]))

			req.Header.Set("Content-MD5", fmt.Sprintf("%x", string(data[:16])))

			signingString += newdata + "\n" + fmt.Sprintf("content-type:%v", req.Header.Get("Content-Type")+"\n")
		}
		u, _ := url.Parse(k.Url)
		signingString += "x-kumoru-date:" + date.String() + "\n" + u.Path
		req.Header.Set("X-Kumoru-Date", date.String())

		h := hmac.New(sha256.New, []byte(k.Tokens.Private))
		h.Write([]byte(signingString))
		digest := fmt.Sprintf("%x", h.Sum(nil))

		req.Header.Set("Authorization", base64.StdEncoding.EncodeToString([]byte(k.Tokens.Public+":"+digest)))
	}

	// Set Transport
	k.Client.Transport = k.Transport

	// Log details of this request
	if k.Debug {
		dump, err := httputil.DumpRequest(req, true)
		if err != nil {
			k.Logger.Println("Error:", err)
		} else {
			k.Logger.Printf("HTTP Request: %s", string(dump))
		}
	}

	// Send request
	resp, err := k.Client.Do(req)
	if err != nil {
		k.Errors = append(k.Errors, err)
		return nil, nil, k.Errors
	}
	defer resp.Body.Close()

	// Log details of this response
	if k.Debug {
		dump, err := httputil.DumpResponse(resp, true)
		if nil != err {
			k.Logger.Println("Error:", err)
		} else {
			k.Logger.Printf("HTTP Response: %s", string(dump))
		}
	}

	body, _ := ioutil.ReadAll(resp.Body)
	// Reset resp.Body so it can be use again
	resp.Body = ioutil.NopCloser(bytes.NewBuffer(body))
	// deep copy response to give it to both return and callback func
	respCallback := *resp
	if len(callback) != 0 {
		callback[0](&respCallback, body, k.Errors)
	}
	return resp, body, nil
}

func changeMapToURLValues(data map[string]interface{}) url.Values {
	var newUrlValues = url.Values{}
	for k, v := range data {
		switch val := v.(type) {
		case string:
			newUrlValues.Add(k, val)
		case []string:
			for _, element := range val {
				newUrlValues.Add(k, element)
			}
		// if a number, change to string
		// json.Number used to protect against a wrong (for GoRequest) default conversion
		// which always converts number to float64.
		// This type is caused by using Decoder.UseNumber()
		case json.Number:
			newUrlValues.Add(k, string(val))
		}
	}
	return newUrlValues
}
<|endoftext|>