<commit_before>package wsproxy

import (
	"bufio"
	"io"
	"net/http"
	"strings"

	"github.com/gorilla/websocket"
	"github.com/sirupsen/logrus"
	"golang.org/x/net/context"
)

// MethodOverrideParam defines the special URL parameter that is translated into the subsequent proxied streaming http request's method.
//
// Deprecated: it is preferable to use the Options parameters to WebSocketProxy to supply parameters.
var MethodOverrideParam = "method"

// TokenCookieName defines the cookie name that is translated to an 'Authorization: Bearer' header in the streaming http request's headers.
//
// Deprecated: it is preferable to use the Options parameters to WebSocketProxy to supply parameters.
var TokenCookieName = "token"

// RequestMutatorFunc can supply an alternate outgoing request.
type RequestMutatorFunc func(incoming *http.Request, outgoing *http.Request) *http.Request

// Proxy provides websocket transport upgrade to compatible endpoints.
type Proxy struct {
	h                   http.Handler
	logger              Logger
	methodOverrideParam string
	tokenCookieName     string
	requestMutator      RequestMutatorFunc
}

// Logger collects log messages.
type Logger interface {
	Warnln(...interface{})
	Debugln(...interface{})
}

func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !websocket.IsWebSocketUpgrade(r) {
		p.h.ServeHTTP(w, r)
		return
	}
	p.proxy(w, r)
}

// Option allows customization of the proxy.
type Option func(*Proxy)

// WithMethodParamOverride allows specification of the special http parameter that is used in the proxied streaming request.
func WithMethodParamOverride(param string) Option {
	return func(p *Proxy) {
		p.methodOverrideParam = param
	}
}

// WithTokenCookieName allows specification of the cookie that is supplied as an upstream 'Authorization: Bearer' http header.
func WithTokenCookieName(param string) Option {
	return func(p *Proxy) {
		p.tokenCookieName = param
	}
}

// WithRequestMutator allows a custom RequestMutatorFunc to be supplied.
func WithRequestMutator(fn RequestMutatorFunc) Option {
	return func(p *Proxy) {
		p.requestMutator = fn
	}
}

// WithLogger allows a custom FieldLogger to be supplied
func WithLogger(logger Logger) Option {
	return func(p *Proxy) {
		p.logger = logger
	}
}

// WebsocketProxy attempts to expose the underlying handler as a bidi websocket stream with newline-delimited
// JSON as the content encoding.
//
// The HTTP Authorization header is either populated from the Sec-Websocket-Protocol field or by a cookie.
// The cookie name is specified by the TokenCookieName value.
//
// example:
//   Sec-Websocket-Protocol: Bearer, foobar
// is converted to:
//   Authorization: Bearer foobar
//
// Method can be overwritten with the MethodOverrideParam get parameter in the requested URL
func WebsocketProxy(h http.Handler, opts ...Option) http.Handler {
	p := &Proxy{
		h:                   h,
		logger:              logrus.New(),
		methodOverrideParam: MethodOverrideParam,
		tokenCookieName:     TokenCookieName,
	}
	for _, o := range opts {
		o(p)
	}
	return p
}

// TODO(tmc): allow modification of upgrader settings?
var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin:     func(r *http.Request) bool { return true },
}

func isClosedConnError(err error) bool {
	str := err.Error()
	if strings.Contains(str, "use of closed network connection") {
		return true
	}
	return websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway)
}

func (p *Proxy) proxy(w http.ResponseWriter, r *http.Request) {
	var responseHeader http.Header
	// If Sec-WebSocket-Protocol starts with "Bearer", respond in kind.
	// TODO(tmc): consider customizability/extension point here.
	if strings.HasPrefix(r.Header.Get("Sec-WebSocket-Protocol"), "Bearer") {
		responseHeader = http.Header{
			"Sec-WebSocket-Protocol": []string{"Bearer"},
		}
	}
	conn, err := upgrader.Upgrade(w, r, responseHeader)
	if err != nil {
		p.logger.Warnln("error upgrading websocket:", err)
		return
	}
	defer conn.Close()

	ctx, cancelFn := context.WithCancel(context.Background())
	defer cancelFn()

	requestBodyR, requestBodyW := io.Pipe()
	request, err := http.NewRequest(r.Method, r.URL.String(), requestBodyR)
	if err != nil {
		p.logger.Warnln("error preparing request:", err)
		return
	}
	if swsp := r.Header.Get("Sec-WebSocket-Protocol"); swsp != "" {
		request.Header.Set("Authorization", strings.Replace(swsp, "Bearer, ", "Bearer ", 1))
	}
	// If token cookie is present, populate Authorization header from the cookie instead.
	if cookie, err := r.Cookie(p.tokenCookieName); err == nil {
		request.Header.Set("Authorization", "Bearer "+cookie.Value)
	}
	if m := r.URL.Query().Get(p.methodOverrideParam); m != "" {
		request.Method = m
	}

	if p.requestMutator != nil {
		request = p.requestMutator(r, request)
	}

	responseBodyR, responseBodyW := io.Pipe()
	response := newInMemoryResponseWriter(responseBodyW)
	go func() {
		<-ctx.Done()
		p.logger.Debugln("closing pipes")
		requestBodyW.CloseWithError(io.EOF)
		responseBodyW.CloseWithError(io.EOF)
		response.closed <- true
	}()

	go func() {
		defer cancelFn()
		p.h.ServeHTTP(response, request)
	}()

	// read loop -- take messages from websocket and write to http request
	go func() {
		defer func() {
			cancelFn()
		}()
		for {
			select {
			case <-ctx.Done():
				p.logger.Debugln("read loop done")
				return
			default:
			}
			p.logger.Debugln("[read] reading from socket.")
			_, payload, err := conn.ReadMessage()
			if err != nil {
				if isClosedConnError(err) {
					p.logger.Debugln("[read] websocket closed:", err)
					return
				}
				p.logger.Warnln("error reading websocket message:", err)
				return
			}
			p.logger.Debugln("[read] read payload:", string(payload))
			p.logger.Debugln("[read] writing to requestBody:")
			n, err := requestBodyW.Write(payload)
			requestBodyW.Write([]byte("\n"))
			p.logger.Debugln("[read] wrote to requestBody", n)
			if err != nil {
				p.logger.Warnln("[read] error writing message to upstream http server:", err)
				return
			}
		}
	}()
	// write loop -- take messages from response and write to websocket
	scanner := bufio.NewScanner(responseBodyR)
	for scanner.Scan() {
		if len(scanner.Bytes()) == 0 {
			p.logger.Warnln("[write] empty scan", scanner.Err())
			continue
		}
		p.logger.Debugln("[write] scanned", scanner.Text())
		if err = conn.WriteMessage(websocket.TextMessage, scanner.Bytes()); err != nil {
			p.logger.Warnln("[write] error writing websocket message:", err)
			return
		}
	}
	if err := scanner.Err(); err != nil {
		p.logger.Warnln("scanner err:", err)
	}
}

type inMemoryResponseWriter struct {
	io.Writer
	header http.Header
	code   int
	closed chan bool
}

func newInMemoryResponseWriter(w io.Writer) *inMemoryResponseWriter {
	return &inMemoryResponseWriter{
		Writer: w,
		header: http.Header{},
		closed: make(chan bool, 1),
	}
}

func (w *inMemoryResponseWriter) Write(b []byte) (int, error) {
	return w.Writer.Write(b)
}
func (w *inMemoryResponseWriter) Header() http.Header {
	return w.header
}
func (w *inMemoryResponseWriter) WriteHeader(code int) {
	w.code = code
}
func (w *inMemoryResponseWriter) CloseNotify() <-chan bool {
	return w.closed
}
func (w *inMemoryResponseWriter) Flush() {}
<commit_msg>add ability control forwarded headers<commit_after>package wsproxy

import (
	"bufio"
	"io"
	"net/http"
	"strings"

	"github.com/gorilla/websocket"
	"github.com/sirupsen/logrus"
	"golang.org/x/net/context"
)

// MethodOverrideParam defines the special URL parameter that is translated into the subsequent proxied streaming http request's method.
//
// Deprecated: it is preferable to use the Options parameters to WebSocketProxy to supply parameters.
var MethodOverrideParam = "method"

// TokenCookieName defines the cookie name that is translated to an 'Authorization: Bearer' header in the streaming http request's headers.
//
// Deprecated: it is preferable to use the Options parameters to WebSocketProxy to supply parameters.
var TokenCookieName = "token"

// RequestMutatorFunc can supply an alternate outgoing request.
type RequestMutatorFunc func(incoming *http.Request, outgoing *http.Request) *http.Request

// Proxy provides websocket transport upgrade to compatible endpoints.
type Proxy struct {
	h                   http.Handler
	logger              Logger
	methodOverrideParam string
	tokenCookieName     string
	requestMutator      RequestMutatorFunc
	headerForwarder     func(header string) bool
}

// Logger collects log messages.
type Logger interface {
	Warnln(...interface{})
	Debugln(...interface{})
}

func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !websocket.IsWebSocketUpgrade(r) {
		p.h.ServeHTTP(w, r)
		return
	}
	p.proxy(w, r)
}

// Option allows customization of the proxy.
type Option func(*Proxy)

// WithMethodParamOverride allows specification of the special http parameter that is used in the proxied streaming request.
func WithMethodParamOverride(param string) Option {
	return func(p *Proxy) {
		p.methodOverrideParam = param
	}
}

// WithTokenCookieName allows specification of the cookie that is supplied as an upstream 'Authorization: Bearer' http header.
func WithTokenCookieName(param string) Option {
	return func(p *Proxy) {
		p.tokenCookieName = param
	}
}

// WithRequestMutator allows a custom RequestMutatorFunc to be supplied.
func WithRequestMutator(fn RequestMutatorFunc) Option {
	return func(p *Proxy) {
		p.requestMutator = fn
	}
}

// WithForwardedHeaders allows controlling which headers are forwarded.
func WithForwardedHeaders(fn func(header string) bool) Option {
	return func(p *Proxy) {
		p.headerForwarder = fn
	}
}

// WithLogger allows a custom FieldLogger to be supplied
func WithLogger(logger Logger) Option {
	return func(p *Proxy) {
		p.logger = logger
	}
}

var defaultHeadersToForward = map[string]bool{
	"Origin":  true,
	"origin":  true,
	"Referer": true,
	"referer": true,
}

func defaultHeaderForwarder(header string) bool {
	return defaultHeadersToForward[header]
}

// WebsocketProxy attempts to expose the underlying handler as a bidi websocket stream with newline-delimited
// JSON as the content encoding.
//
// The HTTP Authorization header is either populated from the Sec-Websocket-Protocol field or by a cookie.
// The cookie name is specified by the TokenCookieName value.
//
// example:
//   Sec-Websocket-Protocol: Bearer, foobar
// is converted to:
//   Authorization: Bearer foobar
//
// Method can be overwritten with the MethodOverrideParam get parameter in the requested URL
func WebsocketProxy(h http.Handler, opts ...Option) http.Handler {
	p := &Proxy{
		h:                   h,
		logger:              logrus.New(),
		methodOverrideParam: MethodOverrideParam,
		tokenCookieName:     TokenCookieName,
		headerForwarder:     defaultHeaderForwarder,
	}
	for _, o := range opts {
		o(p)
	}
	return p
}

// TODO(tmc): allow modification of upgrader settings?
var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin:     func(r *http.Request) bool { return true },
}

func isClosedConnError(err error) bool {
	str := err.Error()
	if strings.Contains(str, "use of closed network connection") {
		return true
	}
	return websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseGoingAway)
}

func (p *Proxy) proxy(w http.ResponseWriter, r *http.Request) {
	var responseHeader http.Header
	// If Sec-WebSocket-Protocol starts with "Bearer", respond in kind.
	// TODO(tmc): consider customizability/extension point here.
	if strings.HasPrefix(r.Header.Get("Sec-WebSocket-Protocol"), "Bearer") {
		responseHeader = http.Header{
			"Sec-WebSocket-Protocol": []string{"Bearer"},
		}
	}
	conn, err := upgrader.Upgrade(w, r, responseHeader)
	if err != nil {
		p.logger.Warnln("error upgrading websocket:", err)
		return
	}
	defer conn.Close()

	ctx, cancelFn := context.WithCancel(context.Background())
	defer cancelFn()

	requestBodyR, requestBodyW := io.Pipe()
	request, err := http.NewRequest(r.Method, r.URL.String(), requestBodyR)
	if err != nil {
		p.logger.Warnln("error preparing request:", err)
		return
	}
	if swsp := r.Header.Get("Sec-WebSocket-Protocol"); swsp != "" {
		request.Header.Set("Authorization", strings.Replace(swsp, "Bearer, ", "Bearer ", 1))
	}
	for header := range r.Header {
		if p.headerForwarder(header) {
			request.Header.Set(header, r.Header.Get(header))
		}
	}
	// If token cookie is present, populate Authorization header from the cookie instead.
	if cookie, err := r.Cookie(p.tokenCookieName); err == nil {
		request.Header.Set("Authorization", "Bearer "+cookie.Value)
	}
	if m := r.URL.Query().Get(p.methodOverrideParam); m != "" {
		request.Method = m
	}

	if p.requestMutator != nil {
		request = p.requestMutator(r, request)
	}

	responseBodyR, responseBodyW := io.Pipe()
	response := newInMemoryResponseWriter(responseBodyW)
	go func() {
		<-ctx.Done()
		p.logger.Debugln("closing pipes")
		requestBodyW.CloseWithError(io.EOF)
		responseBodyW.CloseWithError(io.EOF)
		response.closed <- true
	}()

	go func() {
		defer cancelFn()
		p.h.ServeHTTP(response, request)
	}()

	// read loop -- take messages from websocket and write to http request
	go func() {
		defer func() {
			cancelFn()
		}()
		for {
			select {
			case <-ctx.Done():
				p.logger.Debugln("read loop done")
				return
			default:
			}
			p.logger.Debugln("[read] reading from socket.")
			_, payload, err := conn.ReadMessage()
			if err != nil {
				if isClosedConnError(err) {
					p.logger.Debugln("[read] websocket closed:", err)
					return
				}
				p.logger.Warnln("error reading websocket message:", err)
				return
			}
			p.logger.Debugln("[read] read payload:", string(payload))
			p.logger.Debugln("[read] writing to requestBody:")
			n, err := requestBodyW.Write(payload)
			requestBodyW.Write([]byte("\n"))
			p.logger.Debugln("[read] wrote to requestBody", n)
			if err != nil {
				p.logger.Warnln("[read] error writing message to upstream http server:", err)
				return
			}
		}
	}()
	// write loop -- take messages from response and write to websocket
	scanner := bufio.NewScanner(responseBodyR)
	for scanner.Scan() {
		if len(scanner.Bytes()) == 0 {
			p.logger.Warnln("[write] empty scan", scanner.Err())
			continue
		}
		p.logger.Debugln("[write] scanned", scanner.Text())
		if err = conn.WriteMessage(websocket.TextMessage, scanner.Bytes()); err != nil {
			p.logger.Warnln("[write] error writing websocket message:", err)
			return
		}
	}
	if err := scanner.Err(); err != nil {
		p.logger.Warnln("scanner err:", err)
	}
}

type inMemoryResponseWriter struct {
	io.Writer
	header http.Header
	code   int
	closed chan bool
}

func newInMemoryResponseWriter(w io.Writer) *inMemoryResponseWriter {
	return &inMemoryResponseWriter{
		Writer: w,
		header: http.Header{},
		closed: make(chan bool, 1),
	}
}

func (w *inMemoryResponseWriter) Write(b []byte) (int, error) {
	return w.Writer.Write(b)
}
func (w *inMemoryResponseWriter) Header() http.Header {
	return w.header
}
func (w *inMemoryResponseWriter) WriteHeader(code int) {
	w.code = code
}
func (w *inMemoryResponseWriter) CloseNotify() <-chan bool {
	return w.closed
}
func (w *inMemoryResponseWriter) Flush() {}
<|endoftext|>


<commit_before>package qbit

import (
	//	"errors"
	"fmt"
	"github.com/fatih/structs"
	"github.com/serenize/snaker"
	//	"reflect"
	"strings"
	//	"errors"
	"errors"
)

const TAG = "qbit"
const DEFAULT_FLOAT_P = 53

func NewMapper(driver string) *Mapper {
	return &Mapper{
		driver: driver,
	}
}

type Mapper struct {
	driver string
}

func (m *Mapper) extractValue(value string) string {

	hasParams := strings.Contains(value, "(") && strings.Contains(value, ")")

	if hasParams {
		startIndex := strings.Index(value, "(")
		endIndex := strings.Index(value, ")")
		return value[startIndex+1 : endIndex]
	}

	return ""
}

func (m *Mapper) ConvertType(colType string, tagType string) *Type {

	// convert tagType
	if tagType != "" {
		tagType = strings.ToUpper(tagType)
		return &Type{func() string { return tagType }}
	}

	// convert default type
	switch colType {
	case "string":
		return VarChar()
	case "int":
		return Int()
	case "int64":
		return BigInt()
	case "float32":
		return Float()
	case "float64":
		return Float()
	case "bool":
		return Boolean()
	case "uuid.UUID":
		if m.driver == "postgres" {
			return UUID()
		}
		return VarChar(36)
	case "time.Time":
		return Timestamp()
	case "*time.Time":
		return Timestamp()
	default:
		return VarChar()
	}
}

func (m *Mapper) convertConstraints(rawConstraints []string) ([]Constraint, error) {

	constraints := []Constraint{}

	var constraint Constraint
	for _, v := range rawConstraints {

		if v == "null" {
			constraint = Null()
		} else if v == "notnull" {
			constraint = NotNull()
		} else if v == "unique" {
			constraint = Unique()
		} else if v == "key" {
			constraint = Key()
		} else if v == "index" {
			constraint = Index()
		} else if strings.Contains(v, "default") {
			constraint = Default(m.extractValue(v))
		} else {
			return nil, errors.New(fmt.Sprintf("Invalid constraint: %s", v))
		}

		//else if v == "primary_key" {
		//			constraint = PrimaryKey()
		//}

		//else if strings.Contains(v, "foreignkey") {
		//			tableColumnPair := strings.Split(m.extractValue(v), ".")
		//			if len(tableColumnPair) != 2 {
		//				return nil, errors.New("Invalid foreign key tag. It should be foreign_key(table.column)")
		//			}
		//			// returns unformatted foreign key with parametric name
		//			constraint = ForeignKey("%s", )
		//}

		//		fmt.Println("Matched constraint: ", constraint.Name)

		constraints = append(constraints, constraint)
	}

	return constraints, nil
}

func (m *Mapper) Convert(model interface{}) (*Table, error) {

	modelName := snaker.CamelToSnake(structs.Name(model))

	table := &Table{
		name:        modelName,
		columns:     []Column{},
		constraints: []Constraint{},
		builder:     NewBuilder(),
	}

	fmt.Printf("model name: %s\n\n", modelName)

	var col Column
	var rawTag string

	for _, f := range structs.Fields(model) {

		colName := snaker.CamelToSnake(f.Name())
		colType := fmt.Sprintf("%T", f.Value())

		rawTag = f.Tag(TAG)

		constraints := []Constraint{}
		fmt.Printf("field name: %s\n", colName)
		fmt.Printf("field raw tag: %s\n", rawTag)
		fmt.Printf("field type name: %T\n", f.Value())
		fmt.Printf("field constraints: %v\n", constraints)

		if colType != "qbit.PrimaryKey" && colType != "qbit.ForeignKey" {

			// clean trailing spaces of tag
			rawTag = strings.Replace(f.Tag(TAG), " ", "", 1)

			// parse tag
			tag, err := ParseTag(rawTag)
			if err != nil {
				return nil, err
			}

			// convert tag into constraints
			constraints, err = m.convertConstraints(tag.Constraints)
			if err != nil {
				return nil, err
			}

			fmt.Printf("field tag.Type: %s\n", tag.Type)
			fmt.Printf("field tag.Constraints: %v\n", tag.Constraints)

			col = Column{
				Name:        colName,
				Constraints: constraints,
				Type:        m.ConvertType(colType, tag.Type), // TODO: map type
			}

			table.AddColumn(col)

		} else if colType == "qbit.PrimaryKey" {

			table.AddConstraint(Constraint{
				Name: fmt.Sprintf("PRIMARY KEY (%s)", rawTag),
			})

		} else { // colType == "qbit.ForeignKey"

			rawTag = strings.Replace(rawTag, "references", "REFERENCES", 1)
			table.AddConstraint(Constraint{
				Name: fmt.Sprintf("FOREIGN KEY %s", rawTag),
			})
		}

		fmt.Println()
	}

	//	cols, err := m.convertColumns(structs.Fields(model))
	//	if err != nil {
	//		return nil, err
	//	}

	//	fmt.Println("cols: ", cols)

	return table, nil

	//	return NewTable(name, cols, []Constraint{}), nil
}
<commit_msg>remove unused const<commit_after>package qbit

import (
	//	"errors"
	"fmt"
	"github.com/fatih/structs"
	"github.com/serenize/snaker"
	//	"reflect"
	"strings"
	//	"errors"
	"errors"
)

const TAG = "qbit"

func NewMapper(driver string) *Mapper {
	return &Mapper{
		driver: driver,
	}
}

type Mapper struct {
	driver string
}

func (m *Mapper) extractValue(value string) string {

	hasParams := strings.Contains(value, "(") && strings.Contains(value, ")")

	if hasParams {
		startIndex := strings.Index(value, "(")
		endIndex := strings.Index(value, ")")
		return value[startIndex+1 : endIndex]
	}

	return ""
}

func (m *Mapper) ConvertType(colType string, tagType string) *Type {

	// convert tagType
	if tagType != "" {
		tagType = strings.ToUpper(tagType)
		return &Type{func() string { return tagType }}
	}

	// convert default type
	switch colType {
	case "string":
		return VarChar()
	case "int":
		return Int()
	case "int64":
		return BigInt()
	case "float32":
		return Float()
	case "float64":
		return Float()
	case "bool":
		return Boolean()
	case "uuid.UUID":
		if m.driver == "postgres" {
			return UUID()
		}
		return VarChar(36)
	case "time.Time":
		return Timestamp()
	case "*time.Time":
		return Timestamp()
	default:
		return VarChar()
	}
}

func (m *Mapper) convertConstraints(rawConstraints []string) ([]Constraint, error) {

	constraints := []Constraint{}

	var constraint Constraint
	for _, v := range rawConstraints {

		if v == "null" {
			constraint = Null()
		} else if v == "notnull" {
			constraint = NotNull()
		} else if v == "unique" {
			constraint = Unique()
		} else if v == "key" {
			constraint = Key()
		} else if v == "index" {
			constraint = Index()
		} else if strings.Contains(v, "default") {
			constraint = Default(m.extractValue(v))
		} else {
			return nil, errors.New(fmt.Sprintf("Invalid constraint: %s", v))
		}

		//else if v == "primary_key" {
		//			constraint = PrimaryKey()
		//}

		//else if strings.Contains(v, "foreignkey") {
		//			tableColumnPair := strings.Split(m.extractValue(v), ".")
		//			if len(tableColumnPair) != 2 {
		//				return nil, errors.New("Invalid foreign key tag. It should be foreign_key(table.column)")
		//			}
		//			// returns unformatted foreign key with parametric name
		//			constraint = ForeignKey("%s", )
		//}

		//		fmt.Println("Matched constraint: ", constraint.Name)

		constraints = append(constraints, constraint)
	}

	return constraints, nil
}

func (m *Mapper) Convert(model interface{}) (*Table, error) {

	modelName := snaker.CamelToSnake(structs.Name(model))

	table := &Table{
		name:        modelName,
		columns:     []Column{},
		constraints: []Constraint{},
		builder:     NewBuilder(),
	}

	fmt.Printf("model name: %s\n\n", modelName)

	var col Column
	var rawTag string

	for _, f := range structs.Fields(model) {

		colName := snaker.CamelToSnake(f.Name())
		colType := fmt.Sprintf("%T", f.Value())

		rawTag = f.Tag(TAG)

		constraints := []Constraint{}
		fmt.Printf("field name: %s\n", colName)
		fmt.Printf("field raw tag: %s\n", rawTag)
		fmt.Printf("field type name: %T\n", f.Value())
		fmt.Printf("field constraints: %v\n", constraints)

		if colType != "qbit.PrimaryKey" && colType != "qbit.ForeignKey" {

			// clean trailing spaces of tag
			rawTag = strings.Replace(f.Tag(TAG), " ", "", 1)

			// parse tag
			tag, err := ParseTag(rawTag)
			if err != nil {
				return nil, err
			}

			// convert tag into constraints
			constraints, err = m.convertConstraints(tag.Constraints)
			if err != nil {
				return nil, err
			}

			fmt.Printf("field tag.Type: %s\n", tag.Type)
			fmt.Printf("field tag.Constraints: %v\n", tag.Constraints)

			col = Column{
				Name:        colName,
				Constraints: constraints,
				Type:        m.ConvertType(colType, tag.Type), // TODO: map type
			}

			table.AddColumn(col)

		} else if colType == "qbit.PrimaryKey" {

			table.AddConstraint(Constraint{
				Name: fmt.Sprintf("PRIMARY KEY (%s)", rawTag),
			})

		} else { // colType == "qbit.ForeignKey"

			rawTag = strings.Replace(rawTag, "references", "REFERENCES", 1)
			table.AddConstraint(Constraint{
				Name: fmt.Sprintf("FOREIGN KEY %s", rawTag),
			})
		}

		fmt.Println()
	}

	//	cols, err := m.convertColumns(structs.Fields(model))
	//	if err != nil {
	//		return nil, err
	//	}

	//	fmt.Println("cols: ", cols)

	return table, nil

	//	return NewTable(name, cols, []Constraint{}), nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"bytes"
	"time"
    "crypto/rand"
    "encoding/base64"
    "github.com/bradfitz/gomemcache/memcache"
    "github.com/montanaflynn/stats"
)

func main() {
	mc := memcache.New("localhost:11211")
	n := 10000
	timeToSet := make([]float64, n)
	timeToGet := make([]float64, n)
	for i := 0; i < n; i++ {
		timeToSet[i], timeToGet[i] = measureSetAndGetTime(mc)
	}
	fmt.Printf("Set min: %v, max: %v, 90%%: %v, 99%%: %v \n",
		stats.Min(timeToSet), stats.Max(timeToSet),
		stats.Percentile(timeToSet, 90), stats.Percentile(timeToSet, 99))
	fmt.Printf("Get min: %v, max: %v, 90%%: %v, 99%%: %v \n",
		stats.Min(timeToGet), stats.Max(timeToGet),
		stats.Percentile(timeToGet, 90), stats.Percentile(timeToGet, 99))
}

func measureSetAndGetTime(mc *memcache.Client) (float64, float64) {

	// create key and value
	k := randStr(10)
	v := []byte(randStr(1024))

	// test setting
	start := time.Now().Nanosecond()
	mc.Set(&memcache.Item{Key: k, Value: v})
	timeToSet := float64((time.Now().Nanosecond() - start)) / 1000.0

	// test getting
	start = time.Now().Nanosecond()
	it, err := mc.Get(k)
        if err != nil {
		fmt.Printf("%v\n", err)
		os.Exit(1)
	}
	timeToGet := float64((time.Now().Nanosecond() - start)) / 1000.0

	// validate the value
	if !bytes.Equal(it.Value, v) {
		fmt.Printf("Wrong value: %v\n", it.Value)
		os.Exit(1)
	}
	return timeToSet, timeToGet
}

func randStr(l int) string {
	v := make([]byte, l)
	rand.Read(v)
	return base64.URLEncoding.EncodeToString(v)
}
<commit_msg>Formatted<commit_after>package main

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"github.com/bradfitz/gomemcache/memcache"
	"github.com/montanaflynn/stats"
	"os"
	"time"
)

func main() {
	mc := memcache.New("localhost:11211")
	n := 10000
	timeToSet := make([]float64, n)
	timeToGet := make([]float64, n)
	for i := 0; i < n; i++ {
		timeToSet[i], timeToGet[i] = measureSetAndGetTime(mc)
	}
	fmt.Printf("Set min: %v, max: %v, 90%%: %v, 99%%: %v \n",
		stats.Min(timeToSet), stats.Max(timeToSet),
		stats.Percentile(timeToSet, 90), stats.Percentile(timeToSet, 99))
	fmt.Printf("Get min: %v, max: %v, 90%%: %v, 99%%: %v \n",
		stats.Min(timeToGet), stats.Max(timeToGet),
		stats.Percentile(timeToGet, 90), stats.Percentile(timeToGet, 99))
}

func measureSetAndGetTime(mc *memcache.Client) (float64, float64) {

	// create key and value
	k := randStr(10)
	v := []byte(randStr(1024))

	// test setting
	start := time.Now().Nanosecond()
	mc.Set(&memcache.Item{Key: k, Value: v})
	timeToSet := float64((time.Now().Nanosecond() - start)) / 1000.0

	// test getting
	start = time.Now().Nanosecond()
	it, err := mc.Get(k)
	if err != nil {
		fmt.Printf("%v\n", err)
		os.Exit(1)
	}
	timeToGet := float64((time.Now().Nanosecond() - start)) / 1000.0

	// validate the value
	if !bytes.Equal(it.Value, v) {
		fmt.Printf("Wrong value: %v\n", it.Value)
		os.Exit(1)
	}
	return timeToSet, timeToGet
}

func randStr(l int) string {
	v := make([]byte, l)
	rand.Read(v)
	return base64.URLEncoding.EncodeToString(v)
}
<|endoftext|>


<commit_before>// Copyright © 2016 Aaron Longwell
//
// Use of this source code is governed by an MIT license.
// Details in the LICENSE file.

package trello

import (
	"fmt"
)

// Member represents a Trello member.
// https://developers.trello.com/reference/#member-object
type Member struct {
	client          *Client
	ID              string   `json:"id"`
	Username        string   `json:"username"`
	FullName        string   `json:"fullName"`
	Initials        string   `json:"initials"`
	AvatarHash      string   `json:"avatarHash"`
	Email           string   `json:"email"`
	IDBoards        []string `json:"idBoards"`
	IDOrganizations []string `json:"idOrganizations"`
}

// GetMember takes a member id and Arguments and returns a Member or an error.
func (c *Client) GetMember(memberID string, extraArgs ...Arguments) (member *Member, err error) {
	args := flattenArguments(extraArgs)
	path := fmt.Sprintf("members/%s", memberID)
	err = c.Get(path, args, &member)
	if err == nil {
		member.SetClient(c)
	}
	return
}

// GetMyMember returns Member for the user authenticating the API call
func (c *Client) GetMyMember(args Arguments) (member *Member, err error) {
	path := fmt.Sprintf("members/me")
	err = c.Get(path, args, &member)
	if err == nil {
		member.SetClient(c)
	}
	return
}

// GetMembers takes Arguments and returns a slice of all members of the organization or an error.
func (o *Organization) GetMembers(extraArgs ...Arguments) (members []*Member, err error) {
	args := flattenArguments(extraArgs)
	path := fmt.Sprintf("organizations/%s/members", o.ID)
	err = o.client.Get(path, args, &members)
	for i := range members {
		members[i].SetClient(o.client)
	}
	return
}

// GetMembers takes Arguments and returns a slice of all members of the Board or an error.
func (b *Board) GetMembers(extraArgs ...Arguments) (members []*Member, err error) {
	args := flattenArguments(extraArgs)
	path := fmt.Sprintf("boards/%s/members", b.ID)
	err = b.client.Get(path, args, &members)
	for i := range members {
		members[i].SetClient(b.client)
	}
	return
}

// GetMembers takes Arguments and returns a slice of all members of the Card or an error.
func (c *Card) GetMembers(extraArgs ...Arguments) (members []*Member, err error) {
	args := flattenArguments(extraArgs)
	path := fmt.Sprintf("cards/%s/members", c.ID)
	err = c.client.Get(path, args, &members)
	for i := range members {
		members[i].SetClient(c.client)
	}
	return
}

// SetClient can be used to override this Member's internal connection to the
// Trello API. Normally, this is set automatically after API calls.
func (m *Member) SetClient(newClient *Client) {
	m.client = newClient
}
<commit_msg>Remove unnecessary fmt.Sprintf.<commit_after>// Copyright © 2016 Aaron Longwell
//
// Use of this source code is governed by an MIT license.
// Details in the LICENSE file.

package trello

import (
	"fmt"
)

// Member represents a Trello member.
// https://developers.trello.com/reference/#member-object
type Member struct {
	client          *Client
	ID              string   `json:"id"`
	Username        string   `json:"username"`
	FullName        string   `json:"fullName"`
	Initials        string   `json:"initials"`
	AvatarHash      string   `json:"avatarHash"`
	Email           string   `json:"email"`
	IDBoards        []string `json:"idBoards"`
	IDOrganizations []string `json:"idOrganizations"`
}

// GetMember takes a member id and Arguments and returns a Member or an error.
func (c *Client) GetMember(memberID string, extraArgs ...Arguments) (member *Member, err error) {
	args := flattenArguments(extraArgs)
	path := fmt.Sprintf("members/%s", memberID)
	err = c.Get(path, args, &member)
	if err == nil {
		member.SetClient(c)
	}
	return
}

// GetMyMember returns Member for the user authenticating the API call
func (c *Client) GetMyMember(args Arguments) (member *Member, err error) {
	path := "members/me"
	err = c.Get(path, args, &member)
	if err == nil {
		member.SetClient(c)
	}
	return
}

// GetMembers takes Arguments and returns a slice of all members of the organization or an error.
func (o *Organization) GetMembers(extraArgs ...Arguments) (members []*Member, err error) {
	args := flattenArguments(extraArgs)
	path := fmt.Sprintf("organizations/%s/members", o.ID)
	err = o.client.Get(path, args, &members)
	for i := range members {
		members[i].SetClient(o.client)
	}
	return
}

// GetMembers takes Arguments and returns a slice of all members of the Board or an error.
func (b *Board) GetMembers(extraArgs ...Arguments) (members []*Member, err error) {
	args := flattenArguments(extraArgs)
	path := fmt.Sprintf("boards/%s/members", b.ID)
	err = b.client.Get(path, args, &members)
	for i := range members {
		members[i].SetClient(b.client)
	}
	return
}

// GetMembers takes Arguments and returns a slice of all members of the Card or an error.
func (c *Card) GetMembers(extraArgs ...Arguments) (members []*Member, err error) {
	args := flattenArguments(extraArgs)
	path := fmt.Sprintf("cards/%s/members", c.ID)
	err = c.client.Get(path, args, &members)
	for i := range members {
		members[i].SetClient(c.client)
	}
	return
}

// SetClient can be used to override this Member's internal connection to the
// Trello API. Normally, this is set automatically after API calls.
func (m *Member) SetClient(newClient *Client) {
	m.client = newClient
}
<|endoftext|>


<commit_before>package distnano

import (
	"encoding/json"
	"fmt"
	"log"
)

type Child struct {
	Path     []uint  `json:"path,omitempty"`
	X        *int    `json:"x,omitempty"`
	Y        *int    `json:"y,omitempty"`
	Val      *int    `json:"val,omitempty"`
	Children []Child `json:"children,omitempty"`
}

type Root struct {
	Val      *int    `json:"val,omitempty"`
	Children []Child `json:"children,omitempty"`
}

type NanocubeResponse struct {
	Layers []string `json:"layers"`
	Root   Root     `json:"root"`
}

// asKey is a function that encodes c's path or x and y values as a string to
// be used as a key in a map. This is necessary to produce quick aggregations
// on keys.
func (c Child) asKey() string {
	// Want to ignore val.
	c.Val = nil
	b, err := json.Marshal(c)
	if err != nil {
		log.Fatalf("Got %v encoding child %v", err, c)
	}
	return string(b)
}

// TODO(asubiotto): The whole error handling has to be looked at more closely.

// mergeChildren merges the children array by aggregating "val"s at the base
// level and using either path as key or x and y as keys.
func mergeChildren(dest, src []Child) []Child {
	if dest == nil || src == nil {
		if dest == nil {
			return src
		}
		return dest
	}

	// Store pointers to children accesible by key.
	destMap := make(map[string]*Child)
	for i, child := range dest {
		destMap[child.asKey()] = &dest[i]
	}

	// For each child in src, merge with the destMap.
	for i, child := range src {
		key := child.asKey()

		// If the key already exists in the map, we want to merge with that
		// key. Otherwise, we simply add it.
		if _, e := destMap[key]; e {
			// If the child doesn't have a Val, it necessarily has something in
			// its []Child field. We therefore initiate a recursive merge.
			// Otherwise, the semantics of merging is to add to the value.
			if child.Val == nil {
				destMap[key].Children =
					mergeChildren(destMap[key].Children, child.Children)
			} else {
				*(destMap[key].Val) += *(child.Val)
			}
		} else {
			destMap[key] = &src[i]
		}
	}

	// We now want to create a new []Child slice from our [string]*Child map.
	result := make([]Child, 0, len(destMap))

	for _, v := range destMap {
		// Note that result is not reallocated on each iteration because its
		// capacity was specified.
		result = append(result, *v)
	}

	return result
}

// merge merges src into dest according to the API.md document found in
// github.com/laurolins/nanocube.
func merge(dest, src *NanocubeResponse) {
	// Little check for layers. TODO(asubiotto): Think about this case a bit
	// more when we have empty responses or we want to return an error.
	if dest.Layers == nil {
		dest.Layers = []string{}
	}

	if dest.Root.Val != nil {
		*(dest.Root.Val) += *(src.Root.Val)
		return
	}

	b, _ := json.Marshal(dest)
	b1, _ := json.Marshal(src)
	fmt.Printf("Merging children %v and %v\n\n", string(b), string(b1))
	dest.Root.Children = mergeChildren(dest.Root.Children, src.Root.Children)
	b, _ = json.Marshal(dest)
	fmt.Printf("Got: %v\n\n\n\n", string(b))
}
<commit_msg>Stable merger file for most queries. Working on server next and visualizer<commit_after>package distnano

import (
	"encoding/json"
	"log"
)

type Child struct {
	Path     []uint  `json:"path,omitempty"`
	X        *int    `json:"x,omitempty"`
	Y        *int    `json:"y,omitempty"`
	Val      *int    `json:"val,omitempty"`
	Children []Child `json:"children,omitempty"`
}

type Root struct {
	Val      *int    `json:"val,omitempty"`
	Children []Child `json:"children,omitempty"`
}

type NanocubeResponse struct {
	Layers []string `json:"layers"`
	Root   Root     `json:"root"`
}

// asKey is a function that encodes c's path or x and y values as a string to
// be used as a key in a map. This is necessary to produce quick aggregations
// on keys.
func (c Child) asKey() string {
	// Want to ignore val.
	c.Val = nil
	b, err := json.Marshal(c)
	if err != nil {
		log.Fatalf("Got %v encoding child %v", err, c)
	}
	return string(b)
}

// mergeChildren merges the children array by aggregating "val"s at the base
// level and using either path as key or x and y as keys.
func mergeChildren(dest, src []Child) []Child {
	if dest == nil || src == nil {
		if dest == nil {
			return src
		}
		return dest
	}

	// Store pointers to children accesible by key.
	destMap := make(map[string]*Child)
	for i, child := range dest {
		destMap[child.asKey()] = &dest[i]
	}

	// For each child in src, merge with the destMap.
	for i, child := range src {
		key := child.asKey()

		// If the key already exists in the map, we want to merge with that
		// key. Otherwise, we simply add it.
		if _, e := destMap[key]; e {
			// If the child doesn't have a Val, it necessarily has something in
			// its []Child field. We therefore initiate a recursive merge.
			// Otherwise, the semantics of merging is to add to the value.
			if child.Val == nil {
				destMap[key].Children =
					mergeChildren(destMap[key].Children, child.Children)
			} else {
				*(destMap[key].Val) += *(child.Val)
			}
		} else {
			destMap[key] = &src[i]
		}
	}

	// We now want to create a new []Child slice from our [string]*Child map.
	result := make([]Child, 0, len(destMap))

	for _, v := range destMap {
		// Note that result is not reallocated on each iteration because its
		// capacity was specified.
		result = append(result, *v)
	}

	return result
}

// merge merges src into dest according to the API.md document found in
// github.com/laurolins/nanocube.
func merge(dest, src *NanocubeResponse) {
	if dest.Layers == nil {
		dest.Layers = []string{}
	}

	if dest.Root.Val != nil {
		*(dest.Root.Val) += *(src.Root.Val)
		return
	}

	dest.Root.Children = mergeChildren(dest.Root.Children, src.Root.Children)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	cRand "crypto/rand"
	"errors"
	"flag"
	"fmt"
	"math/big"
	mRand "math/rand"
	"os"
	"regexp"
	"strings"
)

const Version = "0.0.1"

/* Reads a file of words, filters the words and returns an array of words.
 *
 * path: Path to the file to read (each line is a different word)
 * minLen: The minumum length of the words. Any words shorter than the minimum
 *         length are filtered out.
 */
func readDict(path string, minLen int) ([]string, error) {
	// Build the regexp to use as the filter
	filterRegexp := fmt.Sprintf("^[[:word:]]{%d,}$", minLen)
	validWord := regexp.MustCompile(filterRegexp)

	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		var line = scanner.Text()
		// Filter out invalid lines
		if validWord.MatchString(line) {
			lines = append(lines, line)
		}
	}
	return lines, scanner.Err()
}

/* Returns a random string from the passed array
 *
 * dict: The array of string.
 */
func getRandomWord(dict []string) (string, error) {
	max := len(dict)
	if max < 1 {
		return "", errors.New("No words in the dict")
	}
	rand_index := mRand.Intn(max)

	word := dict[rand_index]

	return word, nil
}

/* Returns an array of the passed length containing randoms words from the
 * passed array.
 *
 * dict: The array of words.
 * numberOfWords: THe number of strings to return.
 */
func genPassword(dict []string, numberOfWords int) ([]string, error) {
	var words []string

	if numberOfWords < 1 {
		return []string{}, errors.New("Need a positive number of words")
	}

	for i := 0; i < numberOfWords; i++ {
		word, err := getRandomWord(dict)
		if err != nil {
			return []string{}, err
		}
		words = append(words, word)
	}
	return words, nil
}

func init() {
	// Seed math/rand using crypto/rand
	max := *big.NewInt(9223372036854775807)

	seed, err := cRand.Int(cRand.Reader, &max)
	if err != nil {
		fmt.Println("Unable to seed the random number generator")
		fmt.Println(err)
		os.Exit(1)
	}

	mRand.Seed(seed.Int64())
}

func main() {
	// Parse Arguments
	var numberOfWords, minLenOfWords int
	var wordFile string
	var showVersion bool

	flag.IntVar(&numberOfWords, "n", 4, "The number of words to generate")
	flag.IntVar(&minLenOfWords, "l", 6, "The minimum lenght of each word")
	flag.StringVar(&wordFile, "f", "/usr/share/dict/words", "A file that contains possible words (one per line)")
	flag.BoolVar(&showVersion, "v", false, "Show the version")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s version %s\n", os.Args[0], Version)
		fmt.Fprintf(os.Stderr, "Usage: %s [options]\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "\nOptions\n")
		flag.PrintDefaults()
	}

	flag.Parse()

	if showVersion {
		fmt.Println(Version)
		os.Exit(0)
	}

	// Go to Work
	dict, err := readDict(wordFile, minLenOfWords)
	if err != nil {
		fmt.Printf("Unable to read words from '%s'\n", wordFile)
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Printf("Choosing from %d words\n", len(dict))

	words, err := genPassword(dict, numberOfWords)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Return the result
	fmt.Println("Your words are: ")
	fmt.Println(strings.Join(words, " "))
}
<commit_msg>Small corrections.<commit_after>package main

import (
	"bufio"
	cRand "crypto/rand"
	"errors"
	"flag"
	"fmt"
	"math/big"
	mRand "math/rand"
	"os"
	"regexp"
	"strings"
)

const Version = "0.0.1"

/* Reads a file of words, filters the words and returns an array of words.
 *
 * path: Path to the file to read (each line is a different word)
 * minLen: The minumum length of the words. Any words shorter than the minimum
 *         length are filtered out.
 */
func readDict(path string, minLen int) ([]string, error) {
	// Build the regexp to use as the filter
	filterRegexp := fmt.Sprintf("^[[:word:]]{%d,}$", minLen)
	validWord := regexp.MustCompile(filterRegexp)

	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		var line = scanner.Text()
		// Filter out invalid lines
		if validWord.MatchString(line) {
			lines = append(lines, line)
		}
	}
	return lines, scanner.Err()
}

/* Returns a random string from the passed array
 *
 * dict: The array of string.
 */
func getRandomWord(dict []string) (string, error) {
	max := len(dict)
	if max < 1 {
		return "", errors.New("No words in the dict")
	}
	rand_index := mRand.Intn(max)

	word := dict[rand_index]

	return word, nil
}

/* Returns an array of the passed length containing randoms words from the
 * passed array.
 *
 * dict: The array of words.
 * numberOfWords: THe number of strings to return.
 */
func genPassword(dict []string, numberOfWords int) ([]string, error) {
	var words []string

	if numberOfWords < 1 {
		return []string{}, errors.New("Need a positive number of words")
	}

	for i := 0; i < numberOfWords; i++ {
		word, err := getRandomWord(dict)
		if err != nil {
			return []string{}, err
		}
		words = append(words, word)
	}
	return words, nil
}

func init() {
	// Seed math/rand using crypto/rand
	max := *big.NewInt(9223372036854775807) // largest int64

	seed, err := cRand.Int(cRand.Reader, &max)
	if err != nil {
		fmt.Println("Unable to seed the random number generator")
		fmt.Println(err)
		os.Exit(1)
	}

	mRand.Seed(seed.Int64())
}

func main() {
	// Parse Arguments
	var numberOfWords, minLenOfWords int
	var wordFile string
	var showVersion bool

	flag.IntVar(&numberOfWords, "n", 4, "The number of words to generate")
	flag.IntVar(&minLenOfWords, "l", 6, "The minimum lenght of each word")
	flag.StringVar(&wordFile, "f", "/usr/share/dict/words", "A file that contains possible words (one per line)")
	flag.BoolVar(&showVersion, "v", false, "Display the version")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s version %s\n", os.Args[0], Version)
		fmt.Fprintf(os.Stderr, "Usage: %s [options]\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "\nOptions\n")
		flag.PrintDefaults()
	}

	flag.Parse()

	if showVersion {
		fmt.Println(Version)
		os.Exit(0)
	}

	// Go to Work
	dict, err := readDict(wordFile, minLenOfWords)
	if err != nil {
		fmt.Printf("Unable to read words from '%s'\n", wordFile)
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Printf("Choosing from %d words\n", len(dict))

	words, err := genPassword(dict, numberOfWords)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Return the result
	fmt.Println("Your words are:")
	fmt.Println(strings.Join(words, " "))
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/md5"
	"encoding/gob"
	"fmt"
	"io"
	"net/http"

	log "github.com/Sirupsen/logrus"
	"io/ioutil"
)

// DBClient provides access to cache, http client and configuration
type DBClient struct {
	cache Cache
	http  *http.Client
	cfg   *Configuration
}

// request holds structure for request
type request struct {
	details requestDetails
}

var emptyResp = &http.Response{}

// requestDetails stores information about request, it's used for creating unique hash and also as a payload structure
type requestDetails struct {
	Path        string              `json:"path"`
	Method      string              `json:"method"`
	Destination string              `json:"destination"`
	Scheme      string              `json:"scheme"`
	Query       string              `json:"query"`
	Body        string              `json:"body"`
	RemoteAddr  string              `json:"remoteAddr"`
	Headers     map[string][]string `json:"headers"`
}

func (r *request) concatenate() string {
	var buffer bytes.Buffer

	buffer.WriteString(r.details.Destination)
	buffer.WriteString(r.details.Path)
	buffer.WriteString(r.details.Method)
	buffer.WriteString(r.details.Query)
	buffer.WriteString(r.details.Body)

	return buffer.String()
}

// hash returns unique hash key for request
func (r *request) hash() string {
	h := md5.New()
	io.WriteString(h, r.concatenate())
	return fmt.Sprintf("%x", h.Sum(nil))
}

// res structure hold response body from external service, body is not decoded and is supposed
// to be bytes, however headers should provide all required information for later decoding
// by the client.
type response struct {
	Status  int                 `json:"status"`
	Body    string              `json:"body"`
	Headers map[string][]string `json:"headers"`
}

// Payload structure holds request and response structure
type Payload struct {
	Response response       `json:"response"`
	Request  requestDetails `json:"request"`
	ID       string         `json:"id"`
}

// encode method encodes all exported Payload fields to bytes
func (p *Payload) encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	enc := gob.NewEncoder(buf)
	err := enc.Encode(p)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// decodePayload decodes supplied bytes into Payload structure
func decodePayload(data []byte) (*Payload, error) {
	var p *Payload
	buf := bytes.NewBuffer(data)
	dec := gob.NewDecoder(buf)
	err := dec.Decode(&p)
	if err != nil {
		return nil, err
	}
	return p, nil
}

// captureRequest saves request for later playback
func (d *DBClient) captureRequest(req *http.Request) (*http.Response, error) {

	// this is mainly for testing, since when you create
	if req.Body == nil {
		req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte("")))
	}

	reqBody, err := ioutil.ReadAll(req.Body)

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
			"mode":  "capture",
		}).Error("Got error when reading request body")
	}

	// outputting request body if verbose logging is set
	log.WithFields(log.Fields{
		"body": string(reqBody),
		"mode": "capture",
	}).Debug("got request body")

	req.Body = ioutil.NopCloser(bytes.NewBuffer(reqBody))

	// forwarding request
	resp, err := d.doRequest(req)

	if err == nil {
		respBody, err := extractBody(resp)

		if err != nil {

			log.WithFields(log.Fields{
				"error": err.Error(),
				"mode":  "capture",
			}).Error("Failed to copy response body.")

			return resp, err
		}

		// saving response body with request/response meta to cache
		d.save(req, reqBody, resp, respBody)
	}

	// return new response or error here
	return resp, err
}

func copyBody(body io.ReadCloser) (resp1, resp2 io.ReadCloser, err error) {
	var buf bytes.Buffer
	if _, err = buf.ReadFrom(body); err != nil {
		return nil, nil, err
	}
	if err = body.Close(); err != nil {
		return nil, nil, err
	}
	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
}

func extractBody(resp *http.Response) (extract []byte, err error) {
	save := resp.Body
	savecl := resp.ContentLength

	save, resp.Body, err = copyBody(resp.Body)

	if err != nil {
		return
	}
	defer resp.Body.Close()
	extract, err = ioutil.ReadAll(resp.Body)

	resp.Body = save
	resp.ContentLength = savecl
	if err != nil {
		return nil, err
	}
	return extract, nil
}

// doRequest performs original request and returns response that should be returned to client and error (if there is one)
func (d *DBClient) doRequest(request *http.Request) (*http.Response, error) {

	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	request.RequestURI = ""

	if d.cfg.middleware != "" {
		var payload Payload

		c := NewConstructor(request, payload)
		err := c.ApplyMiddleware(d.cfg.middleware)

		if err != nil {
			log.WithFields(log.Fields{
				"mode":   d.cfg.mode,
				"error":  err.Error(),
				"host":   request.Host,
				"method": request.Method,
				"path":   request.URL.Path,
			}).Error("could not forward request, middleware failed to modify request.")
			return nil, err
		}

		request, err = c.reconstructRequest()
		if err != nil {
			return nil, err
		}
	}

	resp, err := d.http.Do(request)

	if err != nil {
		log.WithFields(log.Fields{
			"mode":   d.cfg.mode,
			"error":  err.Error(),
			"host":   request.Host,
			"method": request.Method,
			"path":   request.URL.Path,
		}).Error("could not forward request, failed to do an HTTP request.")
		return nil, err
	}

	log.WithFields(log.Fields{
		"mode":   d.cfg.mode,
		"host":   request.Host,
		"method": request.Method,
		"path":   request.URL.Path,
	}).Debug("response from external service got successfuly!")

	resp.Header.Set("hoverfly", "Was-Here")
	return resp, nil

}

// save gets request fingerprint, extracts request body, status code and headers, then saves it to cache
func (d *DBClient) save(req *http.Request, reqBody []byte, resp *http.Response, respBody []byte) {
	// record request here
	key := getRequestFingerprint(req, reqBody)

	if resp == nil {
		resp = emptyResp
	} else {
		responseObj := response{
			Status:  resp.StatusCode,
			Body:    string(respBody),
			Headers: resp.Header,
		}

		log.WithFields(log.Fields{
			"path":          req.URL.Path,
			"rawQuery":      req.URL.RawQuery,
			"requestMethod": req.Method,
			"bodyLen":       len(reqBody),
			"destination":   req.Host,
			"hashKey":       key,
		}).Debug("Capturing")

		requestObj := requestDetails{
			Path:        req.URL.Path,
			Method:      req.Method,
			Destination: req.Host,
			Scheme:      req.URL.Scheme,
			Query:       req.URL.RawQuery,
			Body:        string(reqBody),
			RemoteAddr:  req.RemoteAddr,
			Headers:     req.Header,
		}

		payload := Payload{
			Response: responseObj,
			Request:  requestObj,
			ID:       key,
		}

		bts, err := payload.encode()
		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
			}).Error("Failed to serialize payload")
		} else {
			d.cache.Set([]byte(key), bts)
		}
	}
}

// getRequestFingerprint returns request hash
func getRequestFingerprint(req *http.Request, requestBody []byte) string {
	details := requestDetails{
		Path:        req.URL.Path,
		Method:      req.Method,
		Destination: req.Host,
		Query:       req.URL.RawQuery,
		Body:        string(requestBody),
	}

	r := request{details: details}
	return r.hash()
}

// getResponse returns stored response from cache
func (d *DBClient) getResponse(req *http.Request) *http.Response {

	if req.Body == nil {
		req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte("")))
	}

	reqBody, err := ioutil.ReadAll(req.Body)

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Got error when reading request body")
	}

	key := getRequestFingerprint(req, reqBody)

	payloadBts, err := d.cache.Get([]byte(key))

	if err == nil {
		// getting cache response
		payload, err := decodePayload(payloadBts)
		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
				"value": string(payloadBts),
				"key":   key,
			}).Error("Failed to decode payload")
			return hoverflyError(req, err, "Failed to virtualize", http.StatusInternalServerError)
		}

		c := NewConstructor(req, *payload)

		if d.cfg.middleware != "" {
			_ = c.ApplyMiddleware(d.cfg.middleware)
		}

		response := c.reconstructResponse()

		log.WithFields(log.Fields{
			"key":         key,
			"mode":        "virtualize",
			"middleware":  d.cfg.middleware,
			"path":        req.URL.Path,
			"rawQuery":    req.URL.RawQuery,
			"method":      req.Method,
			"destination": req.Host,
			"status":      payload.Response.Status,
			"bodyLength":  response.ContentLength,
		}).Info("Response found, returning")

		return response

	}

	log.WithFields(log.Fields{
		"key":         key,
		"error":       err.Error(),
		"query":       req.URL.RawQuery,
		"path":        req.URL.RawPath,
		"destination": req.Host,
		"method":      req.Method,
	}).Warn("Failed to retrieve response from cache")
	// return error? if we return nil - proxy forwards request to original destination
	return hoverflyError(req, err, "Could not find recorded request, please record it first!", http.StatusPreconditionFailed)
}

// modifyRequestResponse modifies outgoing request and then modifies incoming response, neither request nor response
// is saved to cache.
func (d *DBClient) modifyRequestResponse(req *http.Request, middleware string) (*http.Response, error) {

	// modifying request
	resp, err := d.doRequest(req)

	if err != nil {
		return nil, err
	}

	// preparing payload
	bodyBytes, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		log.WithFields(log.Fields{
			"error":      err.Error(),
			"middleware": middleware,
		}).Error("Failed to read response body after sending modified request")
		return nil, err
	}

	r := response{
		Status:  resp.StatusCode,
		Body:    string(bodyBytes),
		Headers: resp.Header,
	}
	payload := Payload{Response: r}

	c := NewConstructor(req, payload)
	// applying middleware to modify response
	err = c.ApplyMiddleware(middleware)

	if err != nil {
		return nil, err
	}

	newResponse := c.reconstructResponse()

	log.WithFields(log.Fields{
		"status":      newResponse.StatusCode,
		"middleware":  middleware,
		"mode":        "modify",
		"path":        c.payload.Request.Path,
		"rawQuery":    c.payload.Request.Query,
		"method":      c.payload.Request.Method,
		"destination": c.payload.Request.Destination,
		// original here
		"originalPath":        req.URL.Path,
		"originalRawQuery":    req.URL.RawQuery,
		"originalMethod":      req.Method,
		"originalDestination": req.Host,
	}).Info("request and response modified, returning")

	return newResponse, nil

}
<commit_msg>config updated<commit_after>package main

import (
	"bytes"
	"crypto/md5"
	"encoding/gob"
	"fmt"
	"io"
	"net/http"

	log "github.com/Sirupsen/logrus"
	"io/ioutil"
)

// DBClient provides access to cache, http client and configuration
type DBClient struct {
	cache   Cache
	http    *http.Client
	cfg     *Configuration
	counter *CounterByMode
}

// request holds structure for request
type request struct {
	details requestDetails
}

var emptyResp = &http.Response{}

// requestDetails stores information about request, it's used for creating unique hash and also as a payload structure
type requestDetails struct {
	Path        string              `json:"path"`
	Method      string              `json:"method"`
	Destination string              `json:"destination"`
	Scheme      string              `json:"scheme"`
	Query       string              `json:"query"`
	Body        string              `json:"body"`
	RemoteAddr  string              `json:"remoteAddr"`
	Headers     map[string][]string `json:"headers"`
}

func (r *request) concatenate() string {
	var buffer bytes.Buffer

	buffer.WriteString(r.details.Destination)
	buffer.WriteString(r.details.Path)
	buffer.WriteString(r.details.Method)
	buffer.WriteString(r.details.Query)
	buffer.WriteString(r.details.Body)

	return buffer.String()
}

// hash returns unique hash key for request
func (r *request) hash() string {
	h := md5.New()
	io.WriteString(h, r.concatenate())
	return fmt.Sprintf("%x", h.Sum(nil))
}

// res structure hold response body from external service, body is not decoded and is supposed
// to be bytes, however headers should provide all required information for later decoding
// by the client.
type response struct {
	Status  int                 `json:"status"`
	Body    string              `json:"body"`
	Headers map[string][]string `json:"headers"`
}

// Payload structure holds request and response structure
type Payload struct {
	Response response       `json:"response"`
	Request  requestDetails `json:"request"`
	ID       string         `json:"id"`
}

// encode method encodes all exported Payload fields to bytes
func (p *Payload) encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	enc := gob.NewEncoder(buf)
	err := enc.Encode(p)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// decodePayload decodes supplied bytes into Payload structure
func decodePayload(data []byte) (*Payload, error) {
	var p *Payload
	buf := bytes.NewBuffer(data)
	dec := gob.NewDecoder(buf)
	err := dec.Decode(&p)
	if err != nil {
		return nil, err
	}
	return p, nil
}

// captureRequest saves request for later playback
func (d *DBClient) captureRequest(req *http.Request) (*http.Response, error) {

	// this is mainly for testing, since when you create
	if req.Body == nil {
		req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte("")))
	}

	reqBody, err := ioutil.ReadAll(req.Body)

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
			"mode":  "capture",
		}).Error("Got error when reading request body")
	}

	// outputting request body if verbose logging is set
	log.WithFields(log.Fields{
		"body": string(reqBody),
		"mode": "capture",
	}).Debug("got request body")

	req.Body = ioutil.NopCloser(bytes.NewBuffer(reqBody))

	// forwarding request
	resp, err := d.doRequest(req)

	if err == nil {
		respBody, err := extractBody(resp)

		if err != nil {

			log.WithFields(log.Fields{
				"error": err.Error(),
				"mode":  "capture",
			}).Error("Failed to copy response body.")

			return resp, err
		}

		// saving response body with request/response meta to cache
		d.save(req, reqBody, resp, respBody)
	}

	// return new response or error here
	return resp, err
}

func copyBody(body io.ReadCloser) (resp1, resp2 io.ReadCloser, err error) {
	var buf bytes.Buffer
	if _, err = buf.ReadFrom(body); err != nil {
		return nil, nil, err
	}
	if err = body.Close(); err != nil {
		return nil, nil, err
	}
	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
}

func extractBody(resp *http.Response) (extract []byte, err error) {
	save := resp.Body
	savecl := resp.ContentLength

	save, resp.Body, err = copyBody(resp.Body)

	if err != nil {
		return
	}
	defer resp.Body.Close()
	extract, err = ioutil.ReadAll(resp.Body)

	resp.Body = save
	resp.ContentLength = savecl
	if err != nil {
		return nil, err
	}
	return extract, nil
}

// doRequest performs original request and returns response that should be returned to client and error (if there is one)
func (d *DBClient) doRequest(request *http.Request) (*http.Response, error) {

	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	request.RequestURI = ""

	if d.cfg.middleware != "" {
		var payload Payload

		c := NewConstructor(request, payload)
		err := c.ApplyMiddleware(d.cfg.middleware)

		if err != nil {
			log.WithFields(log.Fields{
				"mode":   d.cfg.mode,
				"error":  err.Error(),
				"host":   request.Host,
				"method": request.Method,
				"path":   request.URL.Path,
			}).Error("could not forward request, middleware failed to modify request.")
			return nil, err
		}

		request, err = c.reconstructRequest()
		if err != nil {
			return nil, err
		}
	}

	resp, err := d.http.Do(request)

	if err != nil {
		log.WithFields(log.Fields{
			"mode":   d.cfg.mode,
			"error":  err.Error(),
			"host":   request.Host,
			"method": request.Method,
			"path":   request.URL.Path,
		}).Error("could not forward request, failed to do an HTTP request.")
		return nil, err
	}

	log.WithFields(log.Fields{
		"mode":   d.cfg.mode,
		"host":   request.Host,
		"method": request.Method,
		"path":   request.URL.Path,
	}).Debug("response from external service got successfuly!")

	resp.Header.Set("hoverfly", "Was-Here")
	return resp, nil

}

// save gets request fingerprint, extracts request body, status code and headers, then saves it to cache
func (d *DBClient) save(req *http.Request, reqBody []byte, resp *http.Response, respBody []byte) {
	// record request here
	key := getRequestFingerprint(req, reqBody)

	if resp == nil {
		resp = emptyResp
	} else {
		responseObj := response{
			Status:  resp.StatusCode,
			Body:    string(respBody),
			Headers: resp.Header,
		}

		log.WithFields(log.Fields{
			"path":          req.URL.Path,
			"rawQuery":      req.URL.RawQuery,
			"requestMethod": req.Method,
			"bodyLen":       len(reqBody),
			"destination":   req.Host,
			"hashKey":       key,
		}).Debug("Capturing")

		requestObj := requestDetails{
			Path:        req.URL.Path,
			Method:      req.Method,
			Destination: req.Host,
			Scheme:      req.URL.Scheme,
			Query:       req.URL.RawQuery,
			Body:        string(reqBody),
			RemoteAddr:  req.RemoteAddr,
			Headers:     req.Header,
		}

		payload := Payload{
			Response: responseObj,
			Request:  requestObj,
			ID:       key,
		}

		bts, err := payload.encode()
		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
			}).Error("Failed to serialize payload")
		} else {
			d.cache.Set([]byte(key), bts)
		}
	}
}

// getRequestFingerprint returns request hash
func getRequestFingerprint(req *http.Request, requestBody []byte) string {
	details := requestDetails{
		Path:        req.URL.Path,
		Method:      req.Method,
		Destination: req.Host,
		Query:       req.URL.RawQuery,
		Body:        string(requestBody),
	}

	r := request{details: details}
	return r.hash()
}

// getResponse returns stored response from cache
func (d *DBClient) getResponse(req *http.Request) *http.Response {

	if req.Body == nil {
		req.Body = ioutil.NopCloser(bytes.NewBuffer([]byte("")))
	}

	reqBody, err := ioutil.ReadAll(req.Body)

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Got error when reading request body")
	}

	key := getRequestFingerprint(req, reqBody)

	payloadBts, err := d.cache.Get([]byte(key))

	if err == nil {
		// getting cache response
		payload, err := decodePayload(payloadBts)
		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
				"value": string(payloadBts),
				"key":   key,
			}).Error("Failed to decode payload")
			return hoverflyError(req, err, "Failed to virtualize", http.StatusInternalServerError)
		}

		c := NewConstructor(req, *payload)

		if d.cfg.middleware != "" {
			_ = c.ApplyMiddleware(d.cfg.middleware)
		}

		response := c.reconstructResponse()

		log.WithFields(log.Fields{
			"key":         key,
			"mode":        "virtualize",
			"middleware":  d.cfg.middleware,
			"path":        req.URL.Path,
			"rawQuery":    req.URL.RawQuery,
			"method":      req.Method,
			"destination": req.Host,
			"status":      payload.Response.Status,
			"bodyLength":  response.ContentLength,
		}).Info("Response found, returning")

		return response

	}

	log.WithFields(log.Fields{
		"key":         key,
		"error":       err.Error(),
		"query":       req.URL.RawQuery,
		"path":        req.URL.RawPath,
		"destination": req.Host,
		"method":      req.Method,
	}).Warn("Failed to retrieve response from cache")
	// return error? if we return nil - proxy forwards request to original destination
	return hoverflyError(req, err, "Could not find recorded request, please record it first!", http.StatusPreconditionFailed)
}

// modifyRequestResponse modifies outgoing request and then modifies incoming response, neither request nor response
// is saved to cache.
func (d *DBClient) modifyRequestResponse(req *http.Request, middleware string) (*http.Response, error) {

	// modifying request
	resp, err := d.doRequest(req)

	if err != nil {
		return nil, err
	}

	// preparing payload
	bodyBytes, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		log.WithFields(log.Fields{
			"error":      err.Error(),
			"middleware": middleware,
		}).Error("Failed to read response body after sending modified request")
		return nil, err
	}

	r := response{
		Status:  resp.StatusCode,
		Body:    string(bodyBytes),
		Headers: resp.Header,
	}
	payload := Payload{Response: r}

	c := NewConstructor(req, payload)
	// applying middleware to modify response
	err = c.ApplyMiddleware(middleware)

	if err != nil {
		return nil, err
	}

	newResponse := c.reconstructResponse()

	log.WithFields(log.Fields{
		"status":      newResponse.StatusCode,
		"middleware":  middleware,
		"mode":        "modify",
		"path":        c.payload.Request.Path,
		"rawQuery":    c.payload.Request.Query,
		"method":      c.payload.Request.Method,
		"destination": c.payload.Request.Destination,
		// original here
		"originalPath":        req.URL.Path,
		"originalRawQuery":    req.URL.RawQuery,
		"originalMethod":      req.Method,
		"originalDestination": req.Host,
	}).Info("request and response modified, returning")

	return newResponse, nil

}
<|endoftext|>


<commit_before><commit_msg>Add changes<commit_after>// Stacker Pentecost: Haven't you heard Mr. Beckett? The world is coming to an end.
// So where would you rather die? Here? Or in a Jaeger!

package main

import (
	"flag"
	"fmt"

	"bytes"
	"code.google.com/p/go.crypto/openpgp"
	"encoding/base64"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

const jaegerTemplateExtension = ".jgrt"
const jaegerJSONGPGDBExtension = ".jgrdb"

func decryptBase64EncryptedMessage(s string, keyring openpgp.KeyRing) {
	// Decrypt base64 encoded encrypted message using decrypted private key
	dec, err := base64.StdEncoding.DecodeString(s)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	md, err := openpgp.ReadMessage(bytes.NewBuffer(dec), keyring, nil /* no prompt */, nil)
	if err != nil {
		fmt.Println("error reading message", err)
	}

	bytes, err := ioutil.ReadAll(md.UnverifiedBody)
	fmt.Println("md:", string(bytes))
}

func main() {
	// Define flags
	var (
		inputTemplate     = flag.String("i", "", "Input Template file. eg. file.txt.jgrt")
		jsonGPGDB         = flag.String("j", "", "JSON GPG database file. eg. file.txt.jgrdb")
		outputFile        = flag.String("o", "", "Output file. eg. file.txt")
		keyringFile       = flag.String("k", "", "Keyring file. Secret key in armor format. eg. secret.asc")
		passphraseKeyring = flag.String("p", "", "Passphrase for keyring. If this is not set the passphrase will be blank of read from the environment variable PASSPHRASE.")
	)
	// Parse
	// Any additional non-flag arguments can be retrieved with flag.Args() which returns a []string.
	flag.Parse()

	if *inputTemplate == "" {
		flag.Usage()
		log.Fatalf("\n\nError: No input file specified")
		return
	}

	// TODO: Handle reading from default keyring
	if *keyringFile == "" {
		flag.Usage()
		log.Fatalf("\n\nError: No keyring file specified")
		return
	}

	basefilename := ""

	if strings.HasSuffix(*inputTemplate, jaegerTemplateExtension) {
		basefilename = strings.TrimSuffix(*inputTemplate, jaegerTemplateExtension)
	}

	if *jsonGPGDB == "" {
		if basefilename == "" {
			flag.Usage()
			log.Fatalf("\n\nERROR: No JSON GPG DB file specified or input file does not have a %v extension", jaegerTemplateExtension)
			return
		}
		// Set from the basefilename
		*jsonGPGDB = fmt.Sprintf("%v%v", basefilename, jaegerJSONGPGDBExtension)
	}

	if *outputFile == "" {
		if basefilename == "" {
			flag.Usage()
			log.Fatalf("\n\nERROR: No Output file specified or input file does not have a %v extension", jaegerTemplateExtension)
			return
		}
		// Set from the basefilename
		*outputFile = basefilename

	}

	if *passphraseKeyring == "" {
		passphrase := os.Getenv("PASSPHRASE")
		if len(passphrase) != 0 {
			*passphraseKeyring = passphrase
		}
	}

	fmt.Println("basefilename:", basefilename)
	fmt.Println("jsonGPGDB:", *jsonGPGDB)
	fmt.Println("outputFile:", *outputFile)
	fmt.Println("passphrase:", *passphraseKeyring)
	fmt.Println(*jsonGPGDB, *outputFile, *keyringFile)

	// Read armored private key into type EntityList
	// An EntityList contains one or more Entities.
	// This assumes there is only one Entity involved
	// TODO: Read default keyring
	// TODO: Support to prompt for passphrase
	//entitylist, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(privateKey))
	keyringFileBuffer, err := os.Open(*keyringFile)
	if err != nil {
		log.Fatalln("ERROR: Unable to read keyring file")
	}
	entitylist, err := openpgp.ReadArmoredKeyRing(keyringFileBuffer)
	if err != nil {
		log.Fatal(err)
	}
	entity := entitylist[0]
	fmt.Println("Private key from armored string:", entity.Identities)

	// Decrypt private key using passphrase
	passphrase := []byte(*passphraseKeyring)
	if entity.PrivateKey != nil && entity.PrivateKey.Encrypted {
		fmt.Println("Decrypting private key using passphrase")
		err := entity.PrivateKey.Decrypt(passphrase)
		if err != nil {
			log.Fatalln("ERROR: Failed to decrypt key")
		}
	}
	for _, subkey := range entity.Subkeys {
		if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted {
			err := subkey.PrivateKey.Decrypt(passphrase)
			if err != nil {
				log.Fatalln("ERROR: Failed to decrypt subkey")
			}
		}
	}

}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package main

import (
	"github.com/jinzhu/gorm"
	"time"
)

// data models
type Match struct {
	gorm.Model

	DateTime time.Time
	Duration uint
	Map      string
	Type     string
}

type Player struct {
	gorm.Model

	Name    string
	Aliases []string

	Wins uint
}

type WeaponStat struct {
	gorm.Model

	Hits  uint
	Shots uint
	Kills uint
}

<commit_msg>models: add match data hash field<commit_after>// The MIT License (MIT)

// Copyright (c) 2016 Maciej Borzecki

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package main

import (
	"github.com/jinzhu/gorm"
	"time"
)

// data models
type Match struct {
	gorm.Model

	DataHash string
	DateTime time.Time
	Duration uint
	Map      string
	Type     string
}

type Player struct {
	gorm.Model

	Name    string
	Aliases []string

	Wins uint
}

type WeaponStat struct {
	gorm.Model

	Hits  uint
	Shots uint
	Kills uint
}

<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httputil"

	log "github.com/Sirupsen/logrus"
	"github.com/elazarl/goproxy"
	"github.com/garyburd/redigo/redis"
)

type DBClient struct {
	cache Cache
	http  *http.Client
}

// request holds structure for request
type request struct {
	details requestDetails
}

var emptyResp = &http.Response{}

// requestDetails stores information about request, it's used for creating unique hash and also as a payload structure
type requestDetails struct {
	Path        string `json:"path"`
	Method      string `json:"method"`
	Destination string `json:"destination"`
	Query       string `json:"query"`
}

// hash returns unique hash key for request
func (r *request) hash() string {
	h := md5.New()
	io.WriteString(h, fmt.Sprintf("%s%s%s%s", r.details.Destination, r.details.Path, r.details.Method, r.details.Query))
	return fmt.Sprintf("%x", h.Sum(nil))
}

// res structure hold response body from external service, body is not decoded and is supposed
// to be bytes, however headers should provide all required information for later decoding
// by the client.
type response struct {
	Status  int                 `json:"status"`
	Body    []byte              `json:"body"`
	Headers map[string][]string `json:"headers"`
}

// Payload structure holds request and response structure
type Payload struct {
	Response response       `json:"response"`
	Request  requestDetails `json:"request"`
	ID       string         `json:"id"`
}

// recordRequest saves request for later playback
func (d *DBClient) recordRequest(req *http.Request) (*http.Response, error) {

	// forwarding request
	resp, err := d.doRequest(req)

	if err == nil {

		// getting response body
		body, err := httputil.DumpResponse(resp, true)
		if err != nil {
			// copying the response body did not work
			if err != nil {
				log.WithFields(log.Fields{
					"error": err.Error(),
				}).Error("Failed to copy response body.")
			}
		}

		// saving response body with request/response meta to cache
		go d.save(req, resp, body)
	}

	// return new response or error here
	return resp, err
}

// doRequest performs original request and returns response that should be returned to client and error (if there is one)
func (d *DBClient) doRequest(request *http.Request) (*http.Response, error) {
	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	request.RequestURI = ""

	resp, err := d.http.Do(request)

	if err != nil {
		log.WithFields(log.Fields{
			"error":  err.Error(),
			"host":   request.Host,
			"method": request.Method,
			"path":   request.URL.Path,
		}).Error("Could not forward request.")
		return nil, err
	}

	log.WithFields(log.Fields{
		"host":   request.Host,
		"method": request.Method,
		"path":   request.URL.Path,
	}).Info("Response got successfuly!")

	resp.Header.Set("Gen-proxy", "Was-Here")
	return resp, nil

}

// save gets request fingerprint, extracts request body, status code and headers, then saves it to cache
func (d *DBClient) save(req *http.Request, resp *http.Response, respBody []byte) {
	// record request here
	key := getRequestFingerprint(req)

	if resp == nil {
		resp = emptyResp
	} else {
		responseObj := response{
			Status: resp.StatusCode,
			Body:   respBody,
			//			Headers: getHeadersMap(resp.Header),
			Headers: resp.Header,
		}

		log.WithFields(log.Fields{
			"path":          req.URL.Path,
			"rawQuery":      req.URL.RawQuery,
			"requestMethod": req.Method,
			"destination":   req.Host,
			"hashKey":       key,
		}).Info("Recording")

		requestObj := requestDetails{
			Path:        req.URL.Path,
			Method:      req.Method,
			Destination: req.Host,
			Query:       req.URL.RawQuery,
		}

		payload := Payload{
			Response: responseObj,
			Request:  requestObj,
			ID:       key,
		}
		// converting it to json bytes
		bts, err := json.Marshal(payload)

		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
			}).Error("Failed to marshal json")
		} else {
			d.cache.set(key, bts)
		}
	}

}

// getAllRecordsRaw returns raw (json string) for all records
func (d *DBClient) getAllRecordsRaw() ([]string, error) {
	keys, err := d.cache.getAllKeys()

	if err == nil {

		// checking if there are any records
		if len(keys) == 0 {
			return nil, nil
		}

		jsonStrs, err := d.cache.getAllValues(keys)

		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
			}).Error("Failed to get all values (raw)")
			return nil, err
		} else {
			return jsonStrs, nil
		}

	} else {
		return nil, err
	}
}

// getAllRecords returns all stored
func (d *DBClient) getAllRecords() ([]Payload, error) {
	var payloads []Payload

	jsonStrs, err := d.getAllRecordsRaw()

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Failed to get all values")
	} else {

		if jsonStrs != nil {
			for _, v := range jsonStrs {
				var pl Payload
				err = json.Unmarshal([]byte(v), &pl)
				if err != nil {
					log.WithFields(log.Fields{
						"error": err.Error(),
						"json":  v,
					}).Warning("Failed to deserialize json")
				} else {
					payloads = append(payloads, pl)
				}
			}
		}
	}

	return payloads, err

}

// deleteAllRecords deletes all recorded requests
func (d *DBClient) deleteAllRecords() error {
	keys, err := d.cache.getAllKeys()

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Warning("Failed to get keys, cannot delete all records")
		return err
	} else {
		for _, v := range keys {
			d.cache.delete(v)
		}
		return nil
	}
}

// getRequestFingerprint returns request hash
func getRequestFingerprint(req *http.Request) string {
	details := requestDetails{Path: req.URL.Path, Method: req.Method, Destination: req.Host, Query: req.URL.RawQuery}
	r := request{details: details}
	return r.hash()
}

// getResponse returns stored response from cache
func (d *DBClient) getResponse(req *http.Request) *http.Response {
	log.Info("Returning response")

	key := getRequestFingerprint(req)
	var payload Payload

	payloadBts, err := redis.Bytes(d.cache.get(key))

	if err == nil {
		log.Info("Decoding bytes")
		// getting cache response
		err = json.Unmarshal(payloadBts, &payload)
		if err != nil {
			log.Error(err)
			// what now?
		}

		newResponse := &http.Response{}
		newResponse.Request = req
		// adding headers
		newResponse.Header = make(http.Header)
		if len(payload.Response.Headers) > 0 {
			for k, values := range payload.Response.Headers {
				// headers is a map, appending each value
				for _, v := range values {
					newResponse.Header.Add(k, v)
				}

			}
		}
		newResponse.Header.Set("Gen-Proxy", "Playback")
		// adding body
		buf := bytes.NewBuffer(payload.Response.Body)
		newResponse.ContentLength = int64(buf.Len())
		newResponse.Body = ioutil.NopCloser(buf)

		newResponse.StatusCode = payload.Response.Status

		log.WithFields(log.Fields{
			"key":        key,
			"status":     payload.Response.Status,
			"bodyLength": newResponse.ContentLength,
		}).Info("Response found, returning")

		return newResponse

	} else {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Failed to retrieve response from cache")
		// return error? if we return nil - proxy forwards request to original destination
		return goproxy.NewResponse(req,
			goproxy.ContentTypeText, http.StatusPreconditionFailed,
			"Coudldn't find recorded request, please record it first!")
	}

}
<commit_msg>storing requests as strings rather than bytes<commit_after>package main

import (
	"bytes"
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httputil"

	log "github.com/Sirupsen/logrus"
	"github.com/elazarl/goproxy"
	"github.com/garyburd/redigo/redis"
)

type DBClient struct {
	cache Cache
	http  *http.Client
}

// request holds structure for request
type request struct {
	details requestDetails
}

var emptyResp = &http.Response{}

// requestDetails stores information about request, it's used for creating unique hash and also as a payload structure
type requestDetails struct {
	Path        string `json:"path"`
	Method      string `json:"method"`
	Destination string `json:"destination"`
	Query       string `json:"query"`
}

// hash returns unique hash key for request
func (r *request) hash() string {
	h := md5.New()
	io.WriteString(h, fmt.Sprintf("%s%s%s%s", r.details.Destination, r.details.Path, r.details.Method, r.details.Query))
	return fmt.Sprintf("%x", h.Sum(nil))
}

// res structure hold response body from external service, body is not decoded and is supposed
// to be bytes, however headers should provide all required information for later decoding
// by the client.
type response struct {
	Status  int                 `json:"status"`
	Body    string              `json:"body"`
	Headers map[string][]string `json:"headers"`
}

// Payload structure holds request and response structure
type Payload struct {
	Response response       `json:"response"`
	Request  requestDetails `json:"request"`
	ID       string         `json:"id"`
}

// recordRequest saves request for later playback
func (d *DBClient) recordRequest(req *http.Request) (*http.Response, error) {

	// forwarding request
	resp, err := d.doRequest(req)

	if err == nil {

		// getting response body
		body, err := httputil.DumpResponse(resp, true)
		if err != nil {
			// copying the response body did not work
			if err != nil {
				log.WithFields(log.Fields{
					"error": err.Error(),
				}).Error("Failed to copy response body.")
			}
		}

		// saving response body with request/response meta to cache
		go d.save(req, resp, body)
	}

	// return new response or error here
	return resp, err
}

// doRequest performs original request and returns response that should be returned to client and error (if there is one)
func (d *DBClient) doRequest(request *http.Request) (*http.Response, error) {
	// We can't have this set. And it only contains "/pkg/net/http/" anyway
	request.RequestURI = ""

	resp, err := d.http.Do(request)

	if err != nil {
		log.WithFields(log.Fields{
			"error":  err.Error(),
			"host":   request.Host,
			"method": request.Method,
			"path":   request.URL.Path,
		}).Error("Could not forward request.")
		return nil, err
	}

	log.WithFields(log.Fields{
		"host":   request.Host,
		"method": request.Method,
		"path":   request.URL.Path,
	}).Info("Response got successfuly!")

	resp.Header.Set("Gen-proxy", "Was-Here")
	return resp, nil

}

// save gets request fingerprint, extracts request body, status code and headers, then saves it to cache
func (d *DBClient) save(req *http.Request, resp *http.Response, respBody []byte) {
	// record request here
	key := getRequestFingerprint(req)

	if resp == nil {
		resp = emptyResp
	} else {
		responseObj := response{
			Status:  resp.StatusCode,
			Body:    string(respBody),
			Headers: resp.Header,
		}

		log.WithFields(log.Fields{
			"path":          req.URL.Path,
			"rawQuery":      req.URL.RawQuery,
			"requestMethod": req.Method,
			"destination":   req.Host,
			"hashKey":       key,
		}).Info("Recording")

		requestObj := requestDetails{
			Path:        req.URL.Path,
			Method:      req.Method,
			Destination: req.Host,
			Query:       req.URL.RawQuery,
		}

		payload := Payload{
			Response: responseObj,
			Request:  requestObj,
			ID:       key,
		}
		// converting it to json bytes
		bts, err := json.Marshal(payload)

		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
			}).Error("Failed to marshal json")
		} else {
			d.cache.set(key, bts)
		}
	}

}

// getAllRecordsRaw returns raw (json string) for all records
func (d *DBClient) getAllRecordsRaw() ([]string, error) {
	keys, err := d.cache.getAllKeys()

	if err == nil {

		// checking if there are any records
		if len(keys) == 0 {
			return nil, nil
		}

		jsonStrs, err := d.cache.getAllValues(keys)

		if err != nil {
			log.WithFields(log.Fields{
				"error": err.Error(),
			}).Error("Failed to get all values (raw)")
			return nil, err
		} else {
			return jsonStrs, nil
		}

	} else {
		return nil, err
	}
}

// getAllRecords returns all stored
func (d *DBClient) getAllRecords() ([]Payload, error) {
	var payloads []Payload

	jsonStrs, err := d.getAllRecordsRaw()

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Failed to get all values")
	} else {

		if jsonStrs != nil {
			for _, v := range jsonStrs {
				var pl Payload
				err = json.Unmarshal([]byte(v), &pl)
				if err != nil {
					log.WithFields(log.Fields{
						"error": err.Error(),
						"json":  v,
					}).Warning("Failed to deserialize json")
				} else {
					payloads = append(payloads, pl)
				}
			}
		}
	}

	return payloads, err

}

// deleteAllRecords deletes all recorded requests
func (d *DBClient) deleteAllRecords() error {
	keys, err := d.cache.getAllKeys()

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Warning("Failed to get keys, cannot delete all records")
		return err
	} else {
		for _, v := range keys {
			d.cache.delete(v)
		}
		return nil
	}
}

// getRequestFingerprint returns request hash
func getRequestFingerprint(req *http.Request) string {
	details := requestDetails{Path: req.URL.Path, Method: req.Method, Destination: req.Host, Query: req.URL.RawQuery}
	r := request{details: details}
	return r.hash()
}

// getResponse returns stored response from cache
func (d *DBClient) getResponse(req *http.Request) *http.Response {
	log.Info("Returning response")

	key := getRequestFingerprint(req)
	var payload Payload

	payloadBts, err := redis.Bytes(d.cache.get(key))

	if err == nil {
		log.Info("Decoding bytes")
		// getting cache response
		err = json.Unmarshal(payloadBts, &payload)
		if err != nil {
			log.Error(err)
			// what now?
		}

		newResponse := &http.Response{}
		newResponse.Request = req
		// adding headers
		newResponse.Header = make(http.Header)
		if len(payload.Response.Headers) > 0 {
			for k, values := range payload.Response.Headers {
				// headers is a map, appending each value
				for _, v := range values {
					newResponse.Header.Add(k, v)
				}

			}
		}
		newResponse.Header.Set("Gen-Proxy", "Playback")
		// adding body
		buf := bytes.NewBufferString(payload.Response.Body)
		newResponse.ContentLength = int64(buf.Len())
		newResponse.Body = ioutil.NopCloser(buf)

		newResponse.StatusCode = payload.Response.Status

		log.WithFields(log.Fields{
			"key":        key,
			"status":     payload.Response.Status,
			"bodyLength": newResponse.ContentLength,
		}).Info("Response found, returning")

		return newResponse

	} else {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Failed to retrieve response from cache")
		// return error? if we return nil - proxy forwards request to original destination
		return goproxy.NewResponse(req,
			goproxy.ContentTypeText, http.StatusPreconditionFailed,
			"Coudldn't find recorded request, please record it first!")
	}

}
<|endoftext|>


<commit_before>package main

import (
	"net/rpc"
	"net/rpc/jsonrpc"

	"honnef.co/go/js/dom"

	"github.com/MJKWoolnough/minewebgen/internal/data"
	"github.com/gopherjs/gopherjs/js"
	"github.com/gopherjs/websocket"
)

type jRPC struct {
	rpc *rpc.Client
}

func rpcInit() error {
	conn, err := websocket.Dial("ws://" + js.Global.Get("location").Get("host").String() + "/rpc")
	if err != nil {
		return err
	}
	dom.GetWindow().AddEventListener("beforeunload", false, func(dom.Event) {
		switch conn.ReadyState {
		case websocket.Connecting, websocket.Open:
			conn.Close()
		}
	})
	RPC = jRPC{jsonrpc.NewClient(conn)}
	return nil
}

var (
	RPC jRPC
	es  = &struct{}{}
)

func (j jRPC) Settings() (data.ServerSettings, error) {
	var s data.ServerSettings
	err := j.rpc.Call("RPC.ServerSettings", nil, &s)
	return s, err
}

func (j jRPC) SetSettings(settings data.ServerSettings) error {
	return j.rpc.Call("RPC.SetSettings", settings, es)
}

func (j jRPC) ServerName() (string, error) {
	var name string
	err := j.rpc.Call("RPC.Name", nil, &name)
	return name, err
}

func (j jRPC) ServerList() ([]data.Server, error) {
	var list []data.Server
	err := j.rpc.Call("RPC.ServerList", nil, &list)
	return list, err
}

func (j jRPC) MapList() ([]data.Map, error) {
	var list []data.Map
	err := j.rpc.Call("RPC.MapList", nil, &list)
	return list, err
}

func (j jRPC) Server(id int) (data.Server, error) {
	var s data.Server
	err := j.rpc.Call("RPC.Server", id, &s)
	return s, err
}

func (j jRPC) Map(id int) (data.Map, error) {
	var m data.Map
	err := j.rpc.Call("RPC.Map", id, &m)
	return m, err
}

func (j jRPC) SetServer(s data.Server) error {
	return j.rpc.Call("RPC.SetServer", s, es)
}

func (j jRPC) SetMap(m data.Map) error {
	return j.rpc.Call("RPC.SetMap", m, es)
}

func (j jRPC) SetServerMap(serverID, mapID int) error {
	return j.rpc.Call("RPC.SetServerMap", [2]int{serverID, mapID}, es)
}

func (j jRPC) ServerProperties(id int) (map[string]string, error) {
	sp := make(map[string]string)
	err := j.rpc.Call("RPC.ServerProperties", id, &sp)
	return sp, err
}

func (j jRPC) SetServerProperties(id int, properties map[string]string) error {
	return j.rpc.Call("RPC.SetServerProperties", data.ServerProperties{id, properties}, es)
}

func (j jRPC) MapProperties(id int) (map[string]string, error) {
	mp := make(map[string]string)
	err := j.rpc.Call("RPC.MapProperties", id, &mp)
	return mp, err
}

func (j jRPC) SetMapProperties(id int, properties map[string]string) error {
	return j.rpc.Call("RPC.SetMapProperties", data.ServerProperties{id, properties}, es)
}

func (j jRPC) RemoveServer(id int) error {
	return j.rpc.Call("RPC.RemoveServer", id, es)
}

func (j jRPC) RemoveMap(id int) error {
	return j.rpc.Call("RPC.RemoveMap", id, es)
}

func (j jRPC) CreateDefaultMap(d data.DefaultMap) error {
	return j.rpc.Call("RPC.CreateDefaultMap", d, es)
}

func (j jRPC) CreateSuperflatMap(d data.SuperFlatMap) error {
	return j.rpc.Call("RPC.CreateSuperflatMap", d, es)
}

func (j jRPC) CreateCustomMap(d data.CustomMap) error {
	return j.rpc.Call("RPC.CreateCustomMap", d, es)
}
<commit_msg>Added websocket close detection<commit_after>package main

import (
	"net/rpc"
	"net/rpc/jsonrpc"

	"honnef.co/go/js/dom"

	"github.com/MJKWoolnough/gopherjs/xdom"
	"github.com/MJKWoolnough/gopherjs/xjs"
	"github.com/MJKWoolnough/minewebgen/internal/data"
	"github.com/gopherjs/gopherjs/js"
	"github.com/gopherjs/websocket"
)

type jRPC struct {
	rpc *rpc.Client
}

func rpcInit() error {
	conn, err := websocket.Dial("ws://" + js.Global.Get("location").Get("host").String() + "/rpc")
	if err != nil {
		return err
	}
	conn.WebSocket.AddEventListener("close", false, func(dom.Event) {
		xjs.RemoveChildren(dom.GetWindow().Document().(dom.HTMLDocument).Body()).AppendChild(xjs.SetInnerText(xdom.H1(), "Connection Lost"))
	})
	dom.GetWindow().AddEventListener("beforeunload", false, func(dom.Event) {
		switch conn.ReadyState {
		case websocket.Connecting, websocket.Open:
			conn.Close()
		}
	})
	RPC = jRPC{jsonrpc.NewClient(conn)}
	return nil
}

var (
	RPC jRPC
	es  = &struct{}{}
)

func (j jRPC) Settings() (data.ServerSettings, error) {
	var s data.ServerSettings
	err := j.rpc.Call("RPC.ServerSettings", nil, &s)
	return s, err
}

func (j jRPC) SetSettings(settings data.ServerSettings) error {
	return j.rpc.Call("RPC.SetSettings", settings, es)
}

func (j jRPC) ServerName() (string, error) {
	var name string
	err := j.rpc.Call("RPC.Name", nil, &name)
	return name, err
}

func (j jRPC) ServerList() ([]data.Server, error) {
	var list []data.Server
	err := j.rpc.Call("RPC.ServerList", nil, &list)
	return list, err
}

func (j jRPC) MapList() ([]data.Map, error) {
	var list []data.Map
	err := j.rpc.Call("RPC.MapList", nil, &list)
	return list, err
}

func (j jRPC) Server(id int) (data.Server, error) {
	var s data.Server
	err := j.rpc.Call("RPC.Server", id, &s)
	return s, err
}

func (j jRPC) Map(id int) (data.Map, error) {
	var m data.Map
	err := j.rpc.Call("RPC.Map", id, &m)
	return m, err
}

func (j jRPC) SetServer(s data.Server) error {
	return j.rpc.Call("RPC.SetServer", s, es)
}

func (j jRPC) SetMap(m data.Map) error {
	return j.rpc.Call("RPC.SetMap", m, es)
}

func (j jRPC) SetServerMap(serverID, mapID int) error {
	return j.rpc.Call("RPC.SetServerMap", [2]int{serverID, mapID}, es)
}

func (j jRPC) ServerProperties(id int) (map[string]string, error) {
	sp := make(map[string]string)
	err := j.rpc.Call("RPC.ServerProperties", id, &sp)
	return sp, err
}

func (j jRPC) SetServerProperties(id int, properties map[string]string) error {
	return j.rpc.Call("RPC.SetServerProperties", data.ServerProperties{id, properties}, es)
}

func (j jRPC) MapProperties(id int) (map[string]string, error) {
	mp := make(map[string]string)
	err := j.rpc.Call("RPC.MapProperties", id, &mp)
	return mp, err
}

func (j jRPC) SetMapProperties(id int, properties map[string]string) error {
	return j.rpc.Call("RPC.SetMapProperties", data.ServerProperties{id, properties}, es)
}

func (j jRPC) RemoveServer(id int) error {
	return j.rpc.Call("RPC.RemoveServer", id, es)
}

func (j jRPC) RemoveMap(id int) error {
	return j.rpc.Call("RPC.RemoveMap", id, es)
}

func (j jRPC) CreateDefaultMap(d data.DefaultMap) error {
	return j.rpc.Call("RPC.CreateDefaultMap", d, es)
}

func (j jRPC) CreateSuperflatMap(d data.SuperFlatMap) error {
	return j.rpc.Call("RPC.CreateSuperflatMap", d, es)
}

func (j jRPC) CreateCustomMap(d data.CustomMap) error {
	return j.rpc.Call("RPC.CreateCustomMap", d, es)
}
<|endoftext|>