<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package factory

import (
	"context"
	"fmt"
	"net"
	"net/url"
	"path"
	"sync"
	"sync/atomic"
	"time"

	grpcprom "github.com/grpc-ecosystem/go-grpc-prometheus"
	"go.etcd.io/etcd/clientv3"
	"go.etcd.io/etcd/pkg/transport"
	"google.golang.org/grpc"

	"k8s.io/apimachinery/pkg/runtime"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/apiserver/pkg/server/egressselector"
	"k8s.io/apiserver/pkg/storage"
	"k8s.io/apiserver/pkg/storage/etcd3"
	"k8s.io/apiserver/pkg/storage/etcd3/metrics"
	"k8s.io/apiserver/pkg/storage/storagebackend"
	"k8s.io/apiserver/pkg/storage/value"
	"k8s.io/component-base/metrics/legacyregistry"
	"k8s.io/klog/v2"
)

const (
	// The short keepalive timeout and interval have been chosen to aggressively
	// detect a failed etcd server without introducing much overhead.
	keepaliveTime    = 30 * time.Second
	keepaliveTimeout = 10 * time.Second

	// dialTimeout is the timeout for failing to establish a connection.
	// It is set to 20 seconds as times shorter than that will cause TLS connections to fail
	// on heavily loaded arm64 CPUs (issue #64649)
	dialTimeout = 20 * time.Second

	dbMetricsMonitorJitter = 0.5
)

func init() {
	// grpcprom auto-registers (via an init function) their client metrics, since we are opting out of
	// using the global prometheus registry and using our own wrapped global registry,
	// we need to explicitly register these metrics to our global registry here.
	// For reference: https://github.com/kubernetes/kubernetes/pull/81387
	legacyregistry.RawMustRegister(grpcprom.DefaultClientMetrics)
	dbMetricsMonitors = make(map[string]struct{})
}

func newETCD3HealthCheck(c storagebackend.Config) (func() error, error) {
	// constructing the etcd v3 client blocks and times out if etcd is not available.
	// retry in a loop in the background until we successfully create the client, storing the client or error encountered

	clientValue := &atomic.Value{}

	clientErrMsg := &atomic.Value{}
	clientErrMsg.Store("etcd client connection not yet established")

	go wait.PollUntil(time.Second, func() (bool, error) {
		client, err := newETCD3Client(c.Transport)
		if err != nil {
			clientErrMsg.Store(err.Error())
			return false, nil
		}
		clientValue.Store(client)
		clientErrMsg.Store("")
		return true, nil
	}, wait.NeverStop)

	return func() error {
		if errMsg := clientErrMsg.Load().(string); len(errMsg) > 0 {
			return fmt.Errorf(errMsg)
		}
		client := clientValue.Load().(*clientv3.Client)
		ctx, cancel := context.WithTimeout(context.Background(), c.HealthcheckTimeout)
		defer cancel()
		// See https://github.com/etcd-io/etcd/blob/c57f8b3af865d1b531b979889c602ba14377420e/etcdctl/ctlv3/command/ep_command.go#L118
		_, err := client.Get(ctx, path.Join("/", c.Prefix, "health"))
		if err == nil {
			return nil
		}
		return fmt.Errorf("error getting data from etcd: %v", err)
	}, nil
}

func newETCD3Client(c storagebackend.TransportConfig) (*clientv3.Client, error) {
	tlsInfo := transport.TLSInfo{
		CertFile:      c.CertFile,
		KeyFile:       c.KeyFile,
		TrustedCAFile: c.TrustedCAFile,
	}
	tlsConfig, err := tlsInfo.ClientConfig()
	if err != nil {
		return nil, err
	}
	// NOTE: Client relies on nil tlsConfig
	// for non-secure connections, update the implicit variable
	if len(c.CertFile) == 0 && len(c.KeyFile) == 0 && len(c.TrustedCAFile) == 0 {
		tlsConfig = nil
	}
	networkContext := egressselector.Etcd.AsNetworkContext()
	var egressDialer utilnet.DialFunc
	if c.EgressLookup != nil {
		egressDialer, err = c.EgressLookup(networkContext)
		if err != nil {
			return nil, err
		}
	}
	dialOptions := []grpc.DialOption{
		grpc.WithBlock(), // block until the underlying connection is up
		grpc.WithUnaryInterceptor(grpcprom.UnaryClientInterceptor),
		grpc.WithStreamInterceptor(grpcprom.StreamClientInterceptor),
	}
	if egressDialer != nil {
		dialer := func(ctx context.Context, addr string) (net.Conn, error) {
			u, err := url.Parse(addr)
			if err != nil {
				return nil, err
			}
			return egressDialer(ctx, "tcp", u.Host)
		}
		dialOptions = append(dialOptions, grpc.WithContextDialer(dialer))
	}
	cfg := clientv3.Config{
		DialTimeout:          dialTimeout,
		DialKeepAliveTime:    keepaliveTime,
		DialKeepAliveTimeout: keepaliveTimeout,
		DialOptions:          dialOptions,
		Endpoints:            c.ServerList,
		TLS:                  tlsConfig,
	}

	return clientv3.New(cfg)
}

type runningCompactor struct {
	interval time.Duration
	cancel   context.CancelFunc
	client   *clientv3.Client
	refs     int
}

var (
	// compactorsMu guards access to compactors map
	compactorsMu sync.Mutex
	compactors   = map[string]*runningCompactor{}
	// dbMetricsMonitorsMu guards access to dbMetricsMonitors map
	dbMetricsMonitorsMu sync.Mutex
	dbMetricsMonitors   map[string]struct{}
)

// startCompactorOnce start one compactor per transport. If the interval get smaller on repeated calls, the
// compactor is replaced. A destroy func is returned. If all destroy funcs with the same transport are called,
// the compactor is stopped.
func startCompactorOnce(c storagebackend.TransportConfig, interval time.Duration) (func(), error) {
	compactorsMu.Lock()
	defer compactorsMu.Unlock()

	key := fmt.Sprintf("%v", c) // gives: {[server1 server2] keyFile certFile caFile}
	if compactor, foundBefore := compactors[key]; !foundBefore || compactor.interval > interval {
		compactorClient, err := newETCD3Client(c)
		if err != nil {
			return nil, err
		}

		if foundBefore {
			// replace compactor
			compactor.cancel()
			compactor.client.Close()
		} else {
			// start new compactor
			compactor = &runningCompactor{}
			compactors[key] = compactor
		}

		ctx, cancel := context.WithCancel(context.Background())

		compactor.interval = interval
		compactor.cancel = cancel
		compactor.client = compactorClient

		etcd3.StartCompactor(ctx, compactorClient, interval)
	}

	compactors[key].refs++

	return func() {
		compactorsMu.Lock()
		defer compactorsMu.Unlock()

		compactor := compactors[key]
		compactor.refs--
		if compactor.refs == 0 {
			compactor.cancel()
			compactor.client.Close()
			delete(compactors, key)
		}
	}, nil
}

func newETCD3Storage(c storagebackend.Config, newFunc func() runtime.Object) (storage.Interface, DestroyFunc, error) {
	stopCompactor, err := startCompactorOnce(c.Transport, c.CompactionInterval)
	if err != nil {
		return nil, nil, err
	}

	client, err := newETCD3Client(c.Transport)
	if err != nil {
		stopCompactor()
		return nil, nil, err
	}

	stopDBSizeMonitor, err := startDBSizeMonitorPerEndpoint(client, c.DBMetricPollInterval)
	if err != nil {
		return nil, nil, err
	}

	var once sync.Once
	destroyFunc := func() {
		// we know that storage destroy funcs are called multiple times (due to reuse in subresources).
		// Hence, we only destroy once.
		// TODO: fix duplicated storage destroy calls higher level
		once.Do(func() {
			stopCompactor()
			stopDBSizeMonitor()
			client.Close()
		})
	}
	transformer := c.Transformer
	if transformer == nil {
		transformer = value.IdentityTransformer
	}
	return etcd3.New(client, c.Codec, newFunc, c.Prefix, transformer, c.Paging), destroyFunc, nil
}

// startDBSizeMonitorPerEndpoint starts a loop to monitor etcd database size and update the
// corresponding metric etcd_db_total_size_in_bytes for each etcd server endpoint.
func startDBSizeMonitorPerEndpoint(client *clientv3.Client, interval time.Duration) (func(), error) {
	if interval == 0 {
		return func() {}, nil
	}
	dbMetricsMonitorsMu.Lock()
	defer dbMetricsMonitorsMu.Unlock()

	ctx, cancel := context.WithCancel(context.Background())
	for _, ep := range client.Endpoints() {
		if _, found := dbMetricsMonitors[ep]; found {
			continue
		}
		dbMetricsMonitors[ep] = struct{}{}
		endpoint := ep
		klog.V(4).Infof("Start monitoring storage db size metric for endpoint %s with polling interval %v", endpoint, interval)
		go wait.JitterUntilWithContext(ctx, func(context.Context) {
			epStatus, err := client.Maintenance.Status(ctx, endpoint)
			if err != nil {
				klog.V(4).Infof("Failed to get storage db size for ep %s: %v", endpoint, err)
				metrics.UpdateEtcdDbSize(endpoint, -1)
			} else {
				metrics.UpdateEtcdDbSize(endpoint, epStatus.DbSize)
			}
		}, interval, dbMetricsMonitorJitter, true)
	}

	return func() {
		cancel()
	}, nil
}
<commit_msg>fix case when HC timeout is 0<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package factory

import (
	"context"
	"fmt"
	"net"
	"net/url"
	"path"
	"sync"
	"sync/atomic"
	"time"

	grpcprom "github.com/grpc-ecosystem/go-grpc-prometheus"
	"go.etcd.io/etcd/clientv3"
	"go.etcd.io/etcd/pkg/transport"
	"google.golang.org/grpc"

	"k8s.io/apimachinery/pkg/runtime"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/apiserver/pkg/server/egressselector"
	"k8s.io/apiserver/pkg/storage"
	"k8s.io/apiserver/pkg/storage/etcd3"
	"k8s.io/apiserver/pkg/storage/etcd3/metrics"
	"k8s.io/apiserver/pkg/storage/storagebackend"
	"k8s.io/apiserver/pkg/storage/value"
	"k8s.io/component-base/metrics/legacyregistry"
	"k8s.io/klog/v2"
)

const (
	// The short keepalive timeout and interval have been chosen to aggressively
	// detect a failed etcd server without introducing much overhead.
	keepaliveTime    = 30 * time.Second
	keepaliveTimeout = 10 * time.Second

	// dialTimeout is the timeout for failing to establish a connection.
	// It is set to 20 seconds as times shorter than that will cause TLS connections to fail
	// on heavily loaded arm64 CPUs (issue #64649)
	dialTimeout = 20 * time.Second

	dbMetricsMonitorJitter = 0.5
)

func init() {
	// grpcprom auto-registers (via an init function) their client metrics, since we are opting out of
	// using the global prometheus registry and using our own wrapped global registry,
	// we need to explicitly register these metrics to our global registry here.
	// For reference: https://github.com/kubernetes/kubernetes/pull/81387
	legacyregistry.RawMustRegister(grpcprom.DefaultClientMetrics)
	dbMetricsMonitors = make(map[string]struct{})
}

func newETCD3HealthCheck(c storagebackend.Config) (func() error, error) {
	// constructing the etcd v3 client blocks and times out if etcd is not available.
	// retry in a loop in the background until we successfully create the client, storing the client or error encountered

	clientValue := &atomic.Value{}

	clientErrMsg := &atomic.Value{}
	clientErrMsg.Store("etcd client connection not yet established")

	go wait.PollUntil(time.Second, func() (bool, error) {
		client, err := newETCD3Client(c.Transport)
		if err != nil {
			clientErrMsg.Store(err.Error())
			return false, nil
		}
		clientValue.Store(client)
		clientErrMsg.Store("")
		return true, nil
	}, wait.NeverStop)

	return func() error {
		if errMsg := clientErrMsg.Load().(string); len(errMsg) > 0 {
			return fmt.Errorf(errMsg)
		}
		client := clientValue.Load().(*clientv3.Client)
		healthcheckTimeout := storagebackend.DefaultHealthcheckTimeout
		if c.HealthcheckTimeout != time.Duration(0) {
			healthcheckTimeout = c.HealthcheckTimeout
		}
		ctx, cancel := context.WithTimeout(context.Background(), healthcheckTimeout)
		defer cancel()
		// See https://github.com/etcd-io/etcd/blob/c57f8b3af865d1b531b979889c602ba14377420e/etcdctl/ctlv3/command/ep_command.go#L118
		_, err := client.Get(ctx, path.Join("/", c.Prefix, "health"))
		if err == nil {
			return nil
		}
		return fmt.Errorf("error getting data from etcd: %v", err)
	}, nil
}

func newETCD3Client(c storagebackend.TransportConfig) (*clientv3.Client, error) {
	tlsInfo := transport.TLSInfo{
		CertFile:      c.CertFile,
		KeyFile:       c.KeyFile,
		TrustedCAFile: c.TrustedCAFile,
	}
	tlsConfig, err := tlsInfo.ClientConfig()
	if err != nil {
		return nil, err
	}
	// NOTE: Client relies on nil tlsConfig
	// for non-secure connections, update the implicit variable
	if len(c.CertFile) == 0 && len(c.KeyFile) == 0 && len(c.TrustedCAFile) == 0 {
		tlsConfig = nil
	}
	networkContext := egressselector.Etcd.AsNetworkContext()
	var egressDialer utilnet.DialFunc
	if c.EgressLookup != nil {
		egressDialer, err = c.EgressLookup(networkContext)
		if err != nil {
			return nil, err
		}
	}
	dialOptions := []grpc.DialOption{
		grpc.WithBlock(), // block until the underlying connection is up
		grpc.WithUnaryInterceptor(grpcprom.UnaryClientInterceptor),
		grpc.WithStreamInterceptor(grpcprom.StreamClientInterceptor),
	}
	if egressDialer != nil {
		dialer := func(ctx context.Context, addr string) (net.Conn, error) {
			u, err := url.Parse(addr)
			if err != nil {
				return nil, err
			}
			return egressDialer(ctx, "tcp", u.Host)
		}
		dialOptions = append(dialOptions, grpc.WithContextDialer(dialer))
	}
	cfg := clientv3.Config{
		DialTimeout:          dialTimeout,
		DialKeepAliveTime:    keepaliveTime,
		DialKeepAliveTimeout: keepaliveTimeout,
		DialOptions:          dialOptions,
		Endpoints:            c.ServerList,
		TLS:                  tlsConfig,
	}

	return clientv3.New(cfg)
}

type runningCompactor struct {
	interval time.Duration
	cancel   context.CancelFunc
	client   *clientv3.Client
	refs     int
}

var (
	// compactorsMu guards access to compactors map
	compactorsMu sync.Mutex
	compactors   = map[string]*runningCompactor{}
	// dbMetricsMonitorsMu guards access to dbMetricsMonitors map
	dbMetricsMonitorsMu sync.Mutex
	dbMetricsMonitors   map[string]struct{}
)

// startCompactorOnce start one compactor per transport. If the interval get smaller on repeated calls, the
// compactor is replaced. A destroy func is returned. If all destroy funcs with the same transport are called,
// the compactor is stopped.
func startCompactorOnce(c storagebackend.TransportConfig, interval time.Duration) (func(), error) {
	compactorsMu.Lock()
	defer compactorsMu.Unlock()

	key := fmt.Sprintf("%v", c) // gives: {[server1 server2] keyFile certFile caFile}
	if compactor, foundBefore := compactors[key]; !foundBefore || compactor.interval > interval {
		compactorClient, err := newETCD3Client(c)
		if err != nil {
			return nil, err
		}

		if foundBefore {
			// replace compactor
			compactor.cancel()
			compactor.client.Close()
		} else {
			// start new compactor
			compactor = &runningCompactor{}
			compactors[key] = compactor
		}

		ctx, cancel := context.WithCancel(context.Background())

		compactor.interval = interval
		compactor.cancel = cancel
		compactor.client = compactorClient

		etcd3.StartCompactor(ctx, compactorClient, interval)
	}

	compactors[key].refs++

	return func() {
		compactorsMu.Lock()
		defer compactorsMu.Unlock()

		compactor := compactors[key]
		compactor.refs--
		if compactor.refs == 0 {
			compactor.cancel()
			compactor.client.Close()
			delete(compactors, key)
		}
	}, nil
}

func newETCD3Storage(c storagebackend.Config, newFunc func() runtime.Object) (storage.Interface, DestroyFunc, error) {
	stopCompactor, err := startCompactorOnce(c.Transport, c.CompactionInterval)
	if err != nil {
		return nil, nil, err
	}

	client, err := newETCD3Client(c.Transport)
	if err != nil {
		stopCompactor()
		return nil, nil, err
	}

	stopDBSizeMonitor, err := startDBSizeMonitorPerEndpoint(client, c.DBMetricPollInterval)
	if err != nil {
		return nil, nil, err
	}

	var once sync.Once
	destroyFunc := func() {
		// we know that storage destroy funcs are called multiple times (due to reuse in subresources).
		// Hence, we only destroy once.
		// TODO: fix duplicated storage destroy calls higher level
		once.Do(func() {
			stopCompactor()
			stopDBSizeMonitor()
			client.Close()
		})
	}
	transformer := c.Transformer
	if transformer == nil {
		transformer = value.IdentityTransformer
	}
	return etcd3.New(client, c.Codec, newFunc, c.Prefix, transformer, c.Paging), destroyFunc, nil
}

// startDBSizeMonitorPerEndpoint starts a loop to monitor etcd database size and update the
// corresponding metric etcd_db_total_size_in_bytes for each etcd server endpoint.
func startDBSizeMonitorPerEndpoint(client *clientv3.Client, interval time.Duration) (func(), error) {
	if interval == 0 {
		return func() {}, nil
	}
	dbMetricsMonitorsMu.Lock()
	defer dbMetricsMonitorsMu.Unlock()

	ctx, cancel := context.WithCancel(context.Background())
	for _, ep := range client.Endpoints() {
		if _, found := dbMetricsMonitors[ep]; found {
			continue
		}
		dbMetricsMonitors[ep] = struct{}{}
		endpoint := ep
		klog.V(4).Infof("Start monitoring storage db size metric for endpoint %s with polling interval %v", endpoint, interval)
		go wait.JitterUntilWithContext(ctx, func(context.Context) {
			epStatus, err := client.Maintenance.Status(ctx, endpoint)
			if err != nil {
				klog.V(4).Infof("Failed to get storage db size for ep %s: %v", endpoint, err)
				metrics.UpdateEtcdDbSize(endpoint, -1)
			} else {
				metrics.UpdateEtcdDbSize(endpoint, epStatus.DbSize)
			}
		}, interval, dbMetricsMonitorJitter, true)
	}

	return func() {
		cancel()
	}, nil
}
<|endoftext|>


<commit_before>package microsoft

import "github.com/st3v/translator"

type api struct {
	clientId     string `json:"client_id"`
	clientSecret string `json:"client_secret"`
}

func NewTranslator(clientId, clientSecret string) translator.Translator {
	return &api{
		clientId:     clientId,
		clientSecret: clientSecret,
	}
}

func (a *api) Languages() ([]translator.Language, error) {
	return make([]translator.Language, 0), nil
}

func (a *api) Translate(text, from, to string) (string, error) {
	return "", nil
}
<commit_msg>Remove json annotations for now<commit_after>package microsoft

import "github.com/st3v/translator"

type api struct {
	clientId     string
	clientSecret string
}

func NewTranslator(clientId, clientSecret string) translator.Translator {
	return &api{
		clientId:     clientId,
		clientSecret: clientSecret,
	}
}

func (a *api) Languages() ([]translator.Language, error) {
	return make([]translator.Language, 0), nil
}

func (a *api) Translate(text, from, to string) (string, error) {
	return "", nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/csv"
	"fmt"
	"gopkg.in/vmihailenco/msgpack.v2"
	"labix.org/v2/mgo"
	"os"
	"strconv"
	"time"
)

// AnalyticsRecord encodes the details of a request
type AnalyticsRecord struct {
	Method        string
	Path          string
	ContentLength int64
	UserAgent     string
	Day           int
	Month         time.Month
	Year          int
	Hour          int
	ResponseCode  int
	APIKey        string
	TimeStamp     time.Time
	APIVersion    string
	APIName       string
	APIID         string
	OrgID         string
	OauthID       string
	RequestTime   int64
	ExpireAt      time.Time `bson:"expireAt" json:"expireAt"`
}

const (
	ANALYTICS_KEYNAME string = "tyk-system-analytics"
)

func (a *AnalyticsRecord) SetExpiry(expiresInSeconds int64) {
	var expiry time.Duration

	expiry = time.Duration(expiresInSeconds) * time.Second

	if expiresInSeconds == 0 {
		// Expiry is set to 100 years
		expiry = (24 * time.Hour) * (365 * 100)
	}

	t := time.Now()
	t2 := t.Add(expiry)
	a.ExpireAt = t2
}

// AnalyticsError is an error for when writing to the storage engine fails
type AnalyticsError struct{}

func (e AnalyticsError) Error() string {
	return "Recording request failed!"
}

// AnalyticsHandler is an interface to record analytics data to a writer.
type AnalyticsHandler interface {
	RecordHit(AnalyticsRecord) error
}

// Purger is an interface that will define how the in-memory store will be purged
// of analytics data to prevent it growing too large
type Purger interface {
	PurgeCache()
	StartPurgeLoop(int)
}

// RedisAnalyticsHandler implements AnalyticsHandler and will record analytics
// data to a redis back end as defined in the Config object
type RedisAnalyticsHandler struct {
	Store *RedisStorageManager
	Clean Purger
}

// RecordHit will store an AnalyticsRecord in Redis
func (r RedisAnalyticsHandler) RecordHit(thisRecord AnalyticsRecord) error {
	// If we are obfuscating API Keys, store the hashed representation (config check handled in hashing function)
	thisRecord.APIKey = publicHash(thisRecord.APIKey)

	encoded, err := msgpack.Marshal(thisRecord)

	if err != nil {
		log.Error("Error encoding analytics data:")
		log.Error(err)
		return AnalyticsError{}
	}

	r.Store.AppendToSet(ANALYTICS_KEYNAME, string(encoded))

	return nil
}

// CSVPurger purges the in-memory analytics store to a CSV file as defined in the Config object
type CSVPurger struct {
	Store *RedisStorageManager
}

// StartPurgeLoop is used as a goroutine to ensure that the cache is purged
// of analytics data (assuring size is small).
func (c CSVPurger) StartPurgeLoop(nextCount int) {
	time.Sleep(time.Duration(nextCount) * time.Second)
	c.PurgeCache()
	c.StartPurgeLoop(nextCount)
}

// PurgeCache Will pull all the analytics data from the
// cache and drop it to a storage engine, in this case a CSV file
func (c CSVPurger) PurgeCache() {
	curtime := time.Now()
	fname := fmt.Sprintf("%s%d-%s-%d-%d-%d.csv", config.AnalyticsConfig.CSVDir, curtime.Year(), curtime.Month().String(), curtime.Day(), curtime.Hour(), curtime.Minute())

	ferr := os.MkdirAll(config.AnalyticsConfig.CSVDir, 0777)
	if ferr != nil {
		log.Error(ferr)
	}
	outfile, _ := os.Create(fname)
	defer outfile.Close()
	writer := csv.NewWriter(outfile)

	var headers = []string{"METHOD", "PATH", "SIZE", "UA", "DAY", "MONTH", "YEAR", "HOUR", "RESPONSE", "APINAME", "APIVERSION"}

	err := writer.Write(headers)
	if err != nil {
		log.Error("Failed to write file headers!")
		log.Error(err)
	} else {
		KeyValueMap := c.Store.GetKeysAndValues()
		keys := []string{}

		for k, v := range KeyValueMap {
			keys = append(keys, k)
			decoded := AnalyticsRecord{}
			err := msgpack.Unmarshal([]byte(v), &decoded)
			if err != nil {
				log.Error("Couldn't unmarshal analytics data:")
				log.Error(err)
			} else {
				toWrite := []string{
					decoded.Method,
					decoded.Path,
					strconv.FormatInt(decoded.ContentLength, 10),
					decoded.UserAgent,
					strconv.Itoa(decoded.Day),
					decoded.Month.String(),
					strconv.Itoa(decoded.Year),
					strconv.Itoa(decoded.Hour),
					strconv.Itoa(decoded.ResponseCode),
					decoded.APIName,
					decoded.APIVersion}
				err := writer.Write(toWrite)
				if err != nil {
					log.Error("File write failed!")
					log.Error(err)
				}
			}
		}
		writer.Flush()
		c.Store.DeleteKeys(keys)
	}
}

// MongoPurger will purge analytics data into a Mongo database, requires that the Mongo DB string is specified
// in the Config object
type MongoPurger struct {
	Store     *RedisStorageManager
	dbSession *mgo.Session
}

// Connect Connects to Mongo
func (m *MongoPurger) Connect() {
	var err error
	m.dbSession, err = mgo.Dial(config.AnalyticsConfig.MongoURL)
	if err != nil {
		log.Error("Mongo connection failed:")
		log.Panic(err)
	}
}

// StartPurgeLoop starts the loop that will be started as a goroutine and pull data out of the in-memory
// store and into MongoDB
func (m MongoPurger) StartPurgeLoop(nextCount int) {
	time.Sleep(time.Duration(nextCount) * time.Second)
	m.PurgeCache()
	m.StartPurgeLoop(nextCount)
}

// PurgeCache will pull the data from the in-memory store and drop it into the specified MongoDB collection
func (m *MongoPurger) PurgeCache() {
	if m.dbSession == nil {
		log.Info("Not connected to analytics store, connecting...")
		m.Connect()
		m.PurgeCache()
	} else {
		analyticsCollection := m.dbSession.DB("").C(config.AnalyticsConfig.MongoCollection)

		AnalyticsValues := m.Store.GetAndDeleteSet(ANALYTICS_KEYNAME)

		if len(AnalyticsValues) > 0 {
			keys := make([]interface{}, len(AnalyticsValues), len(AnalyticsValues))

			for i, v := range AnalyticsValues {
				decoded := AnalyticsRecord{}
				err := msgpack.Unmarshal(v.([]byte), &decoded)
				log.Warning("Decoded Record: ", decoded)
				if err != nil {
					log.Error("Couldn't unmarshal analytics data:")
					log.Error(err)
				} else {
					keys[i] = interface{}(decoded)
				}
			}

			err := analyticsCollection.Insert(keys...)
			if err != nil {
				log.Error("Problem inserting to mongo collection")
				log.Error(err)
			}
		}
	}

}

type MockPurger struct {
	Store *RedisStorageManager
}

// Connect does nothing
func (m *MockPurger) Connect() {}

// StartPurgeLoop does nothing
func (m MockPurger) StartPurgeLoop(nextCount int) {}

// PurgeCache will just empty redis
func (m *MockPurger) PurgeCache() {

	KeyValueMap := m.Store.GetKeysAndValues()

	if len(KeyValueMap) > 0 {
		keyNames := make([]string, len(KeyValueMap), len(KeyValueMap))

		i := 0
		for k, _ := range KeyValueMap {
			keyNames[i] = k
			i++
		}

		m.Store.DeleteKeys(keyNames)
	}

}
<commit_msg>Final warnings cleanup<commit_after>package main

import (
	"encoding/csv"
	"fmt"
	"gopkg.in/vmihailenco/msgpack.v2"
	"labix.org/v2/mgo"
	"os"
	"strconv"
	"time"
)

// AnalyticsRecord encodes the details of a request
type AnalyticsRecord struct {
	Method        string
	Path          string
	ContentLength int64
	UserAgent     string
	Day           int
	Month         time.Month
	Year          int
	Hour          int
	ResponseCode  int
	APIKey        string
	TimeStamp     time.Time
	APIVersion    string
	APIName       string
	APIID         string
	OrgID         string
	OauthID       string
	RequestTime   int64
	ExpireAt      time.Time `bson:"expireAt" json:"expireAt"`
}

const (
	ANALYTICS_KEYNAME string = "tyk-system-analytics"
)

func (a *AnalyticsRecord) SetExpiry(expiresInSeconds int64) {
	var expiry time.Duration

	expiry = time.Duration(expiresInSeconds) * time.Second

	if expiresInSeconds == 0 {
		// Expiry is set to 100 years
		expiry = (24 * time.Hour) * (365 * 100)
	}

	t := time.Now()
	t2 := t.Add(expiry)
	a.ExpireAt = t2
}

// AnalyticsError is an error for when writing to the storage engine fails
type AnalyticsError struct{}

func (e AnalyticsError) Error() string {
	return "Recording request failed!"
}

// AnalyticsHandler is an interface to record analytics data to a writer.
type AnalyticsHandler interface {
	RecordHit(AnalyticsRecord) error
}

// Purger is an interface that will define how the in-memory store will be purged
// of analytics data to prevent it growing too large
type Purger interface {
	PurgeCache()
	StartPurgeLoop(int)
}

// RedisAnalyticsHandler implements AnalyticsHandler and will record analytics
// data to a redis back end as defined in the Config object
type RedisAnalyticsHandler struct {
	Store *RedisStorageManager
	Clean Purger
}

// RecordHit will store an AnalyticsRecord in Redis
func (r RedisAnalyticsHandler) RecordHit(thisRecord AnalyticsRecord) error {
	// If we are obfuscating API Keys, store the hashed representation (config check handled in hashing function)
	thisRecord.APIKey = publicHash(thisRecord.APIKey)

	encoded, err := msgpack.Marshal(thisRecord)

	if err != nil {
		log.Error("Error encoding analytics data:")
		log.Error(err)
		return AnalyticsError{}
	}

	r.Store.AppendToSet(ANALYTICS_KEYNAME, string(encoded))

	return nil
}

// CSVPurger purges the in-memory analytics store to a CSV file as defined in the Config object
type CSVPurger struct {
	Store *RedisStorageManager
}

// StartPurgeLoop is used as a goroutine to ensure that the cache is purged
// of analytics data (assuring size is small).
func (c CSVPurger) StartPurgeLoop(nextCount int) {
	time.Sleep(time.Duration(nextCount) * time.Second)
	c.PurgeCache()
	c.StartPurgeLoop(nextCount)
}

// PurgeCache Will pull all the analytics data from the
// cache and drop it to a storage engine, in this case a CSV file
func (c CSVPurger) PurgeCache() {
	curtime := time.Now()
	fname := fmt.Sprintf("%s%d-%s-%d-%d-%d.csv", config.AnalyticsConfig.CSVDir, curtime.Year(), curtime.Month().String(), curtime.Day(), curtime.Hour(), curtime.Minute())

	ferr := os.MkdirAll(config.AnalyticsConfig.CSVDir, 0777)
	if ferr != nil {
		log.Error(ferr)
	}
	outfile, _ := os.Create(fname)
	defer outfile.Close()
	writer := csv.NewWriter(outfile)

	var headers = []string{"METHOD", "PATH", "SIZE", "UA", "DAY", "MONTH", "YEAR", "HOUR", "RESPONSE", "APINAME", "APIVERSION"}

	err := writer.Write(headers)
	if err != nil {
		log.Error("Failed to write file headers!")
		log.Error(err)
	} else {
		KeyValueMap := c.Store.GetKeysAndValues()
		keys := []string{}

		for k, v := range KeyValueMap {
			keys = append(keys, k)
			decoded := AnalyticsRecord{}
			err := msgpack.Unmarshal([]byte(v), &decoded)
			if err != nil {
				log.Error("Couldn't unmarshal analytics data:")
				log.Error(err)
			} else {
				toWrite := []string{
					decoded.Method,
					decoded.Path,
					strconv.FormatInt(decoded.ContentLength, 10),
					decoded.UserAgent,
					strconv.Itoa(decoded.Day),
					decoded.Month.String(),
					strconv.Itoa(decoded.Year),
					strconv.Itoa(decoded.Hour),
					strconv.Itoa(decoded.ResponseCode),
					decoded.APIName,
					decoded.APIVersion}
				err := writer.Write(toWrite)
				if err != nil {
					log.Error("File write failed!")
					log.Error(err)
				}
			}
		}
		writer.Flush()
		c.Store.DeleteKeys(keys)
	}
}

// MongoPurger will purge analytics data into a Mongo database, requires that the Mongo DB string is specified
// in the Config object
type MongoPurger struct {
	Store     *RedisStorageManager
	dbSession *mgo.Session
}

// Connect Connects to Mongo
func (m *MongoPurger) Connect() {
	var err error
	m.dbSession, err = mgo.Dial(config.AnalyticsConfig.MongoURL)
	if err != nil {
		log.Error("Mongo connection failed:")
		log.Panic(err)
	}
}

// StartPurgeLoop starts the loop that will be started as a goroutine and pull data out of the in-memory
// store and into MongoDB
func (m MongoPurger) StartPurgeLoop(nextCount int) {
	time.Sleep(time.Duration(nextCount) * time.Second)
	m.PurgeCache()
	m.StartPurgeLoop(nextCount)
}

// PurgeCache will pull the data from the in-memory store and drop it into the specified MongoDB collection
func (m *MongoPurger) PurgeCache() {
	if m.dbSession == nil {
		log.Info("Not connected to analytics store, connecting...")
		m.Connect()
		m.PurgeCache()
	} else {
		analyticsCollection := m.dbSession.DB("").C(config.AnalyticsConfig.MongoCollection)

		AnalyticsValues := m.Store.GetAndDeleteSet(ANALYTICS_KEYNAME)

		if len(AnalyticsValues) > 0 {
			keys := make([]interface{}, len(AnalyticsValues), len(AnalyticsValues))

			for i, v := range AnalyticsValues {
				decoded := AnalyticsRecord{}
				err := msgpack.Unmarshal(v.([]byte), &decoded)
				log.Debug("Decoded Record: ", decoded)
				if err != nil {
					log.Error("Couldn't unmarshal analytics data:")
					log.Error(err)
				} else {
					keys[i] = interface{}(decoded)
				}
			}

			err := analyticsCollection.Insert(keys...)
			if err != nil {
				log.Error("Problem inserting to mongo collection")
				log.Error(err)
			}
		}
	}

}

type MockPurger struct {
	Store *RedisStorageManager
}

// Connect does nothing
func (m *MockPurger) Connect() {}

// StartPurgeLoop does nothing
func (m MockPurger) StartPurgeLoop(nextCount int) {}

// PurgeCache will just empty redis
func (m *MockPurger) PurgeCache() {

	KeyValueMap := m.Store.GetKeysAndValues()

	if len(KeyValueMap) > 0 {
		keyNames := make([]string, len(KeyValueMap), len(KeyValueMap))

		i := 0
		for k, _ := range KeyValueMap {
			keyNames[i] = k
			i++
		}

		m.Store.DeleteKeys(keyNames)
	}

}
<|endoftext|>


<commit_before>//+build skip

package main

import (
	"encoding/json"
	"fmt"
	bleed "github.com/FiloSottile/Heartbleed/bleed"
	"log"
	"net/http"
	"strings"
)

var PAYLOAD = []byte("heartbleed.filippo.io")

func defaultHandler(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, "http://filippo.io/Heartbleed", http.StatusFound)
}

func testHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hi there.")
}

type result struct {
	Code  int    `json:"code"`
	Data  string `json:"data"`
	Error string `json:"error"`
}

func bleedHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	host := r.URL.Path[len("/bleed/"):]
	if strings.Index(host, ":") == -1 {
		host = host + ":443"
	}
	data, err := bleed.Heartbleed(string(host), PAYLOAD)
	var rc int
	var errS string
	if err == bleed.Safe {
		rc = 1
		data = []byte("")
		log.Printf("%v - SAFE", host)
	} else if err != nil {
		rc = 2
		data = []byte("")
		errS = err.Error()
		log.Printf("%v - ERROR", host)
	} else {
		rc = 0
		log.Printf("%v - VULNERABLE", host)
	}
	res := result{rc, string(data), errS}
	j, err := json.Marshal(res)
	if err != nil {
		log.Println("ERROR", err)
	} else {
		w.Write(j)
	}
}

func main() {
	http.HandleFunc("/", defaultHandler)
	http.HandleFunc("/test", testHandler)
	http.HandleFunc("/bleed/", bleedHandler)
	err := http.ListenAndServe(":80", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>parse passed host before using<commit_after>//+build skip

package main

import (
	"encoding/json"
	"fmt"
	bleed "github.com/FiloSottile/Heartbleed/bleed"
	"log"
	"net/http"
	"net/url"
	"strings"
)

var PAYLOAD = []byte("heartbleed.filippo.io")

func defaultHandler(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, "http://filippo.io/Heartbleed", http.StatusFound)
}

func testHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hi there.")
}

type result struct {
	Code  int    `json:"code"`
	Data  string `json:"data"`
	Error string `json:"error"`
}

func bleedHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	host := r.URL.Path[len("/bleed/"):]
	u, err := url.Parse(host)
	if err == nil {
		host := u.Host
	}
	if strings.Index(host, ":") == -1 {
		host = host + ":443"
	}
	data, err := bleed.Heartbleed(string(host), PAYLOAD)
	var rc int
	var errS string
	if err == bleed.Safe {
		rc = 1
		data = []byte("")
		log.Printf("%v - SAFE", host)
	} else if err != nil {
		rc = 2
		data = []byte("")
		errS = err.Error()
		log.Printf("%v - ERROR", host)
	} else {
		rc = 0
		log.Printf("%v - VULNERABLE", host)
	}
	res := result{rc, string(data), errS}
	j, err := json.Marshal(res)
	if err != nil {
		log.Println("ERROR", err)
	} else {
		w.Write(j)
	}
}

func main() {
	http.HandleFunc("/", defaultHandler)
	http.HandleFunc("/test", testHandler)
	http.HandleFunc("/bleed/", bleedHandler)
	err := http.ListenAndServe(":80", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package api

import (
	"database/sql"
	"net/http"

	"github.com/danjac/kanban/models"
	"github.com/gin-gonic/gin"
)

func addCard(c *gin.Context) {

	card := &models.Card{}

	if err := c.Bind(card); err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	if err := getDB(c).Cards.Create(card); err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	c.JSON(http.StatusOK, card)

}

func getCards(c *gin.Context) {
	cards, err := getDB(c).Cards.GetAll()
	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}
	c.JSON(http.StatusOK, gin.H{"cards": cards})
}

func deleteCard(c *gin.Context) {

	cardID, err := pInt64(c, "id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}
	if err := getDB(c).Cards.Delete(cardID); err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

}

func moveCard(c *gin.Context) {
	cardID, err := pInt64(c, "id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	targetCardID, err := pInt64(c, "target_id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	if err := getDB(c).Cards.Move(cardID, targetCardID); err != nil {
		if err == sql.ErrNoRows {
			c.AbortWithStatus(http.StatusNotFound)
		} else {
			c.AbortWithError(http.StatusInternalServerError, err)
		}
		return
	}

	c.String(http.StatusOK, statusOK)

}

func updateCard(c *gin.Context) {

	cardID, err := pInt64(c, "id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	s := &struct {
		Name string `json:"name" binding:"required,max=60"`
	}{}

	if err := c.Bind(s); err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	if err := getDB(c).Cards.Update(cardID, s.Name); err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	c.String(http.StatusOK, statusOK)

}

func addTask(c *gin.Context) {

	cardID, err := pInt64(c, "id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	task := &models.Task{CardID: cardID}
	if err := c.Bind(task); err != nil {
		return
	}
	if err := getDB(c).Tasks.Create(task); err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	c.JSON(http.StatusOK, task)
}

func cardRoutes(api *gin.RouterGroup, prefix string) {

	g := api.Group(prefix)
	{
		g.GET("", getCards)
		g.POST("", addCard)
		g.DELETE(":id", deleteCard)
		g.PUT(":id", updateCard)
		g.PUT(":id/move/:target_id", moveCard)
		g.POST(":id/add/", addTask)
	}

}
<commit_msg>Add status to delete<commit_after>package api

import (
	"database/sql"
	"net/http"

	"github.com/danjac/kanban/models"
	"github.com/gin-gonic/gin"
)

func addCard(c *gin.Context) {

	card := &models.Card{}

	if err := c.Bind(card); err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	if err := getDB(c).Cards.Create(card); err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	c.JSON(http.StatusOK, card)

}

func getCards(c *gin.Context) {
	cards, err := getDB(c).Cards.GetAll()
	if err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}
	c.JSON(http.StatusOK, gin.H{"cards": cards})
}

func deleteCard(c *gin.Context) {

	cardID, err := pInt64(c, "id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}
	if err := getDB(c).Cards.Delete(cardID); err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	c.String(http.StatusOK, statusOK)
}

func moveCard(c *gin.Context) {
	cardID, err := pInt64(c, "id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	targetCardID, err := pInt64(c, "target_id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	if err := getDB(c).Cards.Move(cardID, targetCardID); err != nil {
		if err == sql.ErrNoRows {
			c.AbortWithStatus(http.StatusNotFound)
		} else {
			c.AbortWithError(http.StatusInternalServerError, err)
		}
		return
	}

	c.String(http.StatusOK, statusOK)

}

func updateCard(c *gin.Context) {

	cardID, err := pInt64(c, "id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	s := &struct {
		Name string `json:"name" binding:"required,max=60"`
	}{}

	if err := c.Bind(s); err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	if err := getDB(c).Cards.Update(cardID, s.Name); err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	c.String(http.StatusOK, statusOK)

}

func addTask(c *gin.Context) {

	cardID, err := pInt64(c, "id")

	if err != nil {
		c.AbortWithError(http.StatusBadRequest, err)
		return
	}

	task := &models.Task{CardID: cardID}
	if err := c.Bind(task); err != nil {
		return
	}
	if err := getDB(c).Tasks.Create(task); err != nil {
		c.AbortWithError(http.StatusInternalServerError, err)
		return
	}

	c.JSON(http.StatusOK, task)
}

func cardRoutes(api *gin.RouterGroup, prefix string) {

	g := api.Group(prefix)
	{
		g.GET("", getCards)
		g.POST("", addCard)
		g.DELETE(":id", deleteCard)
		g.PUT(":id", updateCard)
		g.PUT(":id/move/:target_id", moveCard)
		g.POST(":id/add/", addTask)
	}

}
<|endoftext|>


<commit_before>package cmd

import (
	"io"
	"math/rand"
	"net/http"
	"strings"
	"time"
)

const defaultTimeout = 1000 * time.Millisecond

var (
	totalRequest = 0
)

func makeHttpClients(totalClients uint) []*http.Client {
	clients := make([]*http.Client, totalClients)
	for i := range clients {
		clients[i] = &http.Client{Transport: &http.Transport{}, Timeout: defaultTimeout}
	}
	return clients
}

func makeMetaRequest(path string) *http.Request {
	req, _ := http.NewRequest("GET", strings.Join([]string{getEndpoint(), path}, ""), nil)
	req.Header.Set("Accept", "application/json")
	if xff != "" {
		req.Header.Set("X-Forwarded-For", xff)
	}
	totalRequest = totalRequest + 1
	return req
}

func makeManageRequest(method, api string, body io.Reader) *http.Request {
	req, _ := http.NewRequest(method, strings.Join([]string{manageEndpoint, api}, ""), body)
	req.Header.Set("Accept", "application/json")
	return req
}

func getEndpoint() string {
	if len(endpoints) == 1 {
		return endpoints[0]
	}
	return endpoints[totalRequest%len(endpoints)]
}

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
	letterIdxBits = 6                    // 6 bits to represent a letter index
	letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
	letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
)

var src = rand.NewSource(time.Now().UnixNano())

//https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang
func RandomString(n int) string {
	b := make([]byte, n)
	// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
	for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
		if remain == 0 {
			cache, remain = src.Int63(), letterIdxMax
		}
		if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
			b[i] = letterBytes[idx]
			i--
		}
		cache >>= letterIdxBits
		remain--
	}

	return string(b)
}

func clientDo(client *http.Client, requests <-chan *http.Request) {
	defer wg.Done()

	for req := range requests {
		st := time.Now()
		resp, err := client.Do(req)
		var errStr string
		if err != nil {
			errStr = err.Error()
		}
		results <- result{errStr: errStr, duration: time.Since(st), happened: time.Now()}
		if resp != nil {
			resp.Body.Close()
		}
		bar.Increment()
	}
}
<commit_msg>optimize benchmark transport config<commit_after>package cmd

import (
	"io"
	"math/rand"
	"net/http"
	"strings"
	"time"
)

const defaultTimeout = 1000 * time.Millisecond

var (
	totalRequest = 0
)

func makeHttpClients(totalClients uint) []*http.Client {
	clients := make([]*http.Client, totalClients)
	for i := range clients {
		transport := &http.Transport{}
		transport.MaxIdleConnsPerHost = 10000
		clients[i] = &http.Client{Transport: transport, Timeout: defaultTimeout}
	}
	return clients
}

func makeMetaRequest(path string) *http.Request {
	req, _ := http.NewRequest("GET", strings.Join([]string{getEndpoint(), path}, ""), nil)
	req.Header.Set("Accept", "application/json")
	if xff != "" {
		req.Header.Set("X-Forwarded-For", xff)
	}
	totalRequest = totalRequest + 1
	return req
}

func makeManageRequest(method, api string, body io.Reader) *http.Request {
	req, _ := http.NewRequest(method, strings.Join([]string{manageEndpoint, api}, ""), body)
	req.Header.Set("Accept", "application/json")
	return req
}

func getEndpoint() string {
	if len(endpoints) == 1 {
		return endpoints[0]
	}
	return endpoints[totalRequest%len(endpoints)]
}

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
	letterIdxBits = 6                    // 6 bits to represent a letter index
	letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
	letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
)

var src = rand.NewSource(time.Now().UnixNano())

//https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang
func RandomString(n int) string {
	b := make([]byte, n)
	// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
	for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
		if remain == 0 {
			cache, remain = src.Int63(), letterIdxMax
		}
		if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
			b[i] = letterBytes[idx]
			i--
		}
		cache >>= letterIdxBits
		remain--
	}

	return string(b)
}

func clientDo(client *http.Client, requests <-chan *http.Request) {
	defer wg.Done()

	for req := range requests {
		st := time.Now()
		resp, err := client.Do(req)
		var errStr string
		if err != nil {
			errStr = err.Error()
		}
		results <- result{errStr: errStr, duration: time.Since(st), happened: time.Now()}
		if resp != nil {
			resp.Body.Close()
		}
		bar.Increment()
	}
}
<|endoftext|>


<commit_before>package goal_test

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"

	"github.com/garyburd/redigo/redis"
	"github.com/jinzhu/gorm"
	"github.com/thomasdao/goal"
)

var server *httptest.Server

type testuser struct {
	ID   uint `gorm:"primary_key"`
	Name string
	Age  int
}

func (user *testuser) Get(w http.ResponseWriter, request *http.Request) (int, interface{}) {
	return goal.Read(user, request)
}

func (user *testuser) Post(w http.ResponseWriter, request *http.Request) (int, interface{}) {
	return goal.Create(user, request)
}

func (user *testuser) Put(w http.ResponseWriter, request *http.Request) (int, interface{}) {
	return goal.Update(user, request)
}

func (user *testuser) Delete(w http.ResponseWriter, request *http.Request) (int, interface{}) {
	return goal.Delete(user, request)
}

var db gorm.DB

var (
	redisAddress   = flag.String("redis-address", ":6379", "Address to the Redis server")
	maxConnections = flag.Int("max-connections", 10, "Max connections to Redis")
)

func setup() {
	var err error
	db, err = gorm.Open("sqlite3", ":memory:")
	if err != nil {
		panic(err)
	}

	db.SingularTable(true)

	// Setup database
	goal.InitGormDb(&db)

	// Setup redis
	pool := redis.NewPool(func() (redis.Conn, error) {
		c, err := redis.Dial("tcp", *redisAddress)

		if err != nil {
			return nil, err
		}

		return c, err
	}, *maxConnections)

	goal.InitRedisPool(pool)

	// Initialize API
	api := goal.NewAPI()

	// Initialize resource
	var user testuser
	db.AutoMigrate(&user)

	// Add default path
	api.AddDefaultCrudPaths(&user)

	// Setup testing server
	server = httptest.NewServer(api.Mux())
}

func tearDown() {
	if server != nil {
		server.Close()
	}

	if goal.DB() != nil {
		db.Close()
	}

	if goal.Pool() != nil {
		goal.RedisClearAll()
		goal.Pool().Close()
	}
}

func userURL() string {
	return fmt.Sprint(server.URL, "/testuser")
}

func idURL(id uint) string {
	return fmt.Sprint(server.URL, "/testuser/", id)
}

func TestCreate(t *testing.T) {
	setup()
	defer tearDown()

	var json = []byte(`{"Name":"Thomas", "Age": 28}`)
	req, _ := http.NewRequest("POST", userURL(), bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	// Get response
	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {
		t.Error(err)
	}

	if res.StatusCode != 200 {
		t.Error("Request Failed ", res.StatusCode)
		return
	}

	// Make sure db has one object
	var user testuser
	db.Where("name = ?", "Thomas").First(&user)
	if &user == nil {
		t.Error("Fail to save object to database")
		return
	}

	if user.Name != "Thomas" || user.Age != 28 {
		t.Error("Save wrong data or missing data")
	}

	// Make sure data exists in Redis
	if goal.Pool() != nil {
		key := goal.RedisKey(user)
		var redisUser testuser
		goal.RedisGet(key, &redisUser)
		if !reflect.DeepEqual(user, redisUser) {
			t.Error("Incorrect data in redis, ", user, redisUser)
		}
	}
}

func TestGet(t *testing.T) {
	setup()
	defer tearDown()

	user := &testuser{}
	user.Name = "Thomas"
	user.Age = 28
	db.Create(user)

	req, _ := http.NewRequest("GET", idURL(user.ID), nil)
	req.Header.Set("Content-Type", "application/json")

	// Get response
	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {
		t.Error(err)
	}

	if res.StatusCode != 200 {
		t.Error("Request Failed")
		return
	}

	defer res.Body.Close()
	content, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Error(err)
		return
	}

	var result testuser
	err = json.Unmarshal(content, &result)

	if err != nil {
		t.Error(err)
		return
	}

	if result.ID != user.ID || result.Name != user.Name || result.Age != user.Age {
		t.Error("Response is invalid")
	}

	// Make sure data exists in Redis
	if goal.Pool() != nil {
		key := goal.RedisKey(user)

		// Test data exists in Redis
		if exist, _ := goal.RedisExists(key); !exist {
			t.Error("Data should be saved into Redis")
		}

		var redisUser testuser
		goal.RedisGet(key, &redisUser)
		if !reflect.DeepEqual(user, &redisUser) {
			t.Error("Incorrect data in redis, ", user, &redisUser)
		}
	}
}

func TestPut(t *testing.T) {
	setup()
	defer tearDown()

	user := &testuser{}
	user.Name = "Thomas"
	user.Age = 28
	db.Create(user)

	var json = []byte(`{"Name":"Thomas Dao"}`)
	req, _ := http.NewRequest("PUT", idURL(user.ID), bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	// Get response
	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {
		t.Error(err)
	}

	if res.StatusCode != 200 {
		t.Error("Request Failed")
		return
	}

	var result testuser
	if db.Where("name = ?", "Thomas Dao").First(&result).RecordNotFound() {
		t.Error("Update unsuccessful")
	}

	if result.ID != user.ID || result.Age != user.Age {
		t.Error("Incorrect update")
	}

	// Make sure data exists in Redis
	if goal.Pool() != nil {
		key := goal.RedisKey(user)
		var redisUser testuser
		goal.RedisGet(key, &redisUser)
		if !reflect.DeepEqual(result, redisUser) {
			t.Error("Incorrect data in redis, ", result, redisUser)
		}
	}
}

func TestDelete(t *testing.T) {
	setup()
	defer tearDown()

	user := &testuser{}
	user.Name = "Thomas"
	user.Age = 28
	db.Create(user)

	fmt.Println("Object Id created", user.ID)

	req, _ := http.NewRequest("DELETE", idURL(user.ID), nil)
	req.Header.Set("Content-Type", "application/json")

	// Get response
	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {
		t.Error(err)
	}

	if res.StatusCode != 200 {
		t.Error("Request Failed")
		return
	}

	var result testuser
	if !db.Where("name = ?", "Thomas").First(&result).RecordNotFound() {
		t.Error("Delete is not successful. Expected result delete from db")
	}

	// Make sure no more data in redis
	if goal.Pool() != nil {
		key := goal.RedisKey(user)
		if exist, _ := goal.RedisExists(key); exist {
			t.Error("Data should be deleted from Redis when object is deleted")
		}
	}

}
<commit_msg>Fix test<commit_after>package goal_test

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"

	"github.com/garyburd/redigo/redis"
	"github.com/jinzhu/gorm"
	"github.com/thomasdao/goal"
)

var server *httptest.Server

type testuser struct {
	ID   uint `gorm:"primary_key"`
	Name string
	Age  int
}

func (user *testuser) Get(w http.ResponseWriter, request *http.Request) (int, interface{}) {
	return goal.Read(user, request)
}

func (user *testuser) Post(w http.ResponseWriter, request *http.Request) (int, interface{}) {
	return goal.Create(user, request)
}

func (user *testuser) Put(w http.ResponseWriter, request *http.Request) (int, interface{}) {
	return goal.Update(user, request)
}

func (user *testuser) Delete(w http.ResponseWriter, request *http.Request) (int, interface{}) {
	return goal.Delete(user, request)
}

var db gorm.DB

var (
	redisAddress   = flag.String("redis-address", ":6379", "Address to the Redis server")
	maxConnections = flag.Int("max-connections", 10, "Max connections to Redis")
)

func setup() {
	var err error
	db, err = gorm.Open("sqlite3", ":memory:")
	if err != nil {
		panic(err)
	}

	db.SingularTable(true)

	// Setup database
	goal.InitGormDb(&db)

	// Setup redis
	pool := redis.NewPool(func() (redis.Conn, error) {
		c, err := redis.Dial("tcp", *redisAddress)

		if err != nil {
			return nil, err
		}

		return c, err
	}, *maxConnections)

	goal.InitRedisPool(pool)

	// Initialize API
	api := goal.NewAPI()

	// Initialize resource
	var user testuser
	db.AutoMigrate(&user)

	// Add default path
	api.AddDefaultCrudPaths(&user)

	// Setup testing server
	server = httptest.NewServer(api.Mux())
}

func tearDown() {
	if server != nil {
		server.Close()
	}

	if goal.DB() != nil {
		db.Close()
	}

	if goal.Pool() != nil {
		goal.RedisClearAll()
		goal.Pool().Close()
	}
}

func userURL() string {
	return fmt.Sprint(server.URL, "/testuser")
}

func idURL(id interface{}) string {
	return fmt.Sprint(server.URL, "/testuser/", id)
}

func TestCreate(t *testing.T) {
	setup()
	defer tearDown()

	var json = []byte(`{"Name":"Thomas", "Age": 28}`)
	req, _ := http.NewRequest("POST", userURL(), bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	// Get response
	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {
		t.Error(err)
	}

	if res.StatusCode != 200 {
		t.Error("Request Failed ", res.StatusCode)
		return
	}

	// Make sure db has one object
	var user testuser
	db.Where("name = ?", "Thomas").First(&user)
	if &user == nil {
		t.Error("Fail to save object to database")
		return
	}

	if user.Name != "Thomas" || user.Age != 28 {
		t.Error("Save wrong data or missing data")
	}

	// Make sure data exists in Redis
	if goal.Pool() != nil {
		key := goal.RedisKey(user)
		var redisUser testuser
		goal.RedisGet(key, &redisUser)
		if !reflect.DeepEqual(user, redisUser) {
			t.Error("Incorrect data in redis, ", user, redisUser)
		}
	}
}

func TestGet(t *testing.T) {
	setup()
	defer tearDown()

	user := &testuser{}
	user.Name = "Thomas"
	user.Age = 28
	db.Create(user)

	req, _ := http.NewRequest("GET", idURL(user.ID), nil)
	req.Header.Set("Content-Type", "application/json")

	// Get response
	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {
		t.Error(err)
	}

	if res.StatusCode != 200 {
		t.Error("Request Failed")
		return
	}

	defer res.Body.Close()
	content, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Error(err)
		return
	}

	var result testuser
	err = json.Unmarshal(content, &result)

	if err != nil {
		t.Error(err)
		return
	}

	if result.ID != user.ID || result.Name != user.Name || result.Age != user.Age {
		t.Error("Response is invalid")
	}

	// Make sure data exists in Redis
	if goal.Pool() != nil {
		key := goal.RedisKey(user)

		// Test data exists in Redis
		if exist, _ := goal.RedisExists(key); !exist {
			t.Error("Data should be saved into Redis")
		}

		var redisUser testuser
		goal.RedisGet(key, &redisUser)
		if !reflect.DeepEqual(user, &redisUser) {
			t.Error("Incorrect data in redis, ", user, &redisUser)
		}
	}
}

func TestPut(t *testing.T) {
	setup()
	defer tearDown()

	user := &testuser{}
	user.Name = "Thomas"
	user.Age = 28
	db.Create(user)

	var json = []byte(`{"Name":"Thomas Dao"}`)
	req, _ := http.NewRequest("PUT", idURL(user.ID), bytes.NewBuffer(json))
	req.Header.Set("Content-Type", "application/json")

	// Get response
	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {
		t.Error(err)
	}

	if res.StatusCode != 200 {
		t.Error("Request Failed")
		return
	}

	var result testuser
	if db.Where("name = ?", "Thomas Dao").First(&result).RecordNotFound() {
		t.Error("Update unsuccessful")
	}

	if result.ID != user.ID || result.Age != user.Age {
		t.Error("Incorrect update")
	}

	// Make sure data exists in Redis
	if goal.Pool() != nil {
		key := goal.RedisKey(user)
		var redisUser testuser
		goal.RedisGet(key, &redisUser)
		if !reflect.DeepEqual(result, redisUser) {
			t.Error("Incorrect data in redis, ", result, redisUser)
		}
	}
}

func TestDelete(t *testing.T) {
	setup()
	defer tearDown()

	user := &testuser{}
	user.Name = "Thomas"
	user.Age = 28
	db.Create(user)

	fmt.Println("Object Id created", user.ID)

	req, _ := http.NewRequest("DELETE", idURL(user.ID), nil)
	req.Header.Set("Content-Type", "application/json")

	// Get response
	client := &http.Client{}
	res, err := client.Do(req)

	if err != nil {
		t.Error(err)
	}

	if res.StatusCode != 200 {
		t.Error("Request Failed")
		return
	}

	var result testuser
	if !db.Where("name = ?", "Thomas").First(&result).RecordNotFound() {
		t.Error("Delete is not successful. Expected result delete from db")
	}

	// Make sure no more data in redis
	if goal.Pool() != nil {
		key := goal.RedisKey(user)
		if exist, _ := goal.RedisExists(key); exist {
			t.Error("Data should be deleted from Redis when object is deleted")
		}
	}

}
<|endoftext|>


<commit_before>package cliapp

import "github.com/mitchellh/cli"
import "github.com/bpicode/fritzctl/logger"

type sessionIDCommand struct {
}

func (cmd *sessionIDCommand) Help() string {
	return "Obtain a session ID"
}

func (cmd *sessionIDCommand) Synopsis() string {
	return "Obtain a session ID"
}

func (cmd *sessionIDCommand) Run(args []string) int {
	client := clientLogin()
	logger.Success("Sucessfully obtained session ID: " + client.SessionInfo.SID)
	return 0
}

func sessionID() (cli.Command, error) {
	p := sessionIDCommand{}
	return &p, nil
}
<commit_msg>fix typo<commit_after>package cliapp

import "github.com/mitchellh/cli"
import "github.com/bpicode/fritzctl/logger"

type sessionIDCommand struct {
}

func (cmd *sessionIDCommand) Help() string {
	return "Obtain a session ID"
}

func (cmd *sessionIDCommand) Synopsis() string {
	return "Obtain a session ID"
}

func (cmd *sessionIDCommand) Run(args []string) int {
	client := clientLogin()
	logger.Success("Successfully obtained session ID: " + client.SessionInfo.SID)
	return 0
}

func sessionID() (cli.Command, error) {
	p := sessionIDCommand{}
	return &p, nil
}
<|endoftext|>


<commit_before>package api

import (
	"io/ioutil"
	"net/http"
	"os"

	"github.com/anyweez/kickoff/utils"
	"github.com/anyweez/matchgrab/config"
)

// Get : Make a request to the Riot API and call the specified function on success.
func Get(url string, cb func(body []byte)) error {
	client := http.Client{
		Timeout: config.Config.HTTPTimeout,
	}

	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		utils.Log(err.Error())
		return err
	}
	request.Header.Set("X-Riot-Token", os.Getenv("RIOT_API_KEY"))

	resp, err := client.Do(request)
	if err != nil {
		return err
	}

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

	cb(raw)

	return nil
}
<commit_msg>Fixed broken dependency (obsolete project)<commit_after>package api

import (
	"io/ioutil"
	"net/http"
	"os"

	"github.com/anyweez/matchgrab/config"
	"github.com/anyweez/matchgrab/utils"
)

// Get : Make a request to the Riot API and call the specified function on success.
func Get(url string, cb func(body []byte)) error {
	client := http.Client{
		Timeout: config.Config.HTTPTimeout,
	}

	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		utils.Log(err.Error())
		return err
	}
	request.Header.Set("X-Riot-Token", os.Getenv("RIOT_API_KEY"))

	resp, err := client.Do(request)
	if err != nil {
		return err
	}

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

	cb(raw)

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"testing"
)

func TestRandomCodePoint(t *testing.T) {
	for _, b := range Blocks {
		var cp rune
		cp = b.RandomCodePoint()

		if cp < b.start || cp > b.end {
			t.Fail()
		}
	}
}

func BenchmarkRandomCodePoint(b *testing.B) {
	testBlock := &UnicodeBlock{0x0000, 0x10ffff}
	for i := 0; i < b.N; i++ {
		testBlock.RandomCodePoint()
	}
}
<commit_msg>Remove var declaration from loop<commit_after>package main

import (
	"testing"
)

func TestRandomCodePoint(t *testing.T) {
	var cp rune
	for _, b := range Blocks {
		cp = b.RandomCodePoint()
		if cp < b.start || cp > b.end {
			t.Fail()
		}
	}
}

func BenchmarkRandomCodePoint(b *testing.B) {
	testBlock := &UnicodeBlock{0x0000, 0x10ffff}
	for i := 0; i < b.N; i++ {
		testBlock.RandomCodePoint()
	}
}
<|endoftext|>


<commit_before>package deje

type Manageable interface {
	GetId() string
	GetParentId() string

	ProvenWrong() bool
	SetProvenWrong()
}

type ManageableSet map[string]Manageable

type ObjectManager struct {
	by_id     ManageableSet
	by_parent map[string]ManageableSet
}

func (om *ObjectManager) Register(m Manageable) {
	id := m.GetId()
	om.by_id[id] = m

	pid := m.GetParentId()
	pchildren := om.by_parent[pid]
	pchildren[id] = m
}

func (om *ObjectManager) Unregister(m Manageable) {
	id := m.GetId()
	pid := m.GetParentId()

	delete(om.by_id, id)
	pchildren := om.by_parent[pid]
	delete(pchildren, id)
}

func (om *ObjectManager) GetParent(m Manageable) (Manageable, bool) {
	pid := m.GetParentId()
	p, ok := om.by_id[pid]
	return p, ok
}

func (om *ObjectManager) GetRoot(m Manageable) Manageable {
	for {
		parent, had_p := om.GetParent(m)
		if had_p {
			m = parent
		} else {
			return m
		}
	}
}
<commit_msg>Simplify manager class to only do grouping<commit_after>package deje

type Manageable interface {
	GetKey() string
	GetGroupKey() string
}

type ManageableSet map[string]Manageable

type ObjectManager struct {
	by_key   ManageableSet
	by_group map[string]ManageableSet
}

func (om *ObjectManager) Register(m Manageable) {
	k := m.GetKey()
	gk := m.GetGroupKey()
	group := om.by_group[gk]

	om.by_key[k] = m
	group[k] = m
}

func (om *ObjectManager) Unregister(m Manageable) {
	k := m.GetKey()
	gk := m.GetGroupKey()
	group := om.by_group[gk]

	delete(om.by_key, k)
	delete(group, k)
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// A helper that allows using gcsfuse with mount(8).
//
// Can be invoked using a command-line of the form expected for mount helpers.
// Calls the gcsfuse binary, which it finds from one of a list of expected
// locations, and waits for it to complete. The device and mount point are
// passed on as positional arguments, and other known options are converted to
// appropriate flags.
//
// This binary returns with exit code zero only after gcsfuse has reported that
// it has successfully mounted the file system. Further output from gcsfuse is
// suppressed.
package main

// Example invocation on OS X:
//
//     mount -t porp -o foo=bar\ baz -o ro,blah bucket ~/tmp/mp
//
// becomes the following arguments:
//
//     Arg 0: "/sbin/mount_gcsfuse "
//     Arg 1: "-o"
//     Arg 2: "foo=bar baz"
//     Arg 3: "-o"
//     Arg 4: "ro"
//     Arg 5: "-o"
//     Arg 6: "blah"
//     Arg 7: "bucket"
//     Arg 8: "/path/to/mp"
//
// On Linux, the fstab entry
//
//     bucket /path/to/mp porp user,foo=bar\040baz
//
// becomes
//
//     Arg 0: "/sbin/mount.gcsfuse"
//     Arg 1: "bucket"
//     Arg 2: "/path/to/mp"
//     Arg 3: "-o"
//     Arg 4: "rw,noexec,nosuid,nodev,user,foo=bar baz"
//

import (
	"fmt"
	"os"
	"os/exec"
	"path"
	"strings"

	"github.com/googlecloudplatform/gcsfuse/internal/mount"
)

// Turn mount-style options into gcsfuse arguments. Skip known detritus that
// the mount command gives us.
//
// The result of this function should be appended to exec.Command.Args.
func makeGcsfuseArgs(
	device string,
	mountPoint string,
	opts map[string]string) (args []string, err error) {
	// Deal with options.
	for name, value := range opts {
		switch name {
		// Don't pass through options that are relevant to mount(8) but not to
		// gcsfuse, and that fusermount chokes on with "Invalid argument" on Linux.
		case "user", "nouser", "auto", "noauto", "_netdev", "no_netdev":

		// Special case: support mount-like formatting for gcsfuse bool flags.
		case "implicit_dirs", "disable_http2":
			args = append(args, "--"+strings.Replace(name, "_", "-", -1))

		// Special case: support mount-like formatting for gcsfuse string flags.
		case "dir_mode",
			"file_mode",
			"uid",
			"gid",
			"app_name",
			"only_dir",
			"billing_project",
			"key_file",
			"token_url",
			"limit_bytes_per_sec",
			"limit_ops_per_sec",
			"rename_dir_limit",
			"max_retry_sleep",
			"stat_cache_capacity",
			"stat_cache_ttl",
			"type_cache_ttl",
			"local_file_cache",
			"temp_dir",
			"max_conns_per_host",
			"monitoring_port",
			"log_format",
			"log_file":
			args = append(args, "--"+strings.Replace(name, "_", "-", -1), value)

		// Special case: support mount-like formatting for gcsfuse debug flags.
		case "debug_fuse",
			"debug_fs",
			"debug_gcs",
			"debug_http",
			"debug_invariants",
			"debug_mutex":
			args = append(args, "--"+name)

		// Pass through everything else.
		default:
			var formatted string
			if value == "" {
				formatted = name
			} else {
				formatted = fmt.Sprintf("%s=%s", name, value)
			}

			args = append(args, "-o", formatted)
		}
	}

	// Set the bucket and mount point.
	args = append(args, device, mountPoint)

	return
}

// Parse the supplied command-line arguments from a mount(8) invocation on OS X
// or Linux.
func parseArgs(
	args []string) (
	device string,
	mountPoint string,
	opts map[string]string,
	err error) {
	opts = make(map[string]string)

	// Process each argument in turn.
	positionalCount := 0
	for i, s := range args {
		switch {
		// Skip the program name.
		case i == 0:
			continue

		// "-o" is illegal only when at the end. We handle its argument in the case
		// below.
		case s == "-o":
			if i == len(args)-1 {
				err = fmt.Errorf("Unexpected -o at end of args.")
				return
			}

		// systemd passes -n (alias --no-mtab) to the mount helper. This seems to
		// be a result of the new setup on many Linux systems with /etc/mtab as a
		// symlink pointing to /proc/self/mounts. /proc/self/mounts is read-only,
		// so any helper that would normally write to /etc/mtab should be
		// configured not to do so. Because systemd does not provide a way to
		// disable this behavior for mount helpers that do not write to /etc/mtab,
		// we ignore the flag.
		case s == "-n":
			continue

		// Is this an options string following a "-o"?
		case i > 0 && args[i-1] == "-o":
			mount.ParseOptions(opts, s)

		// Is this the device?
		case positionalCount == 0:
			device = s
			positionalCount++

		// Is this the mount point?
		case positionalCount == 1:
			mountPoint = s
			positionalCount++

		default:
			err = fmt.Errorf("Unexpected arg %d: %q", i, s)
			return
		}
	}

	if positionalCount != 2 {
		err = fmt.Errorf("Expected two positional arguments; got %d.", positionalCount)
		return
	}

	return
}

func run(args []string) (err error) {
	// If invoked with a single "--help" argument, print a usage message and exit
	// successfully.
	if len(args) == 2 && args[1] == "--help" {
		fmt.Fprintf(
			os.Stderr,
			"Usage: %s [-o options] bucket_name mount_point\n",
			args[0])

		return
	}

	// Find the path to gcsfuse.
	gcsfusePath, err := findGcsfuse()
	if err != nil {
		err = fmt.Errorf("findGcsfuse: %w", err)
		return
	}

	// Find the path to fusermount.
	fusermountPath, err := findFusermount()
	if err != nil {
		err = fmt.Errorf("findFusermount: %w", err)
		return
	}

	// Attempt to parse arguments.
	device, mountPoint, opts, err := parseArgs(args)
	if err != nil {
		err = fmt.Errorf("parseArgs: %w", err)
		return
	}

	// Choose gcsfuse args.
	gcsfuseArgs, err := makeGcsfuseArgs(device, mountPoint, opts)
	if err != nil {
		err = fmt.Errorf("makeGcsfuseArgs: %w", err)
		return
	}

	fmt.Fprintf(
		os.Stderr,
		"Calling gcsfuse with arguments: %s\n",
		strings.Join(gcsfuseArgs, " "))

	// Run gcsfuse.
	cmd := exec.Command(gcsfusePath, gcsfuseArgs...)
	cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s", path.Dir(fusermountPath)))

	// Pass through the https_proxy/http_proxy environment variable,
	// in case the host requires a proxy server to reach the GCS endpoint.
	// http_proxy has precedence over http_proxy, in case both are set
	if p, ok := os.LookupEnv("https_proxy"); ok {
		cmd.Env = append(cmd.Env, fmt.Sprintf("https_proxy=%s", p))
	} else if p, ok := os.LookupEnv("http_proxy"); ok {
		cmd.Env = append(cmd.Env, fmt.Sprintf("http_proxy=%s", p))
	}

	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err = cmd.Run()
	if err != nil {
		err = fmt.Errorf("running gcsfuse: %w", err)
		return
	}

	return
}

func main() {
	err := run(os.Args)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
}
<commit_msg>Update args for mount.gcsfuse with new flag for monitoring<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// A helper that allows using gcsfuse with mount(8).
//
// Can be invoked using a command-line of the form expected for mount helpers.
// Calls the gcsfuse binary, which it finds from one of a list of expected
// locations, and waits for it to complete. The device and mount point are
// passed on as positional arguments, and other known options are converted to
// appropriate flags.
//
// This binary returns with exit code zero only after gcsfuse has reported that
// it has successfully mounted the file system. Further output from gcsfuse is
// suppressed.
package main

// Example invocation on OS X:
//
//     mount -t porp -o foo=bar\ baz -o ro,blah bucket ~/tmp/mp
//
// becomes the following arguments:
//
//     Arg 0: "/sbin/mount_gcsfuse "
//     Arg 1: "-o"
//     Arg 2: "foo=bar baz"
//     Arg 3: "-o"
//     Arg 4: "ro"
//     Arg 5: "-o"
//     Arg 6: "blah"
//     Arg 7: "bucket"
//     Arg 8: "/path/to/mp"
//
// On Linux, the fstab entry
//
//     bucket /path/to/mp porp user,foo=bar\040baz
//
// becomes
//
//     Arg 0: "/sbin/mount.gcsfuse"
//     Arg 1: "bucket"
//     Arg 2: "/path/to/mp"
//     Arg 3: "-o"
//     Arg 4: "rw,noexec,nosuid,nodev,user,foo=bar baz"
//

import (
	"fmt"
	"os"
	"os/exec"
	"path"
	"strings"

	"github.com/googlecloudplatform/gcsfuse/internal/mount"
)

// Turn mount-style options into gcsfuse arguments. Skip known detritus that
// the mount command gives us.
//
// The result of this function should be appended to exec.Command.Args.
func makeGcsfuseArgs(
	device string,
	mountPoint string,
	opts map[string]string) (args []string, err error) {
	// Deal with options.
	for name, value := range opts {
		switch name {
		// Don't pass through options that are relevant to mount(8) but not to
		// gcsfuse, and that fusermount chokes on with "Invalid argument" on Linux.
		case "user", "nouser", "auto", "noauto", "_netdev", "no_netdev":

		// Special case: support mount-like formatting for gcsfuse bool flags.
		case "implicit_dirs", "disable_http2":
			args = append(args, "--"+strings.Replace(name, "_", "-", -1))

		// Special case: support mount-like formatting for gcsfuse string flags.
		case "dir_mode",
			"file_mode",
			"uid",
			"gid",
			"app_name",
			"only_dir",
			"billing_project",
			"key_file",
			"token_url",
			"limit_bytes_per_sec",
			"limit_ops_per_sec",
			"rename_dir_limit",
			"max_retry_sleep",
			"stat_cache_capacity",
			"stat_cache_ttl",
			"type_cache_ttl",
			"local_file_cache",
			"temp_dir",
			"max_conns_per_host",
			"stackdriver_export_interval",
			"log_format",
			"log_file":
			args = append(args, "--"+strings.Replace(name, "_", "-", -1), value)

		// Special case: support mount-like formatting for gcsfuse debug flags.
		case "debug_fuse",
			"debug_fs",
			"debug_gcs",
			"debug_http",
			"debug_invariants",
			"debug_mutex":
			args = append(args, "--"+name)

		// Pass through everything else.
		default:
			var formatted string
			if value == "" {
				formatted = name
			} else {
				formatted = fmt.Sprintf("%s=%s", name, value)
			}

			args = append(args, "-o", formatted)
		}
	}

	// Set the bucket and mount point.
	args = append(args, device, mountPoint)

	return
}

// Parse the supplied command-line arguments from a mount(8) invocation on OS X
// or Linux.
func parseArgs(
	args []string) (
	device string,
	mountPoint string,
	opts map[string]string,
	err error) {
	opts = make(map[string]string)

	// Process each argument in turn.
	positionalCount := 0
	for i, s := range args {
		switch {
		// Skip the program name.
		case i == 0:
			continue

		// "-o" is illegal only when at the end. We handle its argument in the case
		// below.
		case s == "-o":
			if i == len(args)-1 {
				err = fmt.Errorf("Unexpected -o at end of args.")
				return
			}

		// systemd passes -n (alias --no-mtab) to the mount helper. This seems to
		// be a result of the new setup on many Linux systems with /etc/mtab as a
		// symlink pointing to /proc/self/mounts. /proc/self/mounts is read-only,
		// so any helper that would normally write to /etc/mtab should be
		// configured not to do so. Because systemd does not provide a way to
		// disable this behavior for mount helpers that do not write to /etc/mtab,
		// we ignore the flag.
		case s == "-n":
			continue

		// Is this an options string following a "-o"?
		case i > 0 && args[i-1] == "-o":
			mount.ParseOptions(opts, s)

		// Is this the device?
		case positionalCount == 0:
			device = s
			positionalCount++

		// Is this the mount point?
		case positionalCount == 1:
			mountPoint = s
			positionalCount++

		default:
			err = fmt.Errorf("Unexpected arg %d: %q", i, s)
			return
		}
	}

	if positionalCount != 2 {
		err = fmt.Errorf("Expected two positional arguments; got %d.", positionalCount)
		return
	}

	return
}

func run(args []string) (err error) {
	// If invoked with a single "--help" argument, print a usage message and exit
	// successfully.
	if len(args) == 2 && args[1] == "--help" {
		fmt.Fprintf(
			os.Stderr,
			"Usage: %s [-o options] bucket_name mount_point\n",
			args[0])

		return
	}

	// Find the path to gcsfuse.
	gcsfusePath, err := findGcsfuse()
	if err != nil {
		err = fmt.Errorf("findGcsfuse: %w", err)
		return
	}

	// Find the path to fusermount.
	fusermountPath, err := findFusermount()
	if err != nil {
		err = fmt.Errorf("findFusermount: %w", err)
		return
	}

	// Attempt to parse arguments.
	device, mountPoint, opts, err := parseArgs(args)
	if err != nil {
		err = fmt.Errorf("parseArgs: %w", err)
		return
	}

	// Choose gcsfuse args.
	gcsfuseArgs, err := makeGcsfuseArgs(device, mountPoint, opts)
	if err != nil {
		err = fmt.Errorf("makeGcsfuseArgs: %w", err)
		return
	}

	fmt.Fprintf(
		os.Stderr,
		"Calling gcsfuse with arguments: %s\n",
		strings.Join(gcsfuseArgs, " "))

	// Run gcsfuse.
	cmd := exec.Command(gcsfusePath, gcsfuseArgs...)
	cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s", path.Dir(fusermountPath)))

	// Pass through the https_proxy/http_proxy environment variable,
	// in case the host requires a proxy server to reach the GCS endpoint.
	// http_proxy has precedence over http_proxy, in case both are set
	if p, ok := os.LookupEnv("https_proxy"); ok {
		cmd.Env = append(cmd.Env, fmt.Sprintf("https_proxy=%s", p))
	} else if p, ok := os.LookupEnv("http_proxy"); ok {
		cmd.Env = append(cmd.Env, fmt.Sprintf("http_proxy=%s", p))
	}

	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err = cmd.Run()
	if err != nil {
		err = fmt.Errorf("running gcsfuse: %w", err)
		return
	}

	return
}

func main() {
	err := run(os.Args)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before><commit_msg>Fix code style<commit_after><|endoftext|>


<commit_before>package models

type Entity interface {
    Live(entityChan chan Event)
}
<commit_msg>Improve entity interface<commit_after>package models

import (
    "github.com/astaxie/beego"
)

type Entity interface {
    Id() int
    Live(eventChannel chan Event, collisionChannel chan Entity)
    Kill()
    PosX() int
    PosY() int
}

type baseEntity struct {
    id   int
    x    int
    y    int
    stop chan bool
}

func (b *baseEntity) Id() int {
    return b.id
}

func (b *baseEntity) PosX() int {
    return b.x
}

func (b *baseEntity) PosY() int {
    return b.y
}

func (b *baseEntity) Kill() {

    if b.x > 0 {
        beego.Info("baseEntity.Kill id=", b.id)
    }

    b.stop <- true

    if b.x > 0 {
        beego.Info("baseEntity.Kill id=", b.id, "DONE")
    }
}
<|endoftext|>


<commit_before>// hello runs the hello command
package bobby

import (
	"fmt"
	"os"
	"strings"

	"github.com/mohae/contour"
)

func Hello(words ...string) (string, error) {
	logger.Tracef("Entering Hello with: %v\n", words)

	h := "Hello"
	if len(words) == 0 {
		logger.Tracef("exiting Hello: h  = %v, err=nil\n", h)
		return h, nil
	}

	for _, word := range words {
		h += " " + word
	}

	if os.Getenv("lower") == "true" {
		h = strings.ToLower(h)
	}

	// Print out the current settings.
//	var b bool

	v, err := contour.GetString("configfilename")
	if err != nil {
		logger.Critical("configfilename not found in AppConfig")
	} else {
		fmt.Printf("config: %s\n", v)
	}
/*
	b, err = contour.GetBool("lower")
	if err != nil {
		logger.Critical("lower not found in AppConfig")
	} else {
		fmt.Printf("lower: %v\n", b)
	}

	b, err = contour.GetBool("logging")
	if err != nil {
		logger.Critical("logging not found in AppConfig")
	} else {
		fmt.Printf("logging: %v\n", b)
	}
*/
	v, err = contour.GetString("logconfigfilename")
	if err != nil {
		logger.Critical("logconfigfilename not found in AppConfig")
	} else {
		fmt.Printf("logconfigfilename: %s\n", v)
	}

        fmt.Printf("config: %s\n", os.Getenv("configfilename"))
        fmt.Printf("lower: %v\n", os.Getenv("lower"))
        fmt.Printf("logging: %v\n", os.Getenv("logging"))
        fmt.Printf("logconfig: %s\n", os.Getenv("logconfigfilename"))

	// This will go to their defined locations
	logger.Trace("This is an example TRACE message\n")
	logger.Debug("This is an example DEBUG message\n")
	logger.Info("This is an example INFO message\n")
	logger.Warn("This is an example WARN message\n")
	logger.Error("This is an example ERROR message\n")
	logger.Critical("This is an example CRITICAL message\n")
	logger.Tracef("exiting Hello\n", h)
	return h, nil
}
<commit_msg>quine running commands...need to add filters for flags<commit_after>// hello runs the hello command
package bobby

import (
	"fmt"
	"os"
	"strings"

	"github.com/mohae/contour"
)

func Hello(words ...string) (string, error) {
	logger.Tracef("Entering Hello with: %v\n", words)

	h := "Hello"
	if len(words) == 0 {
		logger.Tracef("exiting Hello: h  = %v, err=nil\n", h)
		return h, nil
	}

	for _, word := range words {
		h += " " + word
	}

	if os.Getenv("lower") == "true" {
		h = strings.ToLower(h)
	}

	fmt.Println(h)

	// Print out the current settings.
//	var b bool

	v, err := contour.GetString("configfilename")
	if err != nil {
		logger.Critical("configfilename not found in AppConfig")
	} else {
		fmt.Printf("config: %s\n", v)
	}
/*
	b, err = contour.GetBool("lower")
	if err != nil {
		logger.Critical("lower not found in AppConfig")
	} else {
		fmt.Printf("lower: %v\n", b)
	}

	b, err = contour.GetBool("logging")
	if err != nil {
		logger.Critical("logging not found in AppConfig")
	} else {
		fmt.Printf("logging: %v\n", b)
	}
*/
	v, err = contour.GetString("logconfigfilename")
	if err != nil {
		logger.Critical("logconfigfilename not found in AppConfig")
	} else {
		fmt.Printf("logconfigfilename: %s\n", v)
	}

        fmt.Printf("config: %s\n", os.Getenv("configfilename"))
        fmt.Printf("lower: %v\n", os.Getenv("lower"))
        fmt.Printf("logging: %v\n", os.Getenv("logging"))
        fmt.Printf("logconfig: %s\n", os.Getenv("logconfigfilename"))

	// This will go to their defined locations
	logger.Trace("This is an example TRACE message\n")
	logger.Debug("This is an example DEBUG message\n")
	logger.Info("This is an example INFO message\n")
	logger.Warn("This is an example WARN message\n")
	logger.Error("This is an example ERROR message\n")
	logger.Critical("This is an example CRITICAL message\n")
	logger.Tracef("exiting Hello\n", h)
	return h, nil
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"strings"
)

type UserRestObject struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
	Age  int    `json:"age"`
}

// Respond to URLs of the form /v1/...
func APIHandler(response http.ResponseWriter, request *http.Request) {
	log.Print("APIhandler")
	//Connect to database
	db, e := sql.Open("mysql", "root:@tcp(localhost:3306)/test")

	defer db.Close()

	if e != nil {
		fmt.Print(e)
	}

	//set mime type to JSON
	response.Header().Set("Content-type", "application/json")

	err := request.ParseForm()
	if err != nil {
		http.Error(response, fmt.Sprintf("error parsing url %v", err), 500)
	}

	// var jsonResult []string

    switch request.Method {
	case "GET":
		userId := request.FormValue("userId")

		if userId == "" {
	        var users []UserRestObject
			log.Println("userId", userId)
			log.Println("GET ALL")
			rows, err := db.Query("select id, name, age from users limit 100")
			if err != nil {
				fmt.Print(err)
			}

			defer rows.Close()
			for rows.Next() {
				var name string
				var age int
				var id int
				err = rows.Scan(&id, &name, &age)
                if err != nil {
                    fmt.Println(err)
                    return
                }
				user := UserRestObject{Id: id, Name: name, Age: age}
			    users = append(users, user)
			}
            jsonResult, err := json.Marshal(users)
            if err != nil {
                fmt.Println(err)
                return
            }
            response.WriteHeader(http.StatusOK)
            fmt.Fprintf(response, "%v", string(jsonResult))
            return
		} else {
			log.Println("userId", userId)
			log.Println("GET search")
			st, err := db.Prepare("select id, name, age from users WHERE id = ? ")
			defer st.Close()
			if err != nil {
				log.Fatal("error preparing statement:", err)
			}

			var name string
			var age int
			var id int

			err = st.QueryRow(userId).Scan(&id, &name, &age)

			if err != nil {
				log.Fatal(err)
			}
			user := &UserRestObject{Id: id, Name: name, Age: age}
			jsonResult, err := json.Marshal(user)
			if err != nil {
				fmt.Println(err)
				return
			}
            fmt.Fprintf(response, "%v", string(jsonResult))
            return
		}

	case "POST":
		log.Println("POST")
		var userRestObject UserRestObject
		userRestObject = jsonToUserObject(response, request)
		log.Println("name:" + userRestObject.Name + " age: " + strconv.Itoa(userRestObject.Age))
		st, err := db.Prepare("INSERT INTO users(name, age) VALUES(?, ?)")
		if err != nil {
			fmt.Print(err)
            return
		}
		result, err := st.Exec(userRestObject.Name, userRestObject.Age)
		if err != nil {
			fmt.Print(err)
            return
		}

        lastInsertedId, err := result.LastInsertId()
        if err != nil {
			fmt.Print(err)
            return
		}

        // result.LastInsertId

        // fmt.Println(result)

        // jsonResult, err := json.Marshal(result)
        // if err != nil {
        //     fmt.Println(err)
        //     return
        // }
        // fmt.Println(jsonResult)

        // result.LastInsertId.(int)

        // fmt.Fprintf(response, "%v", "{\"id\":" + strconv.ParseInt(result.LastInsertId, 10, 64) + "}")
        fmt.Fprintf(response, "%v", "{\"id\":" + strconv.FormatInt(lastInsertedId, 10) + "}")
        return

	case "PUT":
		id := strings.Replace(request.URL.Path, "/v1/", "", -1)
		log.Print("DELETE  id:" + id + "")
		var userRestObject UserRestObject
		userRestObject = jsonToUserObject(response, request)

		name := userRestObject.Name
		age := userRestObject.Age
		log.Println("PUT name:" + name + "-id:" + id + " age:" + strconv.Itoa(age) + "")

		st, err := db.Prepare("UPDATE users SET name=?, age=? WHERE id=?")
		if err != nil {
			fmt.Print(err)
		}
		result, err := st.Exec(name, age, id)
		if err != nil {
			fmt.Print(err)
		}

        jsonResult, err := json.Marshal(result)
        if err != nil {
            fmt.Println(err)
            return
        }

        fmt.Fprintf(response, "%v", string(jsonResult))
        return

	case "DELETE":
		id := strings.Replace(request.URL.Path, "/v1/", "", -1)
		log.Print("DELETE  id:" + id + "")
		st, err := db.Prepare("DELETE FROM users WHERE id=?")
		if err != nil {
			fmt.Print(err)
		}
		result, err := st.Exec(id)
		if err != nil {
			fmt.Print(err)
		}

		jsonResult, err := json.Marshal(result)
        if err != nil {
            fmt.Println(err)
            return
        }

        fmt.Fprintf(response, "%v", string(jsonResult))
        return
	    default:
	}
}

func jsonToUserObject(response http.ResponseWriter, request *http.Request) UserRestObject {
	var userRestObject UserRestObject
	body, err := ioutil.ReadAll(io.LimitReader(request.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := request.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &userRestObject); err != nil {
		response.Header().Set("Content-Type", "application/json; charset=UTF-8")
		response.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(response).Encode(err); err != nil {
			panic(err)
		}
	}
	return userRestObject
}

func main() {
	port := 4000

	var err string
	portstring := strconv.Itoa(port)

	mux := http.NewServeMux()

	mux.Handle("/v1/", http.HandlerFunc(APIHandler))
	//	mux.Handle("/", http.HandlerFunc(Handler))

	log.Print("Listening on port " + portstring + " ... ")
	errs := http.ListenAndServe(":"+portstring, mux)
	if errs != nil {
		log.Fatal("ListenAndServe error: ", err)
	}
}
<commit_msg>add 404 controller function<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"strings"

	_ "github.com/go-sql-driver/mysql"
)

type UserRestObject struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
	Age  int    `json:"age"`
}

// Respond to URLs of the form /v1/...
func APIHandler(response http.ResponseWriter, request *http.Request) {
	log.Print("APIhandler")
	//Connect to database
	db, e := sql.Open("mysql", "root:@tcp(localhost:3306)/test")

	defer db.Close()

	if e != nil {
		fmt.Print(e)
	}

	//set mime type to JSON
	response.Header().Set("Content-type", "application/json")

	err := request.ParseForm()
	if err != nil {
		http.Error(response, fmt.Sprintf("error parsing url %v", err), 500)
	}

	// var jsonResult []string

	switch request.Method {
	case "GET":
		userId := request.FormValue("userId")

		if userId == "" {
			var users []UserRestObject
			log.Println("userId", userId)
			log.Println("GET ALL")
			rows, err := db.Query("select id, name, age from users limit 100")
			if err != nil {
				fmt.Print(err)
			}

			defer rows.Close()
			for rows.Next() {
				var name string
				var age int
				var id int
				err = rows.Scan(&id, &name, &age)
				if err != nil {
					fmt.Println(err)
					return
				}
				user := UserRestObject{Id: id, Name: name, Age: age}
				users = append(users, user)
			}
			jsonResult, err := json.Marshal(users)
			if err != nil {
				fmt.Println(err)
				return
			}
			response.WriteHeader(http.StatusOK)
			fmt.Fprintf(response, "%v", string(jsonResult))
			return
		} else {
			log.Println("userId", userId)
			log.Println("GET search")
			st, err := db.Prepare("select id, name, age from users WHERE id = ? ")
			defer st.Close()
			if err != nil {
				log.Fatal("error preparing statement:", err)
			}

			var name string
			var age int
			var id int

			err = st.QueryRow(userId).Scan(&id, &name, &age)

			if err != nil {
				log.Fatal(err)
			}
			user := &UserRestObject{Id: id, Name: name, Age: age}
			jsonResult, err := json.Marshal(user)
			if err != nil {
				fmt.Println(err)
				return
			}
			fmt.Fprintf(response, "%v", string(jsonResult))
			return
		}

	case "POST":
		log.Println("POST")
		var userRestObject UserRestObject
		userRestObject = jsonToUserObject(response, request)
		log.Println("name:" + userRestObject.Name + " age: " + strconv.Itoa(userRestObject.Age))
		st, err := db.Prepare("INSERT INTO users(name, age) VALUES(?, ?)")
		if err != nil {
			fmt.Print(err)
			return
		}
		result, err := st.Exec(userRestObject.Name, userRestObject.Age)
		if err != nil {
			fmt.Print(err)
			return
		}

		lastInsertedId, err := result.LastInsertId()
		if err != nil {
			fmt.Print(err)
			return
		}

		fmt.Fprintf(response, "%v", "{\"id\":"+strconv.FormatInt(lastInsertedId, 10)+"}")
		return

	case "PUT":
		id := strings.Replace(request.URL.Path, "/v1/", "", -1)
		log.Print("DELETE  id:" + id + "")
		var userRestObject UserRestObject
		userRestObject = jsonToUserObject(response, request)

		name := userRestObject.Name
		age := userRestObject.Age
		log.Println("PUT name:" + name + "-id:" + id + " age:" + strconv.Itoa(age) + "")

		st, err := db.Prepare("UPDATE users SET name=?, age=? WHERE id=?")
		if err != nil {
			fmt.Print(err)
		}
		result, err := st.Exec(name, age, id)
		if err != nil {
			fmt.Print(err)
		}

		jsonResult, err := json.Marshal(result)
		if err != nil {
			fmt.Println(err)
			return
		}

		fmt.Fprintf(response, "%v", string(jsonResult))
		return

	case "DELETE":
		id := strings.Replace(request.URL.Path, "/v1/", "", -1)
		log.Print("DELETE  id:" + id + "")
		st, err := db.Prepare("DELETE FROM users WHERE id=?")
		if err != nil {
			fmt.Print(err)
		}
		result, err := st.Exec(id)
		if err != nil {
			fmt.Print(err)
		}

		jsonResult, err := json.Marshal(result)
		if err != nil {
			fmt.Println(err)
			return
		}

		fmt.Fprintf(response, "%v", string(jsonResult))
		return
	default:
	}
}

func jsonToUserObject(response http.ResponseWriter, request *http.Request) UserRestObject {
	var userRestObject UserRestObject
	body, err := ioutil.ReadAll(io.LimitReader(request.Body, 1048576))
	if err != nil {
		panic(err)
	}
	if err := request.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &userRestObject); err != nil {
		response.Header().Set("Content-Type", "application/json; charset=UTF-8")
		response.WriteHeader(422) // unprocessable entity
		if err := json.NewEncoder(response).Encode(err); err != nil {
			panic(err)
		}
	}
	return userRestObject
}

func lostHandler(response http.ResponseWriter, request *http.Request) {
	response.Header().Set("Content-Type", "application/json; charset=utf-8")
	response.WriteHeader(http.StatusNotFound)
	fmt.Fprintf(response, "%v", "{\"status\":\"404\",\"message\":\"incorrect endpoint\"}")
}

func main() {
	port := 4000

	var err string
	portstring := strconv.Itoa(port)

	mux := http.NewServeMux()

	mux.Handle("/v1/", http.HandlerFunc(APIHandler))
	mux.Handle("/", http.HandlerFunc(lostHandler))

	log.Print("Listening on port " + portstring + " ... ")
	errs := http.ListenAndServe(":"+portstring, mux)
	if errs != nil {
		log.Fatal("ListenAndServe error: ", err)
	}
}
<|endoftext|>