<commit_before>/**
 * Copyright 2015 @ z3q.net.
 * name : json_c.go
 * author : jarryliu
 * date : 2016-04-25 23:09
 * description :
 * history :
 */
package shared

import (
	"encoding/gob"
	"encoding/json"
	"fmt"
	"github.com/jsix/gof"
	"github.com/jsix/gof/crypto"
	"github.com/jsix/gof/storage"
	"go2o/core/domain/interface/ad"
	"go2o/core/domain/interface/valueobject"
	"go2o/core/dto"
	"go2o/core/service/dps"
	"go2o/x/echox"
	"log"
	"net/http"
	"strconv"
	"strings"
	"sync"
)

const (
	//todo: ??? 设置为可配置
	maxSeconds int64 = 10
)

func init() {
	gob.Register(map[string]map[string]interface{}{})
	gob.Register(ad.ValueGallery{})
	gob.Register(ad.Ad{})
	gob.Register([]*valueobject.Goods{})
	gob.Register(valueobject.Goods{})
	gob.Register(ad.HyperLink{})
	gob.Register(ad.Image{})
}

type JsonC struct {
	gof.App
	mux *sync.RWMutex
}

func NewJsonC() *JsonC {
	return &JsonC{
		App: gof.CurrentApp,
		mux: new(sync.RWMutex),
	}
}

func getMd5(s string) string {
	return crypto.Md5([]byte(s))[8:16]
}

// 广告
func (j *JsonC) Ad(ctx *echox.Context) error {
	namesParams := strings.TrimSpace(ctx.Query("keys"))
	names := strings.Split(namesParams, "|")
	userId, _ := strconv.Atoi(ctx.Query("ad_user"))
	as := dps.AdService
	result := make(map[string]*ad.AdDto, len(names))
	key := fmt.Sprintf("go2o:rep:ad:%d:front:%s", userId, getMd5(namesParams))
	sto := ctx.App.Storage()
	if err := sto.Get(key, &result); err != nil {
		//从缓存中读取
		for _, n := range names {
			//分别绑定广告
			dto := as.GetAdAndDataByKey(userId, n)
			if dto == nil {
				result[n] = nil
				continue
			}
			result[n] = dto
		}
		seconds := dps.BaseService.GetRegistry().CacheAdMaxAge
		sto.SetExpire(key, result, seconds)
		//log.Println("---- 更新广告缓存 ",err)
	}
	return ctx.JSON(http.StatusOK, result)
}

func (j *JsonC) getMultiParams(s string) (p string, size, begin int) {
	arr := strings.Split(s, "*")
	l := len(arr)
	if l == 1 {
		p = s
		size = 10 //返回默认10条
	} else {
		p = arr[0]
		size, _ = strconv.Atoi(arr[1])
		if l > 2 {
			begin, _ = strconv.Atoi(arr[2])
		}
	}
	return p, size, begin
}

func (j *JsonC) unmarshal(sto storage.Interface, key string, dst interface{}) error {
	jsStr, err := sto.GetString(key)
	if err == nil {
		err = json.Unmarshal([]byte(jsStr), &dst)
	}
	return err
}

// 商城/商铺分类JSON，shop_id为0，则返回商城的分类
// todo: ??? gob编码提示错误
func (j *JsonC) ShopCat(ctx *echox.Context) error {
	parentId, _ := strconv.Atoi(ctx.Form("parent_id"))
	shopId, _ := strconv.Atoi(ctx.Form("shop_id"))
	list := []dto.Category{}
	key := fmt.Sprintf("go2o:rep:cat:%d:json:%d", shopId, parentId)
	sto := ctx.App.Storage()
	if err := j.unmarshal(sto, key, &list); err != nil {
		//if err := sto.Get(key,*list);err != nil{
		if parentId == 0 {
			list = dps.SaleService.GetBigCategories(shopId)
		} else {
			list = dps.SaleService.GetChildCategories(shopId, parentId)
		}
		var d []byte
		d, err = json.Marshal(list)
		sto.Set(key, string(d))
		//sto.Set(key,list)
		log.Println("---- 更新分类缓存 ", err)
	}
	return ctx.JSON(http.StatusOK, list)
}

func (j *JsonC) Get_shop(ctx *echox.Context) error {
	typeParams := strings.TrimSpace(ctx.Form("params"))
	types := strings.Split(typeParams, "|")
	result := make(map[string]interface{}, len(types))
	key := fmt.Sprint("go2o:rep:shop:front:glob_%s", typeParams)
	sto := ctx.App.Storage()
	if err := sto.Get(key, &result); err != nil {
		//从缓存中读取
		ss := dps.ShopService
		for _, t := range types {
			p, size, begin := j.getMultiParams(t)
			switch p {
			case "new-shop":
				_, result[p] = ss.PagedOnBusinessOnlineShops(
					begin, begin+size, "", "sp.create_time DESC")
			case "hot-shop":
				_, result[p] = ss.PagedOnBusinessOnlineShops(
					begin, begin+size, "", "")
			}
		}
		//sto.SetExpire(key, result, maxSeconds)
	}
	return ctx.Debug(ctx.JSON(http.StatusOK, result))
}

// 商品
func (j *JsonC) Get_goods(ctx *echox.Context) error {
	shopId, _ := strconv.Atoi(ctx.Form("shop_id"))
	typeParams := strings.TrimSpace(ctx.Form("params"))
	types := strings.Split(typeParams, "|")
	result := make(map[string]interface{}, len(types))
	key := fmt.Sprint("go2o:rep:gs:fc3:%d_%s", shopId, typeParams)
	sto := ctx.App.Storage()
	if err := sto.Get(key, &result); err != nil {
		//从缓存中读取
		ss := dps.SaleService
		for _, t := range types {
			p, size, begin := j.getMultiParams(t)
			switch p {
			case "new-goods":
				_, result[p] = ss.GetPagedOnShelvesGoods(shopId,
					-1, begin, begin+size, "gs_goods.id DESC")
			case "hot-sales":
				_, result[p] = ss.GetPagedOnShelvesGoods(shopId,
					-1, begin, begin+size, "gs_goods.sale_num DESC")
			}
		}
		//sto.SetExpire(key, result, maxSeconds)
	}
	return ctx.Debug(ctx.JSON(http.StatusOK, result))
}

func (j *JsonC) Mch_goods(ctx *echox.Context) error {
	typeParams := strings.TrimSpace(ctx.Form("params"))
	types := strings.Split(typeParams, "|")
	mchId, _ := strconv.Atoi(ctx.Form("mch_id"))
	result := make(map[string]interface{}, len(types))

	key := fmt.Sprint("go2o:rep:sg:front:%d_%s", mchId, typeParams)
	sto := ctx.App.Storage()
	if err := sto.Get(key, &result); err != nil {
		//从缓存中读取
		ss := dps.SaleService
		for _, t := range types {
			p, size, begin := j.getMultiParams(t)
			switch p {
			case "new-goods":
				_, result[p] = ss.GetShopPagedOnShelvesGoods(mchId,
					-1, begin, begin+size, "gs_goods.id DESC")
			case "hot-sales":
				_, result[p] = ss.GetShopPagedOnShelvesGoods(mchId,
					-1, begin, begin+size, "gs_goods.sale_num DESC")
			}
		}
		sto.SetExpire(key, result, maxSeconds)
	}
	return ctx.Debug(ctx.JSON(http.StatusOK, result))
}

// 获取销售标签获取商品
func (j *JsonC) SaleLabelGoods(ctx *echox.Context) error {
	codeParams := strings.TrimSpace(ctx.Form("params"))
	codes := strings.Split(codeParams, "|")
	mchId, _ := strconv.Atoi(ctx.Form("mch_id"))
	result := make(map[string]interface{}, len(codes))

	key := fmt.Sprint("go2o:rep:stg:front:%d--%s", mchId, getMd5(codeParams))
	sto := ctx.App.Storage()
	if err := sto.Get(key, &result); err != nil {
		//从缓存中读取
		log.Println(err)
		for _, param := range codes {
			code, size, begin := j.getMultiParams(param)
			list := dps.SaleService.GetValueGoodsBySaleLabel(
				mchId, code, "", begin, begin+size)
			result[code] = list
		}
		sto.SetExpire(key, result, maxSeconds)
	}
	return ctx.Debug(ctx.JSON(http.StatusOK, result))
}
<commit_msg>Test Commit<commit_after>/**
 * Copyright 2015 @ z3q.net.
 * name : json_c.go
 * author : jarryliu
 * date : 2016-04-25 23:09
 * description :
 * history :
 */
package shared

import (
	"encoding/gob"
	"encoding/json"
	"fmt"
	"github.com/jsix/gof"
	"github.com/jsix/gof/crypto"
	"github.com/jsix/gof/storage"
	"go2o/core/domain/interface/ad"
	"go2o/core/domain/interface/valueobject"
	"go2o/core/dto"
	"go2o/core/service/dps"
	"go2o/x/echox"
	"log"
	"net/http"
	"strconv"
	"strings"
	"sync"
)

const (
	//todo: ??? 设置为可配置
	maxSeconds int64 = 10
)

func init() {
	gob.Register(map[string]map[string]interface{}{})
	gob.Register(ad.ValueGallery{})
	gob.Register(ad.Ad{})
	gob.Register([]*valueobject.Goods{})
	gob.Register(valueobject.Goods{})
	gob.Register(ad.HyperLink{})
	gob.Register(ad.Image{})
}

type JsonC struct {
	gof.App
	mux *sync.RWMutex
}

func NewJsonC() *JsonC {
	return &JsonC{
		App: gof.CurrentApp,
		mux: new(sync.RWMutex),
	}
}

func getMd5(s string) string {
	return crypto.Md5([]byte(s))[8:16]
}

// 广告
func (j *JsonC) Ad(ctx *echox.Context) error {
	namesParams := strings.TrimSpace(ctx.Query("keys"))
	names := strings.Split(namesParams, "|")
	userId, _ := strconv.Atoi(ctx.Query("ad_user"))
	as := dps.AdService
	result := make(map[string]*ad.AdDto, len(names))
	key := fmt.Sprintf("go2o:rep:ad:%d:front:%s", userId, getMd5(namesParams))
	sto := ctx.App.Storage()
	if err := sto.Get(key, &result); err != nil {
		//从缓存中读取
		for _, n := range names {
			//分别绑定广告
			dto := as.GetAdAndDataByKey(userId, n)
			if dto == nil {
				result[n] = nil
				continue
			}
			result[n] = dto
		}
		seconds := dps.BaseService.GetRegistry().CacheAdMaxAge
		sto.SetExpire(key, result, seconds)
		//log.Println("---- 更新广告缓存 ",err)
	}
	return ctx.JSON(http.StatusOK, result)
}

func (j *JsonC) getMultiParams(s string) (p string, size, begin int) {
	arr := strings.Split(s, "*")
	l := len(arr)
	if l == 1 {
		p = s
		size = 10 //返回默认10条
	} else {
		p = arr[0]
		size, _ = strconv.Atoi(arr[1])
		if l > 2 {
			begin, _ = strconv.Atoi(arr[2])
		}
	}
	return p, size, begin
}

func (j *JsonC) unmarshal(sto storage.Interface, key string, dst interface{}) error {
	jsStr, err := sto.GetString(key)
	if err == nil {
		err = json.Unmarshal([]byte(jsStr), &dst)
	}
	return err
}

// 商城/商铺分类JSON，shop_id为0，则返回商城的分类
// todo: ??? gob编码提示错误
func (j *JsonC) ShopCat(ctx *echox.Context) error {
	parentId, _ := strconv.Atoi(ctx.Form("parent_id"))
	shopId, _ := strconv.Atoi(ctx.Form("shop_id"))
	list := []dto.Category{}
	key := fmt.Sprintf("go2o:rep:cat:%d:json:%d", shopId, parentId)
	sto := ctx.App.Storage()
	if err := j.unmarshal(sto, key, &list); err != nil {
		//if err := sto.Get(key,*list);err != nil{
		if parentId == 0 {
			list = dps.SaleService.GetBigCategories(shopId)
		} else {
			list = dps.SaleService.GetChildCategories(shopId, parentId)
		}
		var d []byte
		d, err = json.Marshal(list)
		sto.Set(key, string(d))
		//sto.Set(key,list)
		log.Println("---- 更新分类缓存 ", err)
	}
	return ctx.JSON(http.StatusOK, list)
}

func (j *JsonC) Get_shop(ctx *echox.Context) error {
	typeParams := strings.TrimSpace(ctx.Form("params"))
	types := strings.Split(typeParams, "|")
	result := make(map[string]interface{}, len(types))
	key := fmt.Sprint("go2o:rep:shop:front:glob_%s", typeParams)
	sto := ctx.App.Storage()
	//从缓存中读取
	if err := sto.Get(key, &result); err != nil {
		ss := dps.ShopService
		for _, t := range types {
			p, size, begin := j.getMultiParams(t)
			switch p {
			case "new-shop":
				_, result[p] = ss.PagedOnBusinessOnlineShops(
					begin, begin+size, "", "sp.create_time DESC")
			case "hot-shop":
				_, result[p] = ss.PagedOnBusinessOnlineShops(
					begin, begin+size, "", "")
			}
		}
		//sto.SetExpire(key, result, maxSeconds)
	}
	return ctx.Debug(ctx.JSON(http.StatusOK, result))
}

// 商品
func (j *JsonC) Get_goods(ctx *echox.Context) error {
	shopId, _ := strconv.Atoi(ctx.Form("shop_id"))
	typeParams := strings.TrimSpace(ctx.Form("params"))
	types := strings.Split(typeParams, "|")
	result := make(map[string]interface{}, len(types))
	key := fmt.Sprint("go2o:rep:gs:fc3:%d_%s", shopId, typeParams)
	sto := ctx.App.Storage()
	if err := sto.Get(key, &result); err != nil {
		//从缓存中读取
		ss := dps.SaleService
		for _, t := range types {
			p, size, begin := j.getMultiParams(t)
			switch p {
			case "new-goods":
				_, result[p] = ss.GetPagedOnShelvesGoods(shopId,
					-1, begin, begin+size, "gs_goods.id DESC")
			case "hot-sales":
				_, result[p] = ss.GetPagedOnShelvesGoods(shopId,
					-1, begin, begin+size, "gs_goods.sale_num DESC")
			}
		}
		//sto.SetExpire(key, result, maxSeconds)
	}
	return ctx.Debug(ctx.JSON(http.StatusOK, result))
}

func (j *JsonC) Mch_goods(ctx *echox.Context) error {
	typeParams := strings.TrimSpace(ctx.Form("params"))
	types := strings.Split(typeParams, "|")
	mchId, _ := strconv.Atoi(ctx.Form("mch_id"))
	result := make(map[string]interface{}, len(types))

	key := fmt.Sprint("go2o:rep:sg:front:%d_%s", mchId, typeParams)
	sto := ctx.App.Storage()
	if err := sto.Get(key, &result); err != nil {
		//从缓存中读取
		ss := dps.SaleService
		for _, t := range types {
			p, size, begin := j.getMultiParams(t)
			switch p {
			case "new-goods":
				_, result[p] = ss.GetShopPagedOnShelvesGoods(mchId,
					-1, begin, begin+size, "gs_goods.id DESC")
			case "hot-sales":
				_, result[p] = ss.GetShopPagedOnShelvesGoods(mchId,
					-1, begin, begin+size, "gs_goods.sale_num DESC")
			}
		}
		sto.SetExpire(key, result, maxSeconds)
	}
	return ctx.Debug(ctx.JSON(http.StatusOK, result))
}

// 获取销售标签获取商品
func (j *JsonC) SaleLabelGoods(ctx *echox.Context) error {
	codeParams := strings.TrimSpace(ctx.Form("params"))
	codes := strings.Split(codeParams, "|")
	mchId, _ := strconv.Atoi(ctx.Form("mch_id"))
	result := make(map[string]interface{}, len(codes))

	key := fmt.Sprint("go2o:rep:stg:front:%d--%s", mchId, getMd5(codeParams))
	sto := ctx.App.Storage()
	if err := sto.Get(key, &result); err != nil {
		//从缓存中读取
		log.Println(err)
		for _, param := range codes {
			code, size, begin := j.getMultiParams(param)
			list := dps.SaleService.GetValueGoodsBySaleLabel(
				mchId, code, "", begin, begin+size)
			result[code] = list
		}
		sto.SetExpire(key, result, maxSeconds)
	}
	return ctx.Debug(ctx.JSON(http.StatusOK, result))
}
<|endoftext|>


<commit_before>package appContext

import (
	"encoding/gob"
	"log"
	"net/http"
	"time"

	"github.com/antihax/evedata/config"
	"github.com/antihax/evedata/models"
	"github.com/antihax/goesi"
	"github.com/gregjones/httpcache"
	httpredis "github.com/gregjones/httpcache/redis"

	"golang.org/x/oauth2"
	gsr "gopkg.in/boj/redistore.v1"

	"github.com/garyburd/redigo/redis"
	"github.com/jmoiron/sqlx"
)

// AppContext provides access to handles throughout the app.
type AppContext struct {
	Conf           *config.Config // App Configuration
	Db             *sqlx.DB       // EVE Database
	Store          *gsr.RediStore // Redis session store.
	HTTPClient     *http.Client   // Redis Cached HTTP client
	Cache          *redis.Pool    // Redis connection Pool for HTTP Cache and session store.
	ESI            *goesi.APIClient
	ESIPublicToken oauth2.TokenSource

	// Since we need to combine data from multiple characters, we use
	// one authenticator for the site to act as the main authentication.
	// second will allow for many alt characters under the main.
	SSOAuthenticator          *goesi.SSOAuthenticator // CREST authenticator for site authentication
	TokenAuthenticator        *goesi.SSOAuthenticator // CREST authenticator for site functionality
	ESIBootstrapAuthenticator *goesi.SSOAuthenticator // CREST authenticator for site functionality
}

func NewTestAppContext() AppContext {
	ctx := AppContext{}

	conf := config.Config{}
	ctx.Conf = &conf
	conf.EVEConsumer.Consumers = 10
	conf.EVEConsumer.ZKillEnabled = false

	database, err := models.SetupDatabase("mysql", "root@tcp(127.0.0.1:3306)/eve?allowOldPasswords=1&parseTime=true")
	if err != nil {
		log.Fatalln(err)
	}
	ctx.Db = database

	// Build the redis pool
	ctx.Cache = &redis.Pool{
		MaxIdle:     10,
		IdleTimeout: 60 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", "127.0.0.1:6379")
			if err != nil {
				return nil, err
			}
			return c, err
		},
	}

	// Nuke anything in redis incase we have a flood of trash
	r := ctx.Cache.Get()
	r.Do("FLUSHALL")
	r.Close()

	// Create a Redis http client for the CCP APIs.
	transportCache := httpcache.NewTransport(httpredis.NewWithClient(ctx.Cache))

	// Attach a basic transport with our chained custom transport.
	transportCache.Transport = &http.Transport{Proxy: http.ProxyFromEnvironment, MaxIdleConnsPerHost: 5}

	ctx.HTTPClient = &http.Client{Transport: transportCache}
	if ctx.HTTPClient == nil {
		log.Fatalln("client is null")
	}

	// Setup the EVE ESI Client
	ctx.ESI = goesi.NewAPIClient(ctx.HTTPClient, "EVEData.Org Test Client (If you can see me.. something broke)")
	ctx.ESI.ChangeBasePath("http://127.0.0.1:8080/latest")

	// Create a memcached session store.
	ctx.Store, err = gsr.NewRediStoreWithPool(ctx.Cache, []byte("SOME FAKE RANDOM KEY"))
	if err != nil {
		log.Fatalf("Cannot build database pool: %v", err)
	}

	// Register structs for storage
	gob.Register(oauth2.Token{})
	gob.Register(goesi.CRESTToken{})
	gob.Register(goesi.VerifyResponse{})

	// Setup the Token authenticator, this handles sub characters.
	tokenScopes := []string{
		goesi.ScopeCharacterContractsRead,
		goesi.ScopeCharacterMarketOrdersRead,
		goesi.ScopeCharacterResearchRead,
		goesi.ScopeCharacterWalletRead,
		"esi-assets.read_assets.v1",
		"esi-characters.read_contacts.v1",
		"esi-characters.write_contacts.v1",
		"esi-corporations.read_corporation_membership.v1",
		"esi-location.read_location.v1",
		"esi-location.read_ship_type.v1",
		"esi-planets.manage_planets.v1",
		"esi-search.search_structures.v1",
		"esi-skills.read_skills.v1",
		"esi-ui.open_window.v1",
		"esi-ui.write_waypoint.v1",
		"esi-universe.read_structures.v1",
		"esi-wallet.read_character_wallet.v1",
	}

	// take care to never actually make real requests on this.
	ctx.TokenAuthenticator = goesi.NewSSOAuthenticator(
		ctx.HTTPClient,
		"123545",
		"PLEASE IGNORE",
		"I DO NOTHING",
		tokenScopes)

	return ctx
}
<commit_msg>update context<commit_after>package appContext

import (
	"encoding/gob"
	"log"
	"net/http"
	"time"

	"github.com/antihax/evedata/config"
	"github.com/antihax/evedata/models"
	"github.com/antihax/goesi"
	"github.com/antihax/httpcache"
	httpredis "github.com/antihax/httpcache/redis"

	"golang.org/x/oauth2"
	gsr "gopkg.in/boj/redistore.v1"

	"github.com/garyburd/redigo/redis"
	"github.com/jmoiron/sqlx"
)

// AppContext provides access to handles throughout the app.
type AppContext struct {
	Conf           *config.Config // App Configuration
	Db             *sqlx.DB       // EVE Database
	Store          *gsr.RediStore // Redis session store.
	HTTPClient     *http.Client   // Redis Cached HTTP client
	Cache          *redis.Pool    // Redis connection Pool for HTTP Cache and session store.
	ESI            *goesi.APIClient
	ESIPublicToken oauth2.TokenSource

	// Since we need to combine data from multiple characters, we use
	// one authenticator for the site to act as the main authentication.
	// second will allow for many alt characters under the main.
	SSOAuthenticator          *goesi.SSOAuthenticator // CREST authenticator for site authentication
	TokenAuthenticator        *goesi.SSOAuthenticator // CREST authenticator for site functionality
	ESIBootstrapAuthenticator *goesi.SSOAuthenticator // CREST authenticator for site functionality
}

func NewTestAppContext() AppContext {
	ctx := AppContext{}

	conf := config.Config{}
	ctx.Conf = &conf
	conf.EVEConsumer.Consumers = 10
	conf.EVEConsumer.ZKillEnabled = false

	database, err := models.SetupDatabase("mysql", "root@tcp(127.0.0.1:3306)/eve?allowOldPasswords=1&parseTime=true")
	if err != nil {
		log.Fatalln(err)
	}
	ctx.Db = database

	// Build the redis pool
	ctx.Cache = &redis.Pool{
		MaxIdle:     10,
		IdleTimeout: 60 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", "127.0.0.1:6379")
			if err != nil {
				return nil, err
			}
			return c, err
		},
	}

	// Nuke anything in redis incase we have a flood of trash
	r := ctx.Cache.Get()
	r.Do("FLUSHALL")
	r.Close()

	// Create a Redis http client for the CCP APIs.
	transportCache := httpcache.NewTransport(httpredis.NewWithClient(ctx.Cache))

	// Attach a basic transport with our chained custom transport.
	transportCache.Transport = &http.Transport{Proxy: http.ProxyFromEnvironment, MaxIdleConnsPerHost: 5}

	ctx.HTTPClient = &http.Client{Transport: transportCache}
	if ctx.HTTPClient == nil {
		log.Fatalln("client is null")
	}

	// Setup the EVE ESI Client
	ctx.ESI = goesi.NewAPIClient(ctx.HTTPClient, "EVEData.Org Test Client (If you can see me.. something broke)")
	ctx.ESI.ChangeBasePath("http://127.0.0.1:8080/latest")

	// Create a memcached session store.
	ctx.Store, err = gsr.NewRediStoreWithPool(ctx.Cache, []byte("SOME FAKE RANDOM KEY"))
	if err != nil {
		log.Fatalf("Cannot build database pool: %v", err)
	}

	// Register structs for storage
	gob.Register(oauth2.Token{})
	gob.Register(goesi.CRESTToken{})
	gob.Register(goesi.VerifyResponse{})

	// Setup the Token authenticator, this handles sub characters.
	tokenScopes := []string{
		goesi.ScopeCharacterContractsRead,
		goesi.ScopeCharacterMarketOrdersRead,
		goesi.ScopeCharacterResearchRead,
		goesi.ScopeCharacterWalletRead,
		"esi-assets.read_assets.v1",
		"esi-characters.read_contacts.v1",
		"esi-characters.write_contacts.v1",
		"esi-corporations.read_corporation_membership.v1",
		"esi-location.read_location.v1",
		"esi-location.read_ship_type.v1",
		"esi-planets.manage_planets.v1",
		"esi-search.search_structures.v1",
		"esi-skills.read_skills.v1",
		"esi-ui.open_window.v1",
		"esi-ui.write_waypoint.v1",
		"esi-universe.read_structures.v1",
		"esi-wallet.read_character_wallet.v1",
	}

	// take care to never actually make real requests on this.
	ctx.TokenAuthenticator = goesi.NewSSOAuthenticator(
		ctx.HTTPClient,
		"123545",
		"PLEASE IGNORE",
		"I DO NOTHING",
		tokenScopes)

	return ctx
}
<|endoftext|>


<commit_before>package sqlinternals

import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"fmt"
	"reflect"
)

var (
	// field indices for faster reflect access
	rowErrIdx       int
	rowRowsIdx      int
	rowsRowsiIdx    int
	errArgNil       = errors.New("argument must not be nil")
	errArgWrongType = errors.New("argument was not *sql.Row or *sql.Rows")
	errRowRows      = errors.New("'rows *sql.Rows' in sql.Row could not be read")
	errRowErr       = errors.New("'err error' in sql.Row could not be read")
	errRowErrNil    = errors.New("'err error' in sql.Row is nil")
	errRowsRowsi    = errors.New("'rowsi driver.Rows' in sql.Rows could not be read")
	errRowsRowsiNil = errors.New("'rowsi driver.Rows' in sql.Rows is nil")
)

// a driver.Rows implementatiton so we are able
// to get a type assignable to driver.Rows with reflect
type dummyRows struct{}

func (d dummyRows) Columns() []string {
	return nil
}

func (d dummyRows) Close() error {
	return nil
}

func (d dummyRows) Next(dest []driver.Value) error {
	return nil
}

func panicIfUnassignable(field reflect.StructField, assignable reflect.Type, panicMsg string) {
	fType := field.Type
	if assignable == fType || assignable.AssignableTo(fType) {
		return
	}
	msg := fmt.Sprintf("%s; %v is not assignable to %v",
		panicMsg, assignable.String(), fType.String())
	panic(msg)
}

func init() {
	// all types we need to check as templates
	var (
		tRow        reflect.Type = reflect.TypeOf(sql.Row{})
		tRows       reflect.Type = reflect.TypeOf(sql.Rows{})
		tRowsPtr    reflect.Type = reflect.TypeOf(&sql.Rows{})
		tErr        reflect.Type = reflect.TypeOf(errors.New(""))
		tDriverRows reflect.Type = reflect.TypeOf((driver.Rows)(dummyRows{}))
	)
	var i, expectFields, fields int
	// sql.Row must have fields "rows sql/*Rows" and "err error"
	for i, expectFields, fields = 0, 2, tRow.NumField(); i < fields; i++ {
		field := tRow.Field(i)
		switch field.Name {
		case "err":
			panicIfUnassignable(field, tErr,
				"database/sql/Row.err is not error")
			rowErrIdx = i
			expectFields--
		case "rows":
			panicIfUnassignable(field, tRowsPtr,
				"database/sql/Row.rows is not database/sql/*Rows")
			rowRowsIdx = i
			expectFields--
		}
	}
	if expectFields != 0 {
		panic("unexpected structure of database/sql/Row")
	}
	// sql.Rows must have a field "rowsi driver/Rows"
	for i, expectFields, fields = 0, 1, tRows.NumField(); i < fields; i++ {
		if field := tRows.Field(i); field.Name == "rowsi" {
			panicIfUnassignable(field, tDriverRows,
				"database/sql/Rows.rowsi is not database/sql/driver/Rows")
			rowsRowsiIdx = i
			expectFields--
		}
	}
	if expectFields != 0 {
		panic("unexpected structure of database/sql/Rows")
	}
}

// return rows and err from from sql/*Row;
// according to documentation, exactly one of the two is non-nil.
// If rows is non nil, it is returned and err is ignored.
// If both are nil, an internal error is returned.
func sqlRowsFromSqlRow(row *sql.Row) (*sql.Rows, error) {
	if row == nil {
		return nil, errArgNil
	}
	derefRow := reflect.ValueOf(row).Elem()
	innerRows := derefRow.Field(rowRowsIdx)
	if innerRows.CanInterface() && !innerRows.IsNil() {
		if rows, ok := innerRows.Interface().(*sql.Rows); ok {
			return rows, nil
		}
		return nil, errRowRows
	}
	rowErr := derefRow.Field(rowErrIdx)
	if !rowErr.CanInterface() {
		return nil, errRowErr
	}
	if err, ok := rowErr.Interface().(error); ok && err != nil {
		// return error from sql.Row.err
		return nil, err
	}
	return nil, errRowErrNil
}

// return rowsi from sql/*Rows;
// return an error if the argument or rowsi is nil or can't be read.
func driverRowsFromSqlRows(rows *sql.Rows) (driver.Rows, error) {
	if rows == nil {
		return nil, errArgNil
	}
	driverRows := reflect.ValueOf(*rows).Field(rowsRowsiIdx)
	if !driverRows.CanInterface() {
		return nil, errRowsRowsi
	}
	if result, ok := driverRows.Interface().(driver.Rows); ok && result != nil {
		return result, nil
	}
	return nil, errRowsRowsiNil
}

// Inspect uses reflect to extract a driver.Driver from sql.Row or sql.Rows.
// This can be used by a driver to work around issue 5606 in legacy versions.
func Inspect(sqlStruct interface{}) (interface{}, error) {
	if sqlStruct == nil {
		return nil, errArgNil
	}
	var rows *sql.Rows
	switch v := sqlStruct.(type) {
	case *sql.Row:
		var err error
		rows, err = sqlRowsFromSqlRow(v)
		if err != nil {
			return nil, err
		}
	case *sql.Rows:
		rows = v
	default:
		return errArgWrongType, nil
	}
	return driverRowsFromSqlRows(rows)
}
<commit_msg>Removed dependency on err and fmt. Still failing.<commit_after>package sqlinternals

import (
	"database/sql"
	"database/sql/driver"
	"reflect"
)

var (
	// field indices for faster reflect access. Types are also checked
	rowErrIdx    int // database/sql/Row.err: error
	rowRowsIdx   int // database/sql/Row.rows: database/sql/*Rows
	rowsRowsiIdx int // database/sql/Rows.rowsi: database/sql/driver/Rows
)

// internal error type
// Used instead of import "errors" for two reasons:
// - is used nowhere else, making it a good template for an AssignableTo assertion
// - can be used in const
type internalErr string

func (e internalErr) Error() string {
	return string(e)
}

const (
	errArgNil       = internalErr("argument must not be nil")
	errArgWrongType = internalErr("argument was not *sql.Row or *sql.Rows")
	errRowRows      = internalErr("'rows *sql.Rows' in sql.Row could not be read")
	errRowErr       = internalErr("'err error' in sql.Row could not be read")
	errRowErrNil    = internalErr("'err error' in sql.Row is nil")
	errRowsRowsi    = internalErr("'rowsi driver.Rows' in sql.Rows could not be read")
	errRowsRowsiNil = internalErr("'rowsi driver.Rows' in sql.Rows is nil")
)

// a driver.Rows implementatiton so we are able
// to get a type assignable to driver.Rows with reflect
type dummyRows struct{}

func (d dummyRows) Columns() []string {
	return nil
}

func (d dummyRows) Close() error {
	return nil
}

func (d dummyRows) Next(dest []driver.Value) error {
	return nil
}

// basic type assertion, panic on error
func panicIfUnassignable(field reflect.StructField, assignable reflect.Type, panicMsg string) {
	fType := field.Type
	if assignable == fType || assignable.AssignableTo(fType) {
		return
	}
	panic(panicMsg + "; " + assignable.String() + " is not assignable to " + fType.String())
}

func init() {
	// all types we need to check as templates
	var (
		tRow        reflect.Type = reflect.TypeOf(sql.Row{})
		tRows       reflect.Type = reflect.TypeOf(sql.Rows{})
		tRowsPtr    reflect.Type = reflect.TypeOf(&sql.Rows{})
		tErr        reflect.Type = reflect.TypeOf(errArgNil)
		tDriverRows reflect.Type = reflect.TypeOf((driver.Rows)(dummyRows{}))
	)
	var i, expectFields, fields int
	// sql.Row must have fields "rows sql/*Rows" and "err error"
	for i, expectFields, fields = 0, 2, tRow.NumField(); i < fields; i++ {
		field := tRow.Field(i)
		switch field.Name {
		case "err":
			panicIfUnassignable(field, tErr,
				"database/sql/Row.err is not error")
			rowErrIdx = i
			expectFields--
		case "rows":
			panicIfUnassignable(field, tRowsPtr,
				"database/sql/Row.rows is not database/sql/*Rows")
			rowRowsIdx = i
			expectFields--
		}
	}
	if expectFields != 0 {
		panic("unexpected structure of database/sql/Row")
	}
	// sql.Rows must have a field "rowsi driver/Rows"
	for i, expectFields, fields = 0, 1, tRows.NumField(); i < fields; i++ {
		if field := tRows.Field(i); field.Name == "rowsi" {
			panicIfUnassignable(field, tDriverRows,
				"database/sql/Rows.rowsi is not database/sql/driver/Rows")
			rowsRowsiIdx = i
			expectFields--
		}
	}
	if expectFields != 0 {
		panic("unexpected structure of database/sql/Rows")
	}
}

// return rows and err from from sql/*Row;
// according to documentation, exactly one of the two is non-nil.
// If rows is non nil, it is returned and err is ignored.
// If both are nil, an internal error is returned.
func sqlRowsFromSqlRow(row *sql.Row) (*sql.Rows, error) {
	if row == nil {
		return nil, errArgNil
	}
	derefRow := reflect.ValueOf(row).Elem()
	innerRows := derefRow.Field(rowRowsIdx)
	if innerRows.CanInterface() && !innerRows.IsNil() {
		if rows, ok := innerRows.Interface().(*sql.Rows); ok {
			return rows, nil
		}
		return nil, errRowRows
	}
	rowErr := derefRow.Field(rowErrIdx)
	if !rowErr.CanInterface() {
		return nil, errRowErr
	}
	if err, ok := rowErr.Interface().(error); ok && err != nil {
		// return error from sql.Row.err
		return nil, err
	}
	return nil, errRowErrNil
}

// return rowsi from sql/*Rows;
// return an error if the argument or rowsi is nil or can't be read.
func driverRowsFromSqlRows(rows *sql.Rows) (driver.Rows, error) {
	if rows == nil {
		return nil, errArgNil
	}
	driverRows := reflect.ValueOf(*rows).Field(rowsRowsiIdx)
	if !driverRows.CanInterface() {
		return nil, errRowsRowsi
	}
	if result, ok := driverRows.Interface().(driver.Rows); ok && result != nil {
		return result, nil
	}
	return nil, errRowsRowsiNil
}

// Inspect uses reflect to extract a driver.Driver from sql.Row or sql.Rows.
// This can be used by a driver to work around issue 5606 in legacy versions.
func Inspect(sqlStruct interface{}) (interface{}, error) {
	if sqlStruct == nil {
		return nil, errArgNil
	}
	var rows *sql.Rows
	switch v := sqlStruct.(type) {
	case *sql.Row:
		var err error
		rows, err = sqlRowsFromSqlRow(v)
		if err != nil {
			return nil, err
		}
	case *sql.Rows:
		rows = v
	default:
		return errArgWrongType, nil
	}
	return driverRowsFromSqlRows(rows)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"time"

	"github.com/gin-gonic/gin"
)

func rootHandler(context *gin.Context) {
	currentTime := time.Now()
	currentTime.Format("20060102150405")
	context.JSON(200, gin.H{
		"current_time": currentTime,
		"text":         "Hello World",
	})
}

// GetMainEngine is default router engine using gin framework.
func GetMainEngine() *gin.Engine {
	r := gin.New()

	r.GET("/", rootHandler)

	return r
}

// RunHTTPServer List 8000 default port.
func RunHTTPServer() error {
	port := flag.String("port", "8000", "The port for the mock server to listen to")

	// Parse all flag
	flag.Parse()

	err := GetMainEngine().Run(":" + *port)

	return err
}

func main() {
	RunHTTPServer()
}
<commit_msg>update handle<commit_after>package main

import (
	"flag"
	"time"

	"github.com/gin-gonic/gin"
)

func rootHandler(c *gin.Context) {
	currentTime := time.Now()
	currentTime.Format("20060102150405")
	c.JSON(200, gin.H{
		"current_time": currentTime,
		"text":         "Hello World",
	})
}

// GetMainEngine is default router engine using gin framework.
func GetMainEngine() *gin.Engine {
	r := gin.New()

	r.GET("/", rootHandler)

	return r
}

// RunHTTPServer List 8000 default port.
func RunHTTPServer() error {
	port := flag.String("port", "8000", "The port for the mock server to listen to")

	// Parse all flag
	flag.Parse()

	err := GetMainEngine().Run(":" + *port)

	return err
}

func main() {
	RunHTTPServer()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
        "os"
	"github.com/GoogleCloudPlatform/golang-docker/hello/vendor/internal"
	"github.com/gorilla/mux"
)

func handle(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, fmt.Sprintf("/%s", internal.Secret), http.StatusFound)
}

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %s! 세상아 안녕!", mux.Vars(r)["who"])
}

func main() {
	r := mux.NewRouter().StrictSlash(true)
	r.HandleFunc("/", handle).Methods("GET")
	r.HandleFunc("/{who}", hello).Methods("GET")

	http.Handle("/", r)
	envPort := os.Getenv("PORT")
	if len(envPort) == 0 { envPort = "8080" }
	listenOn := fmt.Sprintf(":%s", envPort)
	fmt.Println("listening on", listenOn)
	log.Fatal(http.ListenAndServe(listenOn, nil))
}
<commit_msg>gofmt<commit_after>package main

import (
	"fmt"
	"github.com/GoogleCloudPlatform/golang-docker/hello/vendor/internal"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"os"
)

func handle(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, fmt.Sprintf("/%s", internal.Secret), http.StatusFound)
}

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %s! 세상아 안녕!", mux.Vars(r)["who"])
}

func main() {
	r := mux.NewRouter().StrictSlash(true)
	r.HandleFunc("/", handle).Methods("GET")
	r.HandleFunc("/{who}", hello).Methods("GET")

	http.Handle("/", r)
	envPort := os.Getenv("PORT")
	if len(envPort) == 0 {
		envPort = "8080"
	}
	listenOn := fmt.Sprintf(":%s", envPort)
	fmt.Println("listening on", listenOn)
	log.Fatal(http.ListenAndServe(listenOn, nil))
}
<|endoftext|>


<commit_before>package hive

import (
	"log"
	"strings"
	"sync"
	"time"
)

// manager model
type HiveManager struct {
	FreeWorkers  chan *HiveWorker
	Tasks        chan string
	Done         chan bool
	TimeProcess  chan int64
	LastProcess  int64
	TotalTimeOut int64
}

// worker model
type HiveWorker struct {
	WorkerId    int
	TimeProcess chan int64
	FreeWorkers chan *HiveWorker
	Context     *Hive
}

// initiate new manager
func NewHiveManager(numWorkers int) HiveManager {
	var totaltimeout int64 = 10

	m := HiveManager{}
	m.FreeWorkers = make(chan *HiveWorker, numWorkers)
	m.Tasks = make(chan string)
	m.TimeProcess = make(chan int64)
	m.TotalTimeOut = totaltimeout
	m.LastProcess = time.Now().Unix()
	m.Done = make(chan bool, 1)
	return m
}

// do monitoring worker thats free or not
func (m *HiveManager) DoMonitor(wg *sync.WaitGroup) {
	for {
		select {
		case task := <-m.Tasks:
			wg.Add(1)
			go m.AssignTask(task, wg)
		case result := <-m.TimeProcess:
			wg.Add(1)
			go m.InProgress(result, wg)
		case <-m.Done:
			m.Done <- true
			m.EndWorker()
			return
		}
	}
	wg.Wait()
}

// assign task to free worker
func (m *HiveManager) AssignTask(task string, wg *sync.WaitGroup) {
	defer wg.Done()
	select {
	case worker := <-m.FreeWorkers:
		log.Println("Assign task to worker", worker.WorkerId)
		wg.Add(1)
		go worker.Work(task, wg)
	case isDone := <-m.Done:
		m.Done <- isDone
		return
	}
}

// check if a task still in progress to wait it till finish
func (m *HiveManager) InProgress(result int64, wg *sync.WaitGroup) {
	defer wg.Done()
	m.LastProcess = int64(result)
}

// set the timeout to waiting for tasks execution
func (m *HiveManager) Timeout(seconds int, wg *sync.WaitGroup) {
	defer wg.Done()
	for {
		if time.Now().Unix()-m.LastProcess > int64(seconds) {
			m.Done <- true
			return
		} else {
			time.Sleep(time.Millisecond)
		}
	}
}

func (m *HiveManager) EndWorker() {
	for {
		select {
		case worker := <-m.FreeWorkers:
			worker.Context.Conn.Close()
		default:
			return
		}
	}
}

// do a task for worker
func (w *HiveWorker) Work(task string, wg *sync.WaitGroup) {
	defer wg.Done()

	if err := w.Context.Conn.TestConnection(); err != nil {
		w.Context.Conn.Open()
	}

	log.Println("Do task ", task)
	query := task
	if strings.LastIndex(query, ";") == -1 {
		query += ";"
	}
	w.Context.Conn.SendInput(query)

	w.TimeProcess <- time.Now().Unix()
	w.FreeWorkers <- w
}
<commit_msg>modify pointer part 2<commit_after>package hive

import (
	"log"
	"strings"
	"sync"
	"time"
)

// manager model
type HiveManager struct {
	FreeWorkers  chan *HiveWorker
	Tasks        chan string
	Done         chan bool
	TimeProcess  chan int64
	LastProcess  int64
	TotalTimeOut int64
}

// worker model
type HiveWorker struct {
	WorkerId    int
	TimeProcess chan int64
	FreeWorkers chan *HiveWorker
	Context     *Hive
}

// initiate new manager
func NewHiveManager(numWorkers int) HiveManager {
	var totaltimeout int64 = 10

	m := HiveManager{}
	m.FreeWorkers = make(chan *HiveWorker, numWorkers)
	m.Tasks = make(chan string)
	m.TimeProcess = make(chan int64)
	m.TotalTimeOut = totaltimeout
	m.LastProcess = time.Now().Unix()
	m.Done = make(chan bool, 1)
	return m
}

// do monitoring worker thats free or not
func (m *HiveManager) DoMonitor(wg *sync.WaitGroup) {
	for {
		select {
		case task := <-m.Tasks:
			wg.Add(1)
			go m.AssignTask(task, wg)
		case result := <-m.TimeProcess:
			wg.Add(1)
			go m.InProgress(result, wg)
		case <-m.Done:
			m.Done <- true
			m.EndWorker()
			return
		}
	}
	wg.Wait()
}

// assign task to free worker
func (m *HiveManager) AssignTask(task string, wg *sync.WaitGroup) {
	defer wg.Done()
	select {
	case worker := <-m.FreeWorkers:
		log.Println("Assign task to worker", worker.WorkerId)
		wg.Add(1)
		go worker.Work(task, wg)
	case isDone := <-m.Done:
		m.Done <- isDone
		return
	}
}

// check if a task still in progress to wait it till finish
func (m *HiveManager) InProgress(result int64, wg *sync.WaitGroup) {
	defer wg.Done()
	m.LastProcess = int64(result)
}

// set the timeout to waiting for tasks execution
func (m *HiveManager) Timeout(seconds int, wg *sync.WaitGroup) {
	defer wg.Done()
	for {
		if time.Now().Unix()-m.LastProcess > int64(seconds) {
			m.Done <- true
			return
		} else {
			time.Sleep(time.Millisecond)
		}
	}
}

func (m *HiveManager) EndWorker() {
	for {
		select {
		case worker := <-m.FreeWorkers:
			worker.Context.Conn.Close()
		default:
			return
		}
	}
}

// do a task for worker
func (w *HiveWorker) Work(task string, wg *sync.WaitGroup) {
	defer wg.Done()

	log.Printf("jancuk %#v", w)

	if err := w.Context.Conn.TestConnection(); err != nil {
		w.Context.Conn.Open()
	}

	log.Println("Do task ", task)
	query := task
	if strings.LastIndex(query, ";") == -1 {
		query += ";"
	}
	w.Context.Conn.SendInput(query)

	w.TimeProcess <- time.Now().Unix()
	w.FreeWorkers <- w
}
<|endoftext|>


<commit_before>package registration

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

	"github.com/coreos/go-etcd/etcd"
	"github.com/nsqio/go-nsq"
)

// /opsee.co/routes/customer_id/instance_id/svcname = ip:port

const (
	routesPath = "/opsee.co/routes"
	// RegistrationTTL defines the number of seconds that a registration will be
	// valid.
	RegistrationTTL = 60
)

var (
	nsqLookupds = []string{
		"nsqlookupd-1.opsy.co",
		"nsqlookupd-2.opsy.co",
	}
)

type consumerService struct {
	etcdClient   *etcd.Client
	consumer     *nsq.Consumer
	stopChan     chan struct{}
	lookupdHosts []string
}

// NewConsumer creates a new consumer service connected to the "connected" topic
// in NSQ.
func NewConsumer(consumerName, etcdHost string, nsqLookupdHosts []string, concurrency int) (*consumerService, error) {
	consumer, err := nsq.NewConsumer("_.connected", consumerName, nsq.NewConfig())
	if err != nil {
		return nil, err
	}

	consumer.SetLogger(log.New(os.Stderr, "", log.LstdFlags), nsq.LogLevelInfo)

	svc := &consumerService{
		etcd.NewClient([]string{etcdHost}),
		consumer,
		make(chan struct{}, 1),
		nsqLookupdHosts,
	}

	svc.consumer.AddConcurrentHandlers(nsq.HandlerFunc(svc.registerConnection), concurrency)

	return svc, nil
}

// /opsee.co/routes/customer_id/instance_id/svcname = ip:port
func (c *consumerService) registerConnection(msg *nsq.Message) error {
	cMsg := &ConnectedMessage{}
	if err := json.Unmarshal(msg.Body, cMsg); err != nil {
		log.Println("Error unmarshaling connected message:", msg)
		return err
	}
	log.Println("Handling message:", msg.Body)

	for _, connectedSvc := range cMsg.Services {
		log.Printf("Registering %s service for customer %s, bastion %s, at IP: %s, port: %s", connectedSvc.Name, cMsg.CustomerID, cMsg.InstanceID, cMsg.IPAddress, connectedSvc.Port)
		key := fmt.Sprintf("/opsee.co/routes/%s/%s/%s", cMsg.CustomerID, cMsg.InstanceID, connectedSvc.Name)
		value := fmt.Sprintf("%s:%s", cMsg.IPAddress, connectedSvc.Port)

		if resp, err := c.etcdClient.Set(key, value, 60); err != nil {
			return err
		}
		log.Printf("ETCD Response Node: %s", *resp.Node)
	}

	return nil
}

func (c *consumerService) Start() error {
	return c.consumer.ConnectToNSQLookupds(c.lookupdHosts)
}

func (c *consumerService) Stop() error {
	c.consumer.Stop()
	return nil
}
<commit_msg>Port is an integer<commit_after>package registration

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

	"github.com/coreos/go-etcd/etcd"
	"github.com/nsqio/go-nsq"
)

// /opsee.co/routes/customer_id/instance_id/svcname = ip:port

const (
	routesPath = "/opsee.co/routes"
	// RegistrationTTL defines the number of seconds that a registration will be
	// valid.
	RegistrationTTL = 60
)

var (
	nsqLookupds = []string{
		"nsqlookupd-1.opsy.co",
		"nsqlookupd-2.opsy.co",
	}
)

type consumerService struct {
	etcdClient   *etcd.Client
	consumer     *nsq.Consumer
	stopChan     chan struct{}
	lookupdHosts []string
}

// NewConsumer creates a new consumer service connected to the "connected" topic
// in NSQ.
func NewConsumer(consumerName, etcdHost string, nsqLookupdHosts []string, concurrency int) (*consumerService, error) {
	consumer, err := nsq.NewConsumer("_.connected", consumerName, nsq.NewConfig())
	if err != nil {
		return nil, err
	}

	consumer.SetLogger(log.New(os.Stderr, "", log.LstdFlags), nsq.LogLevelInfo)

	svc := &consumerService{
		etcd.NewClient([]string{etcdHost}),
		consumer,
		make(chan struct{}, 1),
		nsqLookupdHosts,
	}

	svc.consumer.AddConcurrentHandlers(nsq.HandlerFunc(svc.registerConnection), concurrency)

	return svc, nil
}

// /opsee.co/routes/customer_id/instance_id/svcname = ip:port
func (c *consumerService) registerConnection(msg *nsq.Message) error {
	cMsg := &ConnectedMessage{}
	if err := json.Unmarshal(msg.Body, cMsg); err != nil {
		log.Println("Error unmarshaling connected message:", msg)
		return err
	}
	log.Println("Handling message:", msg.Body)

	for _, connectedSvc := range cMsg.Services {
		log.Printf("Registering %s service for customer %s, bastion %s, at IP: %s, port: %s", connectedSvc.Name, cMsg.CustomerID, cMsg.InstanceID, cMsg.IPAddress, connectedSvc.Port)
		key := fmt.Sprintf("/opsee.co/routes/%s/%s/%s", cMsg.CustomerID, cMsg.InstanceID, connectedSvc.Name)
		value := fmt.Sprintf("%s:%d", cMsg.IPAddress, connectedSvc.Port)

		resp, err := c.etcdClient.Set(key, value, 60)
		if err != nil {
			return err
		}
		log.Printf("ETCD Response Node: %s", *resp.Node)
	}

	return nil
}

func (c *consumerService) Start() error {
	return c.consumer.ConnectToNSQLookupds(c.lookupdHosts)
}

func (c *consumerService) Stop() error {
	c.consumer.Stop()
	return nil
}
<|endoftext|>


<commit_before>// This test uses github.com/brianm/govdep* repos
// to be known quantities. If you much about with those
// repos it *will* break the test. Sorry.
package vcs

import (
	_ "bitbucket.org/xnio/govdep2"
	_ "github.com/brianm/govdep1"
	"go/build"
	"testing"
)

var govdep1, govdep2 *build.Package

func init() {
	var err error
	govdep1, err = build.Import("github.com/brianm/govdep1", ".", 0)
	if err != nil {
		panic(err)
	}

	govdep2, err = build.Import("bitbucket.org/xnio/govdep2", ".", 0)
	if err != nil {
		panic(err)
	}
}

func TestSetup(t *testing.T) {
	if govdep1 == nil {
		t.Errorf("govdep1 is nil")
	}
	if govdep2 == nil {
		t.Errorf("govdep2 is nil")
	}
}

func TestGovDep1IsClean(t *testing.T) {
	g := GitRepo{govdep1.Dir}
	clean, err := g.IsClean()
	if err != nil {
		t.Error(err)
	}
	if !clean {
		t.Errorf("govdep1 is dirty")
	}
}

func TestMakeGovDep1Dirty(t *testing.T) {
	// g := GitRepo{govdep1.Dir}

	// touch a file in govdep1

	// defer a call to cleanup the file we touched

	// assert that govdep1 repo is dirty
}
<commit_msg>test detecting dirty repo<commit_after>// This test uses github.com/brianm/govdep* repos
// to be known quantities. If you much about with those
// repos it *will* break the test. Sorry.
package vcs

import (
	_ "bitbucket.org/xnio/govdep2"
	_ "github.com/brianm/govdep1"
	"go/build"
	"os"
	"path/filepath"
	"testing"
)

var govdep1, govdep2 *build.Package

func init() {
	var err error
	govdep1, err = build.Import("github.com/brianm/govdep1", ".", 0)
	if err != nil {
		panic(err)
	}

	govdep2, err = build.Import("bitbucket.org/xnio/govdep2", ".", 0)
	if err != nil {
		panic(err)
	}
}

func TestSetup(t *testing.T) {
	if govdep1 == nil {
		t.Errorf("govdep1 is nil")
	}
	if govdep2 == nil {
		t.Errorf("govdep2 is nil")
	}
}

func TestGovDep1IsClean(t *testing.T) {
	g := GitRepo{govdep1.Dir}
	clean, err := g.IsClean()
	if err != nil {
		t.Errorf("Unable to look for clean state of %s: %s", govdep1.Dir, err)
	}
	if !clean {
		t.Fatalf("%s should have been clean!", govdep1.Dir)
	}
}

func TestMakeGovDep1Dirty(t *testing.T) {
	tmp := filepath.Join(govdep1.Dir, "TestMakeGovDep1Dirty")
	_, err := os.Create(tmp)
	if err != nil {
		t.Error(err)
	}
	defer os.Remove(tmp)

	g := GitRepo{govdep1.Dir}
	clean, err := g.IsClean()
	if err != nil {
		t.Errorf("Unable to look for clean state of %s: %s", govdep1.Dir, err)
	}
	if clean {
		t.Fatalf("%s should have been dirty!", govdep1.Dir)
	}
}
<|endoftext|>


<commit_before>package libre

import (
	"fmt"
	"io/ioutil"
	"os/exec"

	"github.com/go-martini/martini"
)

func ExposeRoutes(m martini.Routes) func() (int, string) {
	return func() (int, string) {
		md := routes_to_md(m)
		err := ioutil.WriteFile("/tmp/santo-libre.md", []byte(md), 0644)
		if err != nil {
			panic(err)
		}

		cmd := exec.Command("aglio", "-i", "/tmp/santo-libre.md", "-o", "-")
		out, err := cmd.Output()
		if err != nil {
			panic(err)
		}
		return 200, string(out)
	}
}

func routes_to_md(routes martini.Routes) string {
	s := ""
	s += "FORMAT: 1A\nHOST: http://made.up\n"
	paths := make(map[string][]martini.Route)
	for _, route := range routes.All() {
		if _, ok := paths[route.Pattern()]; ok {
			paths[route.Pattern()] = make([]martini.Route, 1)
		}
		paths[route.Pattern()] = append(paths[route.Pattern()], route)
	}
	for pattern, routes := range paths {
		s += fmt.Sprintf("## Default Name [%s]\n", pattern)
		for _, route := range routes {
			s += fmt.Sprintf("\n### Default Name [%s]\n", route.Method())
		}
	}
	return s
}
<commit_msg>changed to http.HandlerFunc<commit_after>package libre

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

	"github.com/go-martini/martini"
)

func ExposeRoutes(m martini.Routes) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		md := routes_to_md(m)
		err := ioutil.WriteFile("/tmp/santo-libre.md", []byte(md), 0644)
		if err != nil {
			panic(err)
		}

		cmd := exec.Command("aglio", "-i", "/tmp/santo-libre.md", "-o", "-")
		out, err := cmd.Output()
		if err != nil {
			panic(err)
		}
		w.Header().Set("Content-Type", "text/html")
		_, err = w.Write(out)
		if err != nil {
			panic(err)
		}
	}
}

func routes_to_md(routes martini.Routes) string {
	s := ""
	s += "FORMAT: 1A\nHOST: http://made.up\n"
	paths := make(map[string][]martini.Route)
	for _, route := range routes.All() {
		if _, ok := paths[route.Pattern()]; ok {
			paths[route.Pattern()] = make([]martini.Route, 1)
		}
		paths[route.Pattern()] = append(paths[route.Pattern()], route)
	}
	for pattern, routes := range paths {
		s += fmt.Sprintf("## Default Name [%s]\n", pattern)
		for _, route := range routes {
			s += fmt.Sprintf("\n### Default Name [%s]\n", route.Method())
		}
	}
	return s
}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"time"

	"github.com/feedbooks/epub"
	"github.com/feedbooks/webpub-streamer/models"
)

func init() {
	parserList = append(parserList, List{fileExt: "epub", parser: EpubParser})
}

// EpubParser TODO add doc
func EpubParser(filePath string, selfURL string) models.Publication {
	var manifestStruct models.Publication
	var metaStruct models.Metadata

	timeNow := time.Now()
	metaStruct.Modified = &timeNow
	manifestStruct.Links = make([]models.Link, 1)
	manifestStruct.Resources = make([]models.Link, 0)
	manifestStruct.Resources = make([]models.Link, 0)
	if selfURL != "" {
		self := models.Link{
			Rel:      []string{"self"},
			Href:     selfURL,
			TypeLink: "application/json",
		}
		manifestStruct.Links[0] = self
	}

	book, err := epub.Open(filePath)
	if err != nil {
		fmt.Println(err)
		return models.Publication{}
	}
	manifestStruct.Internal = append(manifestStruct.Internal, models.Internal{Name: "epub", Value: book.ZipReader()})
	manifestStruct.Internal = append(manifestStruct.Internal, models.Internal{Name: "rootfile", Value: book.Container.Rootfile.Path})

	metaStruct.Title = book.Opf.Metadata.Title[0]

	metaStruct.Language = book.Opf.Metadata.Language
	metaStruct.Identifier = book.Opf.Metadata.Identifier[0].Data
	if len(book.Opf.Metadata.Contributor) > 0 {
		for _, cont := range book.Opf.Metadata.Contributor {
			addContributor(&metaStruct, cont)
		}
	}
	if len(book.Opf.Metadata.Creator) > 0 {
		for _, cont := range book.Opf.Metadata.Creator {
			addContributor(&metaStruct, cont)
		}
	}

	for _, item := range book.Opf.Manifest {
		linkItem := models.Link{}
		linkItem.TypeLink = item.MediaType
		linkItem.Href = item.Href
		if linkItem.TypeLink == "application/xhtml+xml" {
			manifestStruct.Spine = append(manifestStruct.Spine, linkItem)
		} else {
			manifestStruct.Resources = append(manifestStruct.Resources, linkItem)
		}
	}

	manifestStruct.Metadata = metaStruct
	return manifestStruct
}

func addContributor(metadata *models.Metadata, cont epub.Author) {
	var aut models.Contributor

	aut.Name = cont.Data
	aut.Role = cont.Role
	metadata.Author = append(metadata.Author, aut)
}
<commit_msg>add better title and contributor handling, get epub version<commit_after>package parser

import (
	"fmt"
	"time"

	"github.com/feedbooks/epub"
	"github.com/feedbooks/webpub-streamer/models"
)

func init() {
	parserList = append(parserList, List{fileExt: "epub", parser: EpubParser})
}

// EpubParser TODO add doc
func EpubParser(filePath string, selfURL string) models.Publication {
	var manifestStruct models.Publication
	var metaStruct models.Metadata
	var epubVersion string

	timeNow := time.Now()
	metaStruct.Modified = &timeNow
	manifestStruct.Links = make([]models.Link, 1)
	manifestStruct.Resources = make([]models.Link, 0)
	manifestStruct.Resources = make([]models.Link, 0)
	if selfURL != "" {
		self := models.Link{
			Rel:      []string{"self"},
			Href:     selfURL,
			TypeLink: "application/json",
		}
		manifestStruct.Links[0] = self
	}

	book, err := epub.Open(filePath)
	if err != nil {
		fmt.Println(err)
		return models.Publication{}
	}
	epubVersion = book.Container.Rootfile.Version
	manifestStruct.Internal = append(manifestStruct.Internal, models.Internal{Name: "epub", Value: book.ZipReader()})
	manifestStruct.Internal = append(manifestStruct.Internal, models.Internal{Name: "rootfile", Value: book.Container.Rootfile.Path})

	addTitle(&metaStruct, &book.Opf, epubVersion)
	metaStruct.Language = book.Opf.Metadata.Language
	metaStruct.Identifier = book.Opf.Metadata.Identifier[0].Data
	if len(book.Opf.Metadata.Contributor) > 0 {
		for _, cont := range book.Opf.Metadata.Contributor {
			addContributor(&metaStruct, cont)
		}
	}
	if len(book.Opf.Metadata.Creator) > 0 {
		for _, cont := range book.Opf.Metadata.Creator {
			addContributor(&metaStruct, cont)
		}
	}

	for _, item := range book.Opf.Spine.Items {
		linkItem := findInManifestByID(book, item.IDref)
		if linkItem.Href != "" {
			manifestStruct.Spine = append(manifestStruct.Spine, linkItem)
		}
	}

	for _, item := range book.Opf.Manifest {

		linkSpine := findInSpineByHref(&manifestStruct, item.Href)
		if linkSpine.Href == "" {
			linkItem := models.Link{}
			linkItem.TypeLink = item.MediaType
			linkItem.Href = item.Href
			manifestStruct.Resources = append(manifestStruct.Resources, linkItem)
		}
	}

	manifestStruct.Metadata = metaStruct
	return manifestStruct
}

func findInSpineByHref(publication *models.Publication, href string) models.Link {
	for _, l := range publication.Spine {
		if l.Href == href {
			return l
		}
	}

	return models.Link{}
}

func findInManifestByID(book *epub.Book, ID string) models.Link {
	for _, item := range book.Opf.Manifest {
		if item.ID == ID {
			linkItem := models.Link{}
			linkItem.TypeLink = item.MediaType
			linkItem.Href = item.Href
			return linkItem
		}
	}
	return models.Link{}
}

func addContributor(metadata *models.Metadata, cont epub.Author) {
	var contributor models.Contributor

	contributor.Name = cont.Data
	contributor.Role = cont.Role
	switch contributor.Role {
	case "aut":
		metadata.Author = append(metadata.Author, contributor)
	case "trl":
		metadata.Translator = append(metadata.Author, contributor)
	case "art":
		metadata.Artist = append(metadata.Artist, contributor)
	case "edt":
		metadata.Editor = append(metadata.Editor, contributor)
	case "ill":
		metadata.Illustrator = append(metadata.Illustrator, contributor)
	case "nrt":
		metadata.Narrator = append(metadata.Narrator, contributor)
	default:
		metadata.Contributor = append(metadata.Contributor, contributor)
	}
}

func addTitle(metadata *models.Metadata, opf *epub.Opf, epubVersion string) {

	if len(opf.Metadata.Title) > 1 && epubVersion == "3.0" {
		for _, titleTag := range opf.Metadata.Title {
			for _, metaTag := range opf.Metadata.Meta {
				if metaTag.Refine == "#"+titleTag.ID {
					if metaTag.Data == "main" {
						metadata.Title = titleTag.Data
					}
				}
			}
		}
	} else {
		metadata.Title = opf.Metadata.Title[0].Data
	}

}
<|endoftext|>


<commit_before>package irc

import "testing"

var eventTests = []struct {
	Prefix, Cmd string
	Args        []string
	Expect      string
}{
	{
		Prefix: "server.kevlar.net",
		Cmd:    "NOTICE",
		Args:   []string{"user", "*** This is a test"},
		Expect: ":server.kevlar.net NOTICE user :*** This is a test\n",
	},
	{
		Prefix: "A",
		Cmd:    "B",
		Args:   []string{"C"},
		Expect: ":A B C\n",
	},
	{
		Cmd:    "B",
		Args:   []string{"C"},
		Expect: "B C\n",
	},
	{
		Prefix: "A",
		Cmd:    "B",
		Args:   []string{"C", "D"},
		Expect: ":A B C D\n",
	},
}

func TestParseEvent(t *testing.T) {
	for i, test := range eventTests {
		e := ParseEvent(test.Expect)
		if e == nil {
			t.Errorf("%d. Got nil for valid event", i)
			continue
		}
		if test.Prefix != e.Prefix {
			t.Errorf("%d. prefix = %q, want %q", i, e.Prefix, test.Prefix)
		}
		if test.Cmd != e.Command {
			t.Errorf("%d. command = %q, want %q", i, e.Command, test.Cmd)
		}
		if len(test.Args) != len(e.Args) {
			t.Errorf("%d. args = %v, want %v", i, e.Args, test.Args)
		} else {
			for j := 0; j < len(test.Args) && j < len(e.Args); j++ {
				if test.Args[j] != e.Args[j] {
					t.Errorf("%d. arg[%d] = %q, want %q", i, e.Args[j], test.Args[j])
				}
			}
		}
	}
}

func BenchmarkParseEvent(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ParseEvent(eventTests[i%len(eventTests)].Expect)
	}
}

var identityTests = []struct {
	Nick, User, Host string
	Expect           string
}{
	{
		Nick:   "NickServA",
		User:   "NickServB",
		Host:   "services",
		Expect: "NickServA!NickServB@services",
	},
	{
		User:   "NickServ",
		Host:   "services",
		Expect: "NickServ@services",
	},
	{
		Host:   "NickServ",
		Expect: "NickServ",
	},
}

func TestParseIdentity(t *testing.T) {
	for i, test := range identityTests {
		pi := ParseIdentity(test.Expect)
		if pi == nil {
			t.Errorf("%d. Got nil for valid identity", pi)
			continue
		}
		if test.Nick != pi.Nick {
			t.Errorf("%d. nick = %q, want %q", i, pi.Nick, test.Nick)
		}
		if test.User != pi.User {
			t.Errorf("%d. user = %q, want %q", i, pi.User, test.User)
		}
		if test.Host != pi.Host {
			t.Errorf("%d. host = %q, want %q", i, pi.Host, test.Host)
		}
	}
}

func BenchmarkParseIdentity(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ParseIdentity(identityTests[i%len(identityTests)].Expect)
	}
}
<commit_msg>get parser.go coverage to 100%<commit_after>package irc

import (
	"reflect"
	"testing"
)

var eventTests = []struct {
	// Event parsing
	Prefix, Cmd string
	Args        []string

	// Identity parsing
	Nick, User, Host string

	// Total output
	Expect string
	IsNil  bool

	// FromChannel
	FromChan bool
}{
	{
		IsNil: true,
	},
	{
		Expect: ":A",
		IsNil:  true,
	},
	{
		Prefix: "server.kevlar.net",
		Cmd:    "PING",

		Host: "server.kevlar.net",

		Expect: ":server.kevlar.net PING\n",
	},
	{
		Prefix: "server.kevlar.net",
		Cmd:    "NOTICE",
		Args:   []string{"user", "*** This is a test"},

		Host: "server.kevlar.net",

		Expect: ":server.kevlar.net NOTICE user :*** This is a test\n",
	},
	{
		Prefix: "belakA!belakB@a.host.com",
		Cmd:    "PRIVMSG",
		Args:   []string{"#somewhere", "*** This is a test"},

		Nick: "belakA",
		User: "belakB",
		Host: "a.host.com",

		Expect:   ":belakA!belakB@a.host.com PRIVMSG #somewhere :*** This is a test\n",
		FromChan: true,
	},
	{
		Prefix: "belakA!belakB@a.host.com",
		Cmd:    "PRIVMSG",
		Args:   []string{"&somewhere", "*** This is a test"},

		Nick: "belakA",
		User: "belakB",
		Host: "a.host.com",

		Expect:   ":belakA!belakB@a.host.com PRIVMSG &somewhere :*** This is a test\n",
		FromChan: true,
	},
	{
		Prefix: "belakA!belakB@a.host.com",
		Cmd:    "PRIVMSG",
		Args:   []string{"belak", "*** This is a test"},

		Nick: "belakA",
		User: "belakB",
		Host: "a.host.com",

		Expect: ":belakA!belakB@a.host.com PRIVMSG belak :*** This is a test\n",
	},
	{
		Prefix: "A",
		Cmd:    "B",
		Args:   []string{"C"},

		Host: "A",

		Expect: ":A B C\n",
	},
	{
		Prefix: "A@B",
		Cmd:    "C",
		Args:   []string{"D"},

		User: "A",
		Host: "B",

		Expect: ":A@B C D\n",
	},
	{
		Cmd:    "B",
		Args:   []string{"C"},
		Expect: "B C\n",
	},
	{
		Prefix: "A",
		Cmd:    "B",
		Args:   []string{"C", "D"},

		Host: "A",

		Expect: ":A B C D\n",
	},
}

func TestParseEvent(t *testing.T) {
	for i, test := range eventTests {
		e := ParseEvent(test.Expect)
		if e == nil && !test.IsNil {
			t.Errorf("%d. Got nil for valid event", i)
		} else if e != nil && test.IsNil {
			t.Errorf("%d. Didn't get nil for invalid event", i)
		}

		if e == nil {
			continue
		}

		if test.Prefix != e.Prefix {
			t.Errorf("%d. prefix = %q, want %q", i, e.Prefix, test.Prefix)
		}
		if test.Cmd != e.Command {
			t.Errorf("%d. command = %q, want %q", i, e.Command, test.Cmd)
		}
		if len(test.Args) != len(e.Args) {
			t.Errorf("%d. args = %v, want %v", i, e.Args, test.Args)
		} else {
			for j := 0; j < len(test.Args) && j < len(e.Args); j++ {
				if test.Args[j] != e.Args[j] {
					t.Errorf("%d. arg[%d] = %q, want %q", i, e.Args[j], test.Args[j])
				}
			}
		}
	}
}

func BenchmarkParseEvent(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ParseEvent(eventTests[i%len(eventTests)].Prefix)
	}
}

func TestParseIdentity(t *testing.T) {
	for i, test := range eventTests {
		// TODO: Not sure if we should be skipping empty strings or handling them.
		if test.Prefix == "" {
			continue
		}

		pi := ParseIdentity(test.Prefix)
		if pi == nil {
			t.Errorf("%d. Got nil for valid identity", pi)
			continue
		}
		if test.Nick != pi.Nick {
			t.Errorf("%d. nick = %q, want %q", i, pi.Nick, test.Nick)
		}
		if test.User != pi.User {
			t.Errorf("%d. user = %q, want %q", i, pi.User, test.User)
		}
		if test.Host != pi.Host {
			t.Errorf("%d. host = %q, want %q", i, pi.Host, test.Host)
		}
	}
}

func BenchmarkParseIdentity(b *testing.B) {
	for i := 0; i < b.N; i++ {
		ParseIdentity(eventTests[i%len(eventTests)].Expect)
	}
}

func TestEventTrailing(t *testing.T) {
	for i, test := range eventTests {
		if test.IsNil {
			continue
		}

		e := ParseEvent(test.Expect)
		tr := e.Trailing()
		if len(test.Args) < 1 {
			if tr != "" {
				t.Errorf("%d. trailing = %q, want %q", i, tr, "")
			}
		} else if tr != test.Args[len(test.Args)-1] {
			t.Errorf("%d. trailing = %q, want %q", i, tr, test.Args[len(test.Args)-1])
		}
	}
}

func TestEventFromChan(t *testing.T) {
	for i, test := range eventTests {
		if test.IsNil {
			continue
		}

		e := ParseEvent(test.Expect)
		if e.FromChannel() != test.FromChan {
			t.Errorf("%d. fromchannel = %q, want %q", i, e.FromChannel(), test.FromChan)
		}
	}
}

func TestEventCopy(t *testing.T) {
	for i, test := range eventTests {
		if test.IsNil {
			continue
		}

		e := ParseEvent(test.Expect)
		c := e.Copy()

		if !reflect.DeepEqual(e, c) {
			t.Errorf("%d. copy = %q, want %q", i, e, c)
		}

		c.Args = append(c.Args, "junk")
		if reflect.DeepEqual(e, c) {
			t.Errorf("%d. copyargs matched when it shouldn't", i)
		}
	}
}
<|endoftext|>


<commit_before>package main

import "testing"
import "reflect"

func TestParse(t *testing.T) {
	jobs := []CronJob{
		{line: "32 17 3 10 2 /tmp/hoge.sh", minute: []int{32}, hour: []int{17}, dayOfMonth: []int{3}, month: []int{10}, dayOfWeek: []int{2}},
		{line: "* * * * * /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: dayOfWeekRange.all},
		{line: "4,7,9 17,23 3,5 10,12 2,6 /tmp/hoge.sh", minute: []int{4, 7, 9}, hour: []int{17, 23}, dayOfMonth: []int{3, 5}, month: []int{10, 12}, dayOfWeek: []int{2, 6}},
		{line: "3-6 12-14 3-5 10-12 2-4 /tmp/hoge.sh", minute: []int{3, 4, 5, 6}, hour: []int{12, 13, 14}, dayOfMonth: []int{3, 4, 5}, month: []int{10, 11, 12}, dayOfWeek: []int{2, 3, 4}},
		{line: "3-6/2 17-20/2 3-5/2 10-12/2 1-3/2 /tmp/hoge.sh", minute: []int{3, 5}, hour: []int{17, 19}, dayOfMonth: []int{3, 5}, month: []int{10, 12}, dayOfWeek: []int{1, 3}},
		{line: "3-6/2 17-20/2 3-5/2 10-12/2 0/3 /tmp/hoge.sh", minute: []int{3, 5}, hour: []int{17, 19}, dayOfMonth: []int{3, 5}, month: []int{10, 12}, dayOfWeek: []int{0, 3, 6}},
		{line: "* * * * tue /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: []int{2}},
		{line: "* * * * sun-sat /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: []int{0, 1, 2, 3, 4, 5, 6}},
		// {line: "* * * * mon,wed,thu /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: []int{1, 3, 4}},
		// {line: "* * * * fri-sun /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: []int{5, 6, 7}},
	}

	for _, expected := range jobs {
		actual := Parse(expected.line)

		if !reflect.DeepEqual(actual, expected) {
			t.Fatalf("expected: %+v but actual: %+v\n", expected, actual)
		}
	}
}

func TestNewCronRange(t *testing.T) {
	r := newCronRange(1, 31)

	if len(r.all) != 31 {
		t.Fatalf("expected: %d but actual: %d\n", 31, len(r.all))
	}
	for index, actual := range r.all {
		if expected := index + 1; actual != expected {
			t.Fatalf("expected: %q but actual: %q\n", expected, actual)
		}
	}

}
<commit_msg>add test case<commit_after>package main

import "testing"
import "reflect"

func TestParse(t *testing.T) {
	jobs := []CronJob{
		{line: "32 17 3 10 2 /tmp/hoge.sh", minute: []int{32}, hour: []int{17}, dayOfMonth: []int{3}, month: []int{10}, dayOfWeek: []int{2}},
		{line: "* * * * * /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: dayOfWeekRange.all},
		{line: "4,7,9 17,23 3,5 10,12 2,6 /tmp/hoge.sh", minute: []int{4, 7, 9}, hour: []int{17, 23}, dayOfMonth: []int{3, 5}, month: []int{10, 12}, dayOfWeek: []int{2, 6}},
		{line: "3-6 12-14 3-5 10-12 2-4 /tmp/hoge.sh", minute: []int{3, 4, 5, 6}, hour: []int{12, 13, 14}, dayOfMonth: []int{3, 4, 5}, month: []int{10, 11, 12}, dayOfWeek: []int{2, 3, 4}},
		{line: "3-6/2 17-20/2 3-5/2 10-12/2 1-3/2 /tmp/hoge.sh", minute: []int{3, 5}, hour: []int{17, 19}, dayOfMonth: []int{3, 5}, month: []int{10, 12}, dayOfWeek: []int{1, 3}},
		{line: "3-6/2 17-20/2 3-5/2 10-12/2 0/3 /tmp/hoge.sh", minute: []int{3, 5}, hour: []int{17, 19}, dayOfMonth: []int{3, 5}, month: []int{10, 12}, dayOfWeek: []int{0, 3, 6}},
		{line: "* * * * tue /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: []int{2}},
		{line: "* * * * sun-sat /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: []int{0, 1, 2, 3, 4, 5, 6}},
		{line: "* * * * mon,wed,thu /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: []int{1, 3, 4}},
		// {line: "* * * * fri-sun /tmp/hoge.sh", minute: minutesRange.all, hour: hourRange.all, dayOfMonth: dayOfMonthRange.all, month: monthRange.all, dayOfWeek: []int{5, 6, 7}},
	}

	for _, expected := range jobs {
		actual := Parse(expected.line)

		if !reflect.DeepEqual(actual, expected) {
			t.Fatalf("expected: %+v but actual: %+v\n", expected, actual)
		}
	}
}

func TestNewCronRange(t *testing.T) {
	r := newCronRange(1, 31)

	if len(r.all) != 31 {
		t.Fatalf("expected: %d but actual: %d\n", 31, len(r.all))
	}
	for index, actual := range r.all {
		if expected := index + 1; actual != expected {
			t.Fatalf("expected: %q but actual: %q\n", expected, actual)
		}
	}

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"net"
	"regexp"
)

func revers(ip4 string, fqdn bool, short bool, domain bool) {
	Hostname, err := net.LookupAddr(ip4)
	if err == nil {
		switch {
		case domain:
			regE := regexp.MustCompile("^[^.]*[.](.*)[.]$")
			fmt.Printf("%s\n", regE.FindStringSubmatch(Hostname[0])[1])
		case fqdn:
			regE := regexp.MustCompile("^(.*)[.]$")
			fmt.Printf("%s\n", regE.FindStringSubmatch(Hostname[0])[1])
		default:
			regE := regexp.MustCompile("^([^.]*)")
			fmt.Printf("%s\n", regE.FindStringSubmatch(Hostname[0])[1])
		}
	}
}

func main() {

	fqdnPtr := flag.Bool("f", false, "long host name (FQDN)")
	shortPtr := flag.Bool("s", false, "short host name")
	domainPtr := flag.Bool("d", false, "DNS domain name")
	flag.Parse()

	regS := regexp.MustCompile("[0-9.]*")
	interfaces, _ := net.Interfaces()
	for _, inter := range interfaces {
		if addrs, err := inter.Addrs(); err == nil {
			for _, addr := range addrs {
				monip := regS.FindString(addr.String())
				if monip != "127.0.0.1" {
					revers(monip, *fqdnPtr, *shortPtr, *domainPtr)
				}
			}
		}
	}

}
<commit_msg>Add -i flag to show ip<commit_after>package main

import (
	"flag"
	"fmt"
	"net"
	"regexp"
)

func revers(ip4 string, fqdn bool, short bool, domain bool, ip bool) {
	Hostname, err := net.LookupAddr(ip4)
	if err == nil {
		switch {
		case domain:
			regE := regexp.MustCompile("^[^.]*[.](.*)[.]$")
			fmt.Printf("%s\n", regE.FindStringSubmatch(Hostname[0])[1])
		case fqdn:
			regE := regexp.MustCompile("^(.*)[.]$")
			fmt.Printf("%s\n", regE.FindStringSubmatch(Hostname[0])[1])
		case ip:
			fmt.Printf("%s\n", ip4)
		default:
			regE := regexp.MustCompile("^([^.]*)")
			fmt.Printf("%s\n", regE.FindStringSubmatch(Hostname[0])[1])
		}
	}
}

func main() {

	fqdnPtr := flag.Bool("f", false, "long host name (FQDN)")
	shortPtr := flag.Bool("s", false, "short host name (default)")
	domainPtr := flag.Bool("d", false, "DNS domain name")
	ipPtr := flag.Bool("i", false, "addresses for the host name")
	flag.Parse()

	regS := regexp.MustCompile("[0-9.]*")
	interfaces, _ := net.Interfaces()
	for _, inter := range interfaces {
		if addrs, err := inter.Addrs(); err == nil {
			for _, addr := range addrs {
				monip := regS.FindString(addr.String())
				if monip != "127.0.0.1" {
					revers(monip, *fqdnPtr, *shortPtr, *domainPtr, *ipPtr)
				}
			}
		}
	}

}
<|endoftext|>


<commit_before>// Package httpcache provides a http.RoundTripper implementation that works as a
// mostly RFC-compliant cache for http responses.
//
// It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client
// and not for a shared proxy).
//
// 'max-stale' set on a request is not currently respected. (max-age and min-fresh both are.)
package httpcache

import (
	"bufio"
	"bytes"
	"fmt"
	"net/http"
	"net/http/httputil"
	"strings"
	"sync"
	"time"
)

var _ = fmt.Println

const (
	stale = iota
	fresh
	transparent
	// Header added to responses that are returned from the cache
	XFromCache = "X-From-Cache"
)

// A Cache interface is used by the Transport to store and retrieve responses.
type Cache interface {
	// Get returns the []byte representation of a cached response and a bool
	// set to true if the value isn't empty
	Get(key string) (responseBytes []byte, ok bool)
	// Set stores the []byte representation of a response against a key
	Set(key string, responseBytes []byte)
	// Delete removes the value associated with the key
	Delete(key string)
}

// MemoryCache is an implemtation of Cache that stores responses in an in-memory map.
type MemoryCache struct {
	sync.RWMutex
	items map[string][]byte
}

func (c *MemoryCache) Get(key string) (resp []byte, ok bool) {
	c.RLock()
	defer c.RUnlock()
	resp, ok = c.items[key]
	return resp, ok
}

func (c *MemoryCache) Set(key string, resp []byte) {
	c.Lock()
	defer c.Unlock()
	c.items[key] = resp
}

func (c *MemoryCache) Delete(key string) {
	c.Lock()
	defer c.Unlock()
	delete(c.items, key)
}

// NewMemoryCache returns a new Cache that will store items in an in-memory map
func NewMemoryCache() *MemoryCache {
	c := &MemoryCache{items: map[string][]byte{}, RWMutex: sync.RWMutex{}}
	return c
}

// Transport is an implementation of http.RoundTripper that will return values from a cache
// where possible (avoiding a network request) and will additionally add validators (etag/if-modified-since)
// to repeated requests allowing servers to return 304 / Not Modified
//
// Note: this means that both the request and response are potentially modified
type Transport struct {
	// The RoundTripper interface actually used to make requests
	// If this follows redirects, then only the final response's cache-control will be taken into account
	transport http.RoundTripper
	cache     Cache
	// If true, responses returned from the cache will be given an extra header, X-From-Cache
	MarkCachedResponses bool
}

// NewTransport returns a new Transport using the default HTTP Transport and the
// provided Cache implementation, with MarkCachedResponses set to true
func NewTransport(c Cache) *Transport {
	t := &Transport{transport: http.DefaultTransport, cache: c, MarkCachedResponses: true}
	return t
}

// varyMatches will return false unless all of the cached values for the headers listed in Vary
// match the new request
func varyMatches(cachedResp *http.Response, req *http.Request) bool {
	respVarys := cachedResp.Header.Get("vary")
	for _, header := range strings.Split(respVarys, ",") {
		header = http.CanonicalHeaderKey(strings.Trim(header, " "))
		if header != "" && req.Header.Get(header) != cachedResp.Header.Get("X-Varied-"+header) {
			return false
		}
	}
	return true
}

// RoundTrip takes a Request and returns a Response
//
// If there is a fresh Response already in cache, then it will be returned without connecting to
// the server.
//
// If there is a stale Response, then any validators it contains will be set on the new request
// to give the server a chance to respond with NotModified. If this happens, then the cached Response
// will be returned.
func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
	cacheKey := req.URL.String()
	cachedVal, ok := t.cache.Get(cacheKey)
	cacheableMethod := req.Method == "GET" || req.Method == "HEAD"
	if !cacheableMethod {
		// Need to invalidate an existing value
		t.cache.Delete(cacheKey)
	}
	if ok && cacheableMethod && req.Header.Get("range") == "" {
		cachedResp, err := responseFromCache(cachedVal, req)
		if err == nil {
			if t.MarkCachedResponses {
				cachedResp.Header.Set(XFromCache, "1")
			}

			if varyMatches(cachedResp, req) {
				// Can only use cached value if the new request doesn't Vary significantly
				freshness := getfreshness(cachedResp.Header, req.Header)
				if freshness == fresh {
					return cachedResp, nil
				}

				if freshness == stale {
					// Add validators if caller hasn't already done so
					etag := cachedResp.Header.Get("etag")
					if etag != "" && req.Header.Get("etag") == "" {
						req.Header.Set("if-none-match", etag)
					}
					lastModified := cachedResp.Header.Get("last-modified")
					if lastModified != "" && req.Header.Get("last-modified") == "" {
						req.Header.Set("if-modified-since", lastModified)
					}
				}
			}

			resp, err = t.transport.RoundTrip(req)
			if err == nil && req.Method == "GET" && resp.StatusCode == http.StatusNotModified {
				// Replace the 304 response with the one from cache, but update with some new headers
				headersToMerge := getHopByHopHeaders(resp)
				for _, headerKey := range headersToMerge {
					cachedResp.Header.Set(headerKey, resp.Header.Get(headerKey))
				}
				cachedResp.Status = http.StatusText(http.StatusOK)
				cachedResp.StatusCode = http.StatusOK

				resp = cachedResp
			} else {
				if err != nil || resp.StatusCode != http.StatusOK {
					t.cache.Delete(cacheKey)
				}
			}
		}
	} else {
		reqCacheControl := parseCacheControl(req.Header)
		if _, ok := reqCacheControl["only-if-cached"]; ok {
			resp = newGatewayTimeoutResponse(req)
		} else {
			resp, err = t.transport.RoundTrip(req)
		}
	}
	reqCacheControl := parseCacheControl(req.Header)
	respCacheControl := parseCacheControl(resp.Header)

	if canStore(reqCacheControl, respCacheControl) {
		vary := resp.Header.Get("Vary")
		for _, varyKey := range strings.Split(vary, ",") {
			varyKey = http.CanonicalHeaderKey(strings.Trim(varyKey, " "))
			fakeHeader := "X-Varied-" + varyKey
			reqValue := req.Header.Get(varyKey)
			if reqValue != "" {
				resp.Header.Set(fakeHeader, reqValue)
			}
		}
		respBytes, err := httputil.DumpResponse(resp, true)
		if err == nil {
			// fmt.Println("Set cache", string(respBytes))
			t.cache.Set(cacheKey, respBytes)
		}
	} else {
		t.cache.Delete(cacheKey)
	}
	return resp, nil
}

// getfreshness will return one of fresh/stale/transparent based on the cache-control
// values of the request and the response
//
// fresh indicates the response can be returned
// stale indicates that the response needs validating before it is returned
// transparent indicates the response should not be used to fulfil the request
//
// Because this is only a private cache, 'public' and 'private' in cache-control aren't
// signficant. Similarly, smax-age isn't used.
//
// Limitation: max-stale is not taken into account. It should be.
func getfreshness(respHeaders, reqHeaders http.Header) (freshness int) {
	respCacheControl := parseCacheControl(respHeaders)
	reqCacheControl := parseCacheControl(reqHeaders)
	if _, ok := reqCacheControl["no-cache"]; ok {
		return transparent
	}
	if _, ok := respCacheControl["no-cache"]; ok {
		return stale
	}
	if _, ok := reqCacheControl["only-if-cached"]; ok {
		return fresh
	}
	dateHeader := respHeaders.Get("date")
	if dateHeader != "" {
		date, err := time.Parse(time.RFC1123, dateHeader)
		if err != nil {
			return stale
		}
		currentAge := time.Since(date)
		var lifetime time.Duration
		zeroDuration, _ := time.ParseDuration("0s")
		// If a response includes both an Expires header and a max-age directive,
		// the max-age directive overrides the Expires header, even if the Expires header is more restrictive.
		if maxAge, ok := respCacheControl["max-age"]; ok {
			lifetime, err = time.ParseDuration(maxAge + "s")
			if err != nil {
				lifetime = zeroDuration
			}
		} else {
			if expiresHeader, ok := respCacheControl["expires"]; ok {
				expires, err := time.Parse(time.RFC1123, expiresHeader)
				if err != nil {
					lifetime = zeroDuration
				} else {
					lifetime = expires.Sub(date)
				}
			}
		}

		if maxAge, ok := reqCacheControl["max-age"]; ok {
			// the client is willing to accept a response whose age is no greater than the specified time in seconds
			lifetime, err = time.ParseDuration(maxAge + "s")
			if err != nil {
				lifetime = zeroDuration
			}
		}
		if minfresh, ok := reqCacheControl["min-fresh"]; ok {
			//  the client wants a response that will still be fresh for at least the specified number of seconds.
			minfreshDuration, err := time.ParseDuration(minfresh + "s")
			if err != nil {
				currentAge = time.Duration(currentAge.Nanoseconds() + minfreshDuration.Nanoseconds())
			}
		}

		if lifetime > currentAge {
			return fresh
		}

	}
	return stale
}

func getHopByHopHeaders(resp *http.Response) []string {
	// These headers are always hop-by-hop
	headers := []string{"connection", "keep-alive", "proxy-authenticate", "proxy-authorization", "te", "trailers", "transfer-encoding", "upgrade"}

	for _, extra := range strings.Split(resp.Header.Get("connection"), ",") {
		// any header listed in connection, if present, is also considered hop-by-hop
		if strings.Trim(extra, " ") != "" {
			headers = append(headers, extra)
		}
	}
	return headers
}

func canStore(reqCacheControl, respCacheControl cacheControl) (canStore bool) {
	if _, ok := respCacheControl["no-store"]; ok {
		return false
	}
	if _, ok := reqCacheControl["no-store"]; ok {
		return false
	}
	return true
}

func responseFromCache(cachedVal []byte, req *http.Request) (*http.Response, error) {
	b := bytes.NewBuffer(cachedVal)
	resp, err := http.ReadResponse(bufio.NewReader(b), req)
	return resp, err
}

func newGatewayTimeoutResponse(req *http.Request) *http.Response {
	var braw bytes.Buffer
	braw.WriteString("HTTP/1.1 504 Gateway Timeout\r\n\r\n")
	resp, err := http.ReadResponse(bufio.NewReader(&braw), req)
	if err != nil {
		panic(err)
	}
	return resp
}

type cacheControl map[string]string

func parseCacheControl(headers http.Header) cacheControl {
	cc := cacheControl{}
	ccHeader := headers.Get("Cache-Control")
	for _, part := range strings.Split(ccHeader, ",") {
		part = strings.Trim(part, " ")
		if part == "" {
			continue
		}
		if strings.ContainsRune(part, '=') {
			keyval := strings.Split(part, "=")
			cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",")
		} else {
			cc[part] = "1"
		}
	}
	return cc
}

// NewMemoryCacheTransport returns a new Transport using the in-memory cache implementation
func NewMemoryCacheTransport() *Transport {
	c := NewMemoryCache()
	t := NewTransport(c)
	return t
}
<commit_msg>Fixed handling of Expires header in response<commit_after>// Package httpcache provides a http.RoundTripper implementation that works as a
// mostly RFC-compliant cache for http responses.
//
// It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client
// and not for a shared proxy).
//
// 'max-stale' set on a request is not currently respected. (max-age and min-fresh both are.)
package httpcache

import (
	"bufio"
	"bytes"
	"net/http"
	"net/http/httputil"
	"strings"
	"sync"
	"time"
)

const (
	stale = iota
	fresh
	transparent
	// Header added to responses that are returned from the cache
	XFromCache = "X-From-Cache"
)

// A Cache interface is used by the Transport to store and retrieve responses.
type Cache interface {
	// Get returns the []byte representation of a cached response and a bool
	// set to true if the value isn't empty
	Get(key string) (responseBytes []byte, ok bool)
	// Set stores the []byte representation of a response against a key
	Set(key string, responseBytes []byte)
	// Delete removes the value associated with the key
	Delete(key string)
}

// MemoryCache is an implemtation of Cache that stores responses in an in-memory map.
type MemoryCache struct {
	sync.RWMutex
	items map[string][]byte
}

func (c *MemoryCache) Get(key string) (resp []byte, ok bool) {
	c.RLock()
	defer c.RUnlock()
	resp, ok = c.items[key]
	return resp, ok
}

func (c *MemoryCache) Set(key string, resp []byte) {
	c.Lock()
	defer c.Unlock()
	c.items[key] = resp
}

func (c *MemoryCache) Delete(key string) {
	c.Lock()
	defer c.Unlock()
	delete(c.items, key)
}

// NewMemoryCache returns a new Cache that will store items in an in-memory map
func NewMemoryCache() *MemoryCache {
	c := &MemoryCache{items: map[string][]byte{}, RWMutex: sync.RWMutex{}}
	return c
}

// Transport is an implementation of http.RoundTripper that will return values from a cache
// where possible (avoiding a network request) and will additionally add validators (etag/if-modified-since)
// to repeated requests allowing servers to return 304 / Not Modified
//
// Note: this means that both the request and response are potentially modified
type Transport struct {
	// The RoundTripper interface actually used to make requests
	// If this follows redirects, then only the final response's cache-control will be taken into account
	transport http.RoundTripper
	cache     Cache
	// If true, responses returned from the cache will be given an extra header, X-From-Cache
	MarkCachedResponses bool
}

// NewTransport returns a new Transport using the default HTTP Transport and the
// provided Cache implementation, with MarkCachedResponses set to true
func NewTransport(c Cache) *Transport {
	t := &Transport{transport: http.DefaultTransport, cache: c, MarkCachedResponses: true}
	return t
}

// varyMatches will return false unless all of the cached values for the headers listed in Vary
// match the new request
func varyMatches(cachedResp *http.Response, req *http.Request) bool {
	respVarys := cachedResp.Header.Get("vary")
	for _, header := range strings.Split(respVarys, ",") {
		header = http.CanonicalHeaderKey(strings.Trim(header, " "))
		if header != "" && req.Header.Get(header) != cachedResp.Header.Get("X-Varied-"+header) {
			return false
		}
	}
	return true
}

// RoundTrip takes a Request and returns a Response
//
// If there is a fresh Response already in cache, then it will be returned without connecting to
// the server.
//
// If there is a stale Response, then any validators it contains will be set on the new request
// to give the server a chance to respond with NotModified. If this happens, then the cached Response
// will be returned.
func (t *Transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
	cacheKey := req.URL.String()
	cachedVal, ok := t.cache.Get(cacheKey)
	cacheableMethod := req.Method == "GET" || req.Method == "HEAD"
	if !cacheableMethod {
		// Need to invalidate an existing value
		t.cache.Delete(cacheKey)
	}
	if ok && cacheableMethod && req.Header.Get("range") == "" {
		cachedResp, err := responseFromCache(cachedVal, req)
		if err == nil {
			if t.MarkCachedResponses {
				cachedResp.Header.Set(XFromCache, "1")
			}

			if varyMatches(cachedResp, req) {
				// Can only use cached value if the new request doesn't Vary significantly
				freshness := getFreshness(cachedResp.Header, req.Header)
				if freshness == fresh {
					return cachedResp, nil
				}

				if freshness == stale {
					// Add validators if caller hasn't already done so
					etag := cachedResp.Header.Get("etag")
					if etag != "" && req.Header.Get("etag") == "" {
						req.Header.Set("if-none-match", etag)
					}
					lastModified := cachedResp.Header.Get("last-modified")
					if lastModified != "" && req.Header.Get("last-modified") == "" {
						req.Header.Set("if-modified-since", lastModified)
					}
				}
			}

			resp, err = t.transport.RoundTrip(req)
			if err == nil && req.Method == "GET" && resp.StatusCode == http.StatusNotModified {
				// Replace the 304 response with the one from cache, but update with some new headers
				headersToMerge := getHopByHopHeaders(resp)
				for _, headerKey := range headersToMerge {
					cachedResp.Header.Set(headerKey, resp.Header.Get(headerKey))
				}
				cachedResp.Status = http.StatusText(http.StatusOK)
				cachedResp.StatusCode = http.StatusOK

				resp = cachedResp
			} else {
				if err != nil || resp.StatusCode != http.StatusOK {
					t.cache.Delete(cacheKey)
				}
			}
		}
	} else {
		reqCacheControl := parseCacheControl(req.Header)
		if _, ok := reqCacheControl["only-if-cached"]; ok {
			resp = newGatewayTimeoutResponse(req)
		} else {
			resp, err = t.transport.RoundTrip(req)
		}
	}
	reqCacheControl := parseCacheControl(req.Header)
	respCacheControl := parseCacheControl(resp.Header)

	if canStore(reqCacheControl, respCacheControl) {
		vary := resp.Header.Get("Vary")
		for _, varyKey := range strings.Split(vary, ",") {
			varyKey = http.CanonicalHeaderKey(strings.Trim(varyKey, " "))
			fakeHeader := "X-Varied-" + varyKey
			reqValue := req.Header.Get(varyKey)
			if reqValue != "" {
				resp.Header.Set(fakeHeader, reqValue)
			}
		}
		respBytes, err := httputil.DumpResponse(resp, true)
		if err == nil {
			// fmt.Println("Set cache", string(respBytes))
			t.cache.Set(cacheKey, respBytes)
		}
	} else {
		t.cache.Delete(cacheKey)
	}
	return resp, nil
}

// getFreshness will return one of fresh/stale/transparent based on the cache-control
// values of the request and the response
//
// fresh indicates the response can be returned
// stale indicates that the response needs validating before it is returned
// transparent indicates the response should not be used to fulfil the request
//
// Because this is only a private cache, 'public' and 'private' in cache-control aren't
// signficant. Similarly, smax-age isn't used.
//
// Limitation: max-stale is not taken into account. It should be.
func getFreshness(respHeaders, reqHeaders http.Header) (freshness int) {
	respCacheControl := parseCacheControl(respHeaders)
	reqCacheControl := parseCacheControl(reqHeaders)
	if _, ok := reqCacheControl["no-cache"]; ok {
		return transparent
	}
	if _, ok := respCacheControl["no-cache"]; ok {
		return stale
	}
	if _, ok := reqCacheControl["only-if-cached"]; ok {
		return fresh
	}
	dateHeader := respHeaders.Get("date")
	if dateHeader != "" {
		date, err := time.Parse(time.RFC1123, dateHeader)
		if err != nil {
			return stale
		}
		currentAge := time.Since(date)
		var lifetime time.Duration
		zeroDuration, _ := time.ParseDuration("0s")
		// If a response includes both an Expires header and a max-age directive,
		// the max-age directive overrides the Expires header, even if the Expires header is more restrictive.
		if maxAge, ok := respCacheControl["max-age"]; ok {
			lifetime, err = time.ParseDuration(maxAge + "s")
			if err != nil {
				lifetime = zeroDuration
			}
		} else {
			expiresHeader := respHeaders.Get("Expires")
			if expiresHeader != "" {
				expires, err := time.Parse(time.RFC1123, expiresHeader)
				if err != nil {
					lifetime = zeroDuration
				} else {
					lifetime = expires.Sub(date)
				}
			}
		}

		if maxAge, ok := reqCacheControl["max-age"]; ok {
			// the client is willing to accept a response whose age is no greater than the specified time in seconds
			lifetime, err = time.ParseDuration(maxAge + "s")
			if err != nil {
				lifetime = zeroDuration
			}
		}
		if minfresh, ok := reqCacheControl["min-fresh"]; ok {
			//  the client wants a response that will still be fresh for at least the specified number of seconds.
			minfreshDuration, err := time.ParseDuration(minfresh + "s")
			if err != nil {
				currentAge = time.Duration(currentAge.Nanoseconds() + minfreshDuration.Nanoseconds())
			}
		}

		if lifetime > currentAge {
			return fresh
		}

	}
	return stale
}

func getHopByHopHeaders(resp *http.Response) []string {
	// These headers are always hop-by-hop
	headers := []string{"connection", "keep-alive", "proxy-authenticate", "proxy-authorization", "te", "trailers", "transfer-encoding", "upgrade"}

	for _, extra := range strings.Split(resp.Header.Get("connection"), ",") {
		// any header listed in connection, if present, is also considered hop-by-hop
		if strings.Trim(extra, " ") != "" {
			headers = append(headers, extra)
		}
	}
	return headers
}

func canStore(reqCacheControl, respCacheControl cacheControl) (canStore bool) {
	if _, ok := respCacheControl["no-store"]; ok {
		return false
	}
	if _, ok := reqCacheControl["no-store"]; ok {
		return false
	}
	return true
}

func responseFromCache(cachedVal []byte, req *http.Request) (*http.Response, error) {
	b := bytes.NewBuffer(cachedVal)
	resp, err := http.ReadResponse(bufio.NewReader(b), req)
	return resp, err
}

func newGatewayTimeoutResponse(req *http.Request) *http.Response {
	var braw bytes.Buffer
	braw.WriteString("HTTP/1.1 504 Gateway Timeout\r\n\r\n")
	resp, err := http.ReadResponse(bufio.NewReader(&braw), req)
	if err != nil {
		panic(err)
	}
	return resp
}

type cacheControl map[string]string

func parseCacheControl(headers http.Header) cacheControl {
	cc := cacheControl{}
	ccHeader := headers.Get("Cache-Control")
	for _, part := range strings.Split(ccHeader, ",") {
		part = strings.Trim(part, " ")
		if part == "" {
			continue
		}
		if strings.ContainsRune(part, '=') {
			keyval := strings.Split(part, "=")
			cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",")
		} else {
			cc[part] = "1"
		}
	}
	return cc
}

// NewMemoryCacheTransport returns a new Transport using the in-memory cache implementation
func NewMemoryCacheTransport() *Transport {
	c := NewMemoryCache()
	t := NewTransport(c)
	return t
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 http

import (
	"net/http"

	"github.com/abbot/go-http-auth"
	"github.com/gorilla/context"
)

type NoAuthenticationBackend struct {
}

func (h *NoAuthenticationBackend) AuthType() string {
	return "NoAuth"
}

func (h *NoAuthenticationBackend) Authenticate(username string, password string) (string, error) {
	return "", nil
}

func (h *NoAuthenticationBackend) Wrap(wrapped auth.AuthenticatedHandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		setTLSHeader(w, r)
		ar := &auth.AuthenticatedRequest{Request: *r, Username: ""}
		copyRequestVars(r, &ar.Request)
		wrapped(w, ar)
		context.Clear(&ar.Request)
	}
}

func NewNoAuthenticationBackend() *NoAuthenticationBackend {
	return &NoAuthenticationBackend{}
}
<commit_msg>http: set the username to 'admin' when using no authentication<commit_after>/*
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 http

import (
	"net/http"

	"github.com/abbot/go-http-auth"
	"github.com/gorilla/context"
)

type NoAuthenticationBackend struct {
}

func (h *NoAuthenticationBackend) AuthType() string {
	return "NoAuth"
}

func (h *NoAuthenticationBackend) Authenticate(username string, password string) (string, error) {
	return "", nil
}

func (h *NoAuthenticationBackend) Wrap(wrapped auth.AuthenticatedHandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		setTLSHeader(w, r)
		ar := &auth.AuthenticatedRequest{Request: *r, Username: "admin"}
		copyRequestVars(r, &ar.Request)
		wrapped(w, ar)
		context.Clear(&ar.Request)
	}
}

func NewNoAuthenticationBackend() *NoAuthenticationBackend {
	return &NoAuthenticationBackend{}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"strings"

	"github.com/cloudfoundry-incubator/auction/auctionrep"
	"github.com/cloudfoundry-incubator/auction/auctiontypes"
	auction_nats_server "github.com/cloudfoundry-incubator/auction/communication/nats/auction_nats_server"
	"github.com/cloudfoundry-incubator/auction/simulation/simulationrepdelegate"
	"github.com/cloudfoundry-incubator/cf-lager"
	"github.com/cloudfoundry/yagnats"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/sigmon"
)

var memoryMB = flag.Int("memoryMB", 100, "total available memory in MB")
var diskMB = flag.Int("diskMB", 100, "total available disk in MB")
var containers = flag.Int("containers", 100, "total available containers")
var repGuid = flag.String("repGuid", "", "rep-guid")
var natsAddrs = flag.String("natsAddrs", "", "nats server addresses")

func main() {
	flag.Parse()

	if *repGuid == "" {
		panic("need rep-guid")
	}

	if *natsAddrs == "" {
		panic("need nats addr")
	}

	repDelegate := simulationrepdelegate.New(auctiontypes.Resources{
		MemoryMB:   *memoryMB,
		DiskMB:     *diskMB,
		Containers: *containers,
	})
	rep := auctionrep.New(*repGuid, repDelegate)

	if *natsAddrs != "" {
		client := yagnats.NewClient()

		clusterInfo := &yagnats.ConnectionCluster{}

		for _, addr := range strings.Split(*natsAddrs, ",") {
			clusterInfo.Members = append(clusterInfo.Members, &yagnats.ConnectionInfo{
				Addr: addr,
			})
		}

		err := client.Connect(clusterInfo)

		if err != nil {
			log.Fatalln("no nats:", err)
		}

		log.Println("starting rep nats server")
		natsRunner := auction_nats_server.New(client, rep, cf_lager.New("repnode").Session(*repGuid))
		server := ifrit.Envoke(natsRunner)
		monitor := ifrit.Envoke(sigmon.New(server))
		fmt.Println("rep node listening")
		err = <-monitor.Wait()
		if err != nil {
			println("NATS SERVER EXITED WITH ERROR: ", err.Error())
		}
	}

	select {}
}
<commit_msg>use new sigmon interface<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"strings"

	"github.com/cloudfoundry-incubator/auction/auctionrep"
	"github.com/cloudfoundry-incubator/auction/auctiontypes"
	auction_nats_server "github.com/cloudfoundry-incubator/auction/communication/nats/auction_nats_server"
	"github.com/cloudfoundry-incubator/auction/simulation/simulationrepdelegate"
	"github.com/cloudfoundry-incubator/cf-lager"
	"github.com/cloudfoundry/yagnats"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/sigmon"
)

var memoryMB = flag.Int("memoryMB", 100, "total available memory in MB")
var diskMB = flag.Int("diskMB", 100, "total available disk in MB")
var containers = flag.Int("containers", 100, "total available containers")
var repGuid = flag.String("repGuid", "", "rep-guid")
var natsAddrs = flag.String("natsAddrs", "", "nats server addresses")

func main() {
	flag.Parse()

	if *repGuid == "" {
		panic("need rep-guid")
	}

	if *natsAddrs == "" {
		panic("need nats addr")
	}

	repDelegate := simulationrepdelegate.New(auctiontypes.Resources{
		MemoryMB:   *memoryMB,
		DiskMB:     *diskMB,
		Containers: *containers,
	})
	rep := auctionrep.New(*repGuid, repDelegate)

	if *natsAddrs != "" {
		client := yagnats.NewClient()

		clusterInfo := &yagnats.ConnectionCluster{}

		for _, addr := range strings.Split(*natsAddrs, ",") {
			clusterInfo.Members = append(clusterInfo.Members, &yagnats.ConnectionInfo{
				Addr: addr,
			})
		}

		err := client.Connect(clusterInfo)

		if err != nil {
			log.Fatalln("no nats:", err)
		}

		log.Println("starting rep nats server")
		natsRunner := auction_nats_server.New(client, rep, cf_lager.New("repnode").Session(*repGuid))
		monitor := ifrit.Envoke(sigmon.New(natsRunner))
		fmt.Println("rep node listening")
		err = <-monitor.Wait()
		if err != nil {
			println("NATS SERVER EXITED WITH ERROR: ", err.Error())
		}
	}

	select {}
}
<|endoftext|>