<commit_before>package main

import (
	"crypto/tls"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"path"
	"sync"
	"syscall"
	"time"
)

import "git.torproject.org/pluggable-transports/goptlib.git"

const ptMethodName = "meek"
const minSessionIdLength = 32
const maxPayloadLength = 0x10000
const turnaroundDeadline = 10 * time.Millisecond
// Passed as ReadTimeout and WriteTimeout when constructing the http.Server.
const readWriteTimeout = 10 * time.Second
const maxSessionStaleness = 120 * time.Second

var ptInfo pt.ServerInfo

// When a connection handler starts, +1 is written to this channel; when it
// ends, -1 is written.
var handlerChan = make(chan int)

func httpBadRequest(w http.ResponseWriter) {
	http.Error(w, "Bad request.\n", http.StatusBadRequest)
}

func httpInternalServerError(w http.ResponseWriter) {
	http.Error(w, "Internal server error.\n", http.StatusInternalServerError)
}

type Session struct {
	Or       *net.TCPConn
	LastSeen time.Time
}

func (session *Session) Touch() {
	session.LastSeen = time.Now()
}

func (session *Session) Expired() bool {
	return time.Since(session.LastSeen) > maxSessionStaleness
}

type State struct {
	sessionMap map[string]*Session
	lock       sync.Mutex
}

func NewState() *State {
	state := new(State)
	state.sessionMap = make(map[string]*Session)
	return state
}

func (state *State) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	handlerChan <- 1
	defer func() {
		handlerChan <- -1
	}()

	switch req.Method {
	case "GET":
		state.Get(w, req)
	case "POST":
		state.Post(w, req)
	default:
		httpBadRequest(w)
	}
}

func (state *State) Get(w http.ResponseWriter, req *http.Request) {
	if path.Clean(req.URL.Path) != "/" {
		http.NotFound(w, req)
		return
	}
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("I’m just a happy little web server.\n"))
}

func (state *State) GetSession(sessionId string, req *http.Request) (*Session, error) {
	state.lock.Lock()
	defer state.lock.Unlock()

	session := state.sessionMap[sessionId]
	if session == nil {
		// log.Printf("unknown session id %q; creating new session", sessionId)

		or, err := pt.DialOr(&ptInfo, req.RemoteAddr, ptMethodName)
		if err != nil {
			return nil, err
		}
		session = &Session{Or: or}
		state.sessionMap[sessionId] = session
	}
	session.Touch()

	return session, nil
}

func transact(session *Session, w http.ResponseWriter, req *http.Request) error {
	body := http.MaxBytesReader(w, req.Body, maxPayloadLength+1)
	_, err := io.Copy(session.Or, body)
	if err != nil {
		return errors.New(fmt.Sprintf("copying body to ORPort: %s", err))
	}

	buf := make([]byte, maxPayloadLength)
	session.Or.SetReadDeadline(time.Now().Add(turnaroundDeadline))
	n, err := session.Or.Read(buf)
	if err != nil {
		if e, ok := err.(net.Error); !ok || !e.Timeout() {
			httpInternalServerError(w)
			return errors.New(fmt.Sprintf("reading from ORPort: %s", err))
		}
	}
	// log.Printf("read %d bytes from ORPort: %q", n, buf[:n])
	n, err = w.Write(buf[:n])
	if err != nil {
		return errors.New(fmt.Sprintf("writing to response: %s", err))
	}
	// log.Printf("wrote %d bytes to response", n)
	return nil
}

func (state *State) Post(w http.ResponseWriter, req *http.Request) {
	sessionId := req.Header.Get("X-Session-Id")
	if len(sessionId) < minSessionIdLength {
		httpBadRequest(w)
		return
	}

	session, err := state.GetSession(sessionId, req)
	if err != nil {
		log.Print(err)
		httpInternalServerError(w)
		return
	}

	err = transact(session, w, req)
	if err != nil {
		log.Print(err)
		state.CloseSession(sessionId)
		return
	}
}

func (state *State) CloseSession(sessionId string) {
	state.lock.Lock()
	defer state.lock.Unlock()
	// log.Printf("closing session %q", sessionId)
	session, ok := state.sessionMap[sessionId]
	if ok {
		session.Or.Close()
		delete(state.sessionMap, sessionId)
	}
}

func (state *State) ExpireSessions() {
	for {
		time.Sleep(maxSessionStaleness / 2)
		state.lock.Lock()
		for sessionId, session := range state.sessionMap {
			if session.Expired() {
				// log.Printf("deleting expired session %q", sessionId)
				session.Or.Close()
				delete(state.sessionMap, sessionId)
			}
		}
		state.lock.Unlock()
	}
}

func listenTLS(network string, addr *net.TCPAddr, certFilename, keyFilename string) (net.Listener, error) {
	// This is cribbed from the source of net/http.Server.ListenAndServeTLS.
	// We have to separate the Listen and Serve parts because we need to
	// report the listening address before entering Serve (which is an
	// infinite loop).
	// https://groups.google.com/d/msg/Golang-nuts/3F1VRCCENp8/3hcayZiwYM8J
	config := &tls.Config{}
	config.NextProtos = []string{"http/1.1"}

	var err error
	config.Certificates = make([]tls.Certificate, 1)
	config.Certificates[0], err = tls.LoadX509KeyPair(certFilename, keyFilename)
	if err != nil {
		return nil, err
	}

	conn, err := net.ListenTCP(network, addr)
	if err != nil {
		return nil, err
	}

	tlsListener := tls.NewListener(conn, config)

	return tlsListener, nil
}

func startListener(network string, addr *net.TCPAddr) (net.Listener, error) {
	ln, err := net.ListenTCP(network, addr)
	if err != nil {
		return nil, err
	}
	log.Printf("listening with plain HTTP on %s", ln.Addr())
	return startServer(ln)
}

func startListenerTLS(network string, addr *net.TCPAddr, certFilename, keyFilename string) (net.Listener, error) {
	ln, err := listenTLS(network, addr, certFilename, keyFilename)
	if err != nil {
		return nil, err
	}
	log.Printf("listening with HTTPS on %s", ln.Addr())
	return startServer(ln)
}

func startServer(ln net.Listener) (net.Listener, error) {
	state := NewState()
	go state.ExpireSessions()
	server := &http.Server{
		Handler: state,
		ReadTimeout: readWriteTimeout,
		WriteTimeout: readWriteTimeout,
	}
	go func() {
		defer ln.Close()
		err := server.Serve(ln)
		if err != nil {
			log.Printf("Error in Serve: %s", err)
		}
	}()
	return ln, nil
}

func main() {
	var disableTLS bool
	var certFilename, keyFilename string
	var logFilename string
	var port int

	flag.BoolVar(&disableTLS, "disable-tls", false, "don't use HTTPS")
	flag.StringVar(&certFilename, "cert", "", "TLS certificate file (required without --disable-tls)")
	flag.StringVar(&keyFilename, "key", "", "TLS private key file (required without --disable-tls)")
	flag.StringVar(&logFilename, "log", "", "name of log file")
	flag.IntVar(&port, "port", 0, "port to listen on")
	flag.Parse()

	if logFilename != "" {
		f, err := os.OpenFile(logFilename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
		if err != nil {
			log.Fatalf("error opening log file: %s", err)
		}
		defer f.Close()
		log.SetOutput(f)
	}

	if disableTLS {
		if certFilename != "" || keyFilename != "" {
			log.Fatalf("The --cert and --key options are not allowed with --disable-tls.\n")
		}
	} else {
		if certFilename == "" || keyFilename == "" {
			log.Fatalf("The --cert and --key options are required.\n")
		}
	}

	var err error
	ptInfo, err = pt.ServerSetup([]string{ptMethodName})
	if err != nil {
		log.Fatalf("error in ServerSetup: %s", err)
	}

	log.Printf("starting")
	listeners := make([]net.Listener, 0)
	for _, bindaddr := range ptInfo.Bindaddrs {
		if port != 0 {
			bindaddr.Addr.Port = port
		}
		switch bindaddr.MethodName {
		case ptMethodName:
			var ln net.Listener
			if disableTLS {
				ln, err = startListener("tcp", bindaddr.Addr)
			} else {
				ln, err = startListenerTLS("tcp", bindaddr.Addr, certFilename, keyFilename)
			}
			if err != nil {
				pt.SmethodError(bindaddr.MethodName, err.Error())
				break
			}
			pt.Smethod(bindaddr.MethodName, ln.Addr())
			listeners = append(listeners, ln)
		default:
			pt.SmethodError(bindaddr.MethodName, "no such method")
		}
	}
	pt.SmethodsDone()

	var numHandlers int = 0
	var sig os.Signal
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	// wait for first signal
	sig = nil
	for sig == nil {
		select {
		case n := <-handlerChan:
			numHandlers += n
		case sig = <-sigChan:
		}
	}
	for _, ln := range listeners {
		ln.Close()
	}

	if sig == syscall.SIGTERM {
		return
	}

	// wait for second signal or no more handlers
	sig = nil
	for sig == nil && numHandlers != 0 {
		select {
		case n := <-handlerChan:
			numHandlers += n
		case sig = <-sigChan:
		}
	}

	log.Printf("done")
}
<commit_msg>turnaroundDeadline is actually a timeout.<commit_after>package main

import (
	"crypto/tls"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"path"
	"sync"
	"syscall"
	"time"
)

import "git.torproject.org/pluggable-transports/goptlib.git"

const ptMethodName = "meek"
const minSessionIdLength = 32
const maxPayloadLength = 0x10000
const turnaroundTimeout = 10 * time.Millisecond
// Passed as ReadTimeout and WriteTimeout when constructing the http.Server.
const readWriteTimeout = 10 * time.Second
const maxSessionStaleness = 120 * time.Second

var ptInfo pt.ServerInfo

// When a connection handler starts, +1 is written to this channel; when it
// ends, -1 is written.
var handlerChan = make(chan int)

func httpBadRequest(w http.ResponseWriter) {
	http.Error(w, "Bad request.\n", http.StatusBadRequest)
}

func httpInternalServerError(w http.ResponseWriter) {
	http.Error(w, "Internal server error.\n", http.StatusInternalServerError)
}

type Session struct {
	Or       *net.TCPConn
	LastSeen time.Time
}

func (session *Session) Touch() {
	session.LastSeen = time.Now()
}

func (session *Session) Expired() bool {
	return time.Since(session.LastSeen) > maxSessionStaleness
}

type State struct {
	sessionMap map[string]*Session
	lock       sync.Mutex
}

func NewState() *State {
	state := new(State)
	state.sessionMap = make(map[string]*Session)
	return state
}

func (state *State) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	handlerChan <- 1
	defer func() {
		handlerChan <- -1
	}()

	switch req.Method {
	case "GET":
		state.Get(w, req)
	case "POST":
		state.Post(w, req)
	default:
		httpBadRequest(w)
	}
}

func (state *State) Get(w http.ResponseWriter, req *http.Request) {
	if path.Clean(req.URL.Path) != "/" {
		http.NotFound(w, req)
		return
	}
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("I’m just a happy little web server.\n"))
}

func (state *State) GetSession(sessionId string, req *http.Request) (*Session, error) {
	state.lock.Lock()
	defer state.lock.Unlock()

	session := state.sessionMap[sessionId]
	if session == nil {
		// log.Printf("unknown session id %q; creating new session", sessionId)

		or, err := pt.DialOr(&ptInfo, req.RemoteAddr, ptMethodName)
		if err != nil {
			return nil, err
		}
		session = &Session{Or: or}
		state.sessionMap[sessionId] = session
	}
	session.Touch()

	return session, nil
}

func transact(session *Session, w http.ResponseWriter, req *http.Request) error {
	body := http.MaxBytesReader(w, req.Body, maxPayloadLength+1)
	_, err := io.Copy(session.Or, body)
	if err != nil {
		return errors.New(fmt.Sprintf("copying body to ORPort: %s", err))
	}

	buf := make([]byte, maxPayloadLength)
	session.Or.SetReadDeadline(time.Now().Add(turnaroundTimeout))
	n, err := session.Or.Read(buf)
	if err != nil {
		if e, ok := err.(net.Error); !ok || !e.Timeout() {
			httpInternalServerError(w)
			return errors.New(fmt.Sprintf("reading from ORPort: %s", err))
		}
	}
	// log.Printf("read %d bytes from ORPort: %q", n, buf[:n])
	n, err = w.Write(buf[:n])
	if err != nil {
		return errors.New(fmt.Sprintf("writing to response: %s", err))
	}
	// log.Printf("wrote %d bytes to response", n)
	return nil
}

func (state *State) Post(w http.ResponseWriter, req *http.Request) {
	sessionId := req.Header.Get("X-Session-Id")
	if len(sessionId) < minSessionIdLength {
		httpBadRequest(w)
		return
	}

	session, err := state.GetSession(sessionId, req)
	if err != nil {
		log.Print(err)
		httpInternalServerError(w)
		return
	}

	err = transact(session, w, req)
	if err != nil {
		log.Print(err)
		state.CloseSession(sessionId)
		return
	}
}

func (state *State) CloseSession(sessionId string) {
	state.lock.Lock()
	defer state.lock.Unlock()
	// log.Printf("closing session %q", sessionId)
	session, ok := state.sessionMap[sessionId]
	if ok {
		session.Or.Close()
		delete(state.sessionMap, sessionId)
	}
}

func (state *State) ExpireSessions() {
	for {
		time.Sleep(maxSessionStaleness / 2)
		state.lock.Lock()
		for sessionId, session := range state.sessionMap {
			if session.Expired() {
				// log.Printf("deleting expired session %q", sessionId)
				session.Or.Close()
				delete(state.sessionMap, sessionId)
			}
		}
		state.lock.Unlock()
	}
}

func listenTLS(network string, addr *net.TCPAddr, certFilename, keyFilename string) (net.Listener, error) {
	// This is cribbed from the source of net/http.Server.ListenAndServeTLS.
	// We have to separate the Listen and Serve parts because we need to
	// report the listening address before entering Serve (which is an
	// infinite loop).
	// https://groups.google.com/d/msg/Golang-nuts/3F1VRCCENp8/3hcayZiwYM8J
	config := &tls.Config{}
	config.NextProtos = []string{"http/1.1"}

	var err error
	config.Certificates = make([]tls.Certificate, 1)
	config.Certificates[0], err = tls.LoadX509KeyPair(certFilename, keyFilename)
	if err != nil {
		return nil, err
	}

	conn, err := net.ListenTCP(network, addr)
	if err != nil {
		return nil, err
	}

	tlsListener := tls.NewListener(conn, config)

	return tlsListener, nil
}

func startListener(network string, addr *net.TCPAddr) (net.Listener, error) {
	ln, err := net.ListenTCP(network, addr)
	if err != nil {
		return nil, err
	}
	log.Printf("listening with plain HTTP on %s", ln.Addr())
	return startServer(ln)
}

func startListenerTLS(network string, addr *net.TCPAddr, certFilename, keyFilename string) (net.Listener, error) {
	ln, err := listenTLS(network, addr, certFilename, keyFilename)
	if err != nil {
		return nil, err
	}
	log.Printf("listening with HTTPS on %s", ln.Addr())
	return startServer(ln)
}

func startServer(ln net.Listener) (net.Listener, error) {
	state := NewState()
	go state.ExpireSessions()
	server := &http.Server{
		Handler: state,
		ReadTimeout: readWriteTimeout,
		WriteTimeout: readWriteTimeout,
	}
	go func() {
		defer ln.Close()
		err := server.Serve(ln)
		if err != nil {
			log.Printf("Error in Serve: %s", err)
		}
	}()
	return ln, nil
}

func main() {
	var disableTLS bool
	var certFilename, keyFilename string
	var logFilename string
	var port int

	flag.BoolVar(&disableTLS, "disable-tls", false, "don't use HTTPS")
	flag.StringVar(&certFilename, "cert", "", "TLS certificate file (required without --disable-tls)")
	flag.StringVar(&keyFilename, "key", "", "TLS private key file (required without --disable-tls)")
	flag.StringVar(&logFilename, "log", "", "name of log file")
	flag.IntVar(&port, "port", 0, "port to listen on")
	flag.Parse()

	if logFilename != "" {
		f, err := os.OpenFile(logFilename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
		if err != nil {
			log.Fatalf("error opening log file: %s", err)
		}
		defer f.Close()
		log.SetOutput(f)
	}

	if disableTLS {
		if certFilename != "" || keyFilename != "" {
			log.Fatalf("The --cert and --key options are not allowed with --disable-tls.\n")
		}
	} else {
		if certFilename == "" || keyFilename == "" {
			log.Fatalf("The --cert and --key options are required.\n")
		}
	}

	var err error
	ptInfo, err = pt.ServerSetup([]string{ptMethodName})
	if err != nil {
		log.Fatalf("error in ServerSetup: %s", err)
	}

	log.Printf("starting")
	listeners := make([]net.Listener, 0)
	for _, bindaddr := range ptInfo.Bindaddrs {
		if port != 0 {
			bindaddr.Addr.Port = port
		}
		switch bindaddr.MethodName {
		case ptMethodName:
			var ln net.Listener
			if disableTLS {
				ln, err = startListener("tcp", bindaddr.Addr)
			} else {
				ln, err = startListenerTLS("tcp", bindaddr.Addr, certFilename, keyFilename)
			}
			if err != nil {
				pt.SmethodError(bindaddr.MethodName, err.Error())
				break
			}
			pt.Smethod(bindaddr.MethodName, ln.Addr())
			listeners = append(listeners, ln)
		default:
			pt.SmethodError(bindaddr.MethodName, "no such method")
		}
	}
	pt.SmethodsDone()

	var numHandlers int = 0
	var sig os.Signal
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	// wait for first signal
	sig = nil
	for sig == nil {
		select {
		case n := <-handlerChan:
			numHandlers += n
		case sig = <-sigChan:
		}
	}
	for _, ln := range listeners {
		ln.Close()
	}

	if sig == syscall.SIGTERM {
		return
	}

	// wait for second signal or no more handlers
	sig = nil
	for sig == nil && numHandlers != 0 {
		select {
		case n := <-handlerChan:
			numHandlers += n
		case sig = <-sigChan:
		}
	}

	log.Printf("done")
}
<|endoftext|>


<commit_before>package aphgrpc

import (
	"fmt"
	"math"
	"net/http"
	"strings"

	"gopkg.in/mgutz/dat.v1/sqlx-runner"

	"github.com/dictyBase/go-genproto/dictybaseapis/api/jsonapi"
	"github.com/fatih/structs"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	"github.com/golang/protobuf/ptypes/any"
	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	context "golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
)

const (
	DefaultPagenum  int64 = 1
	DefaultPagesize int64 = 10
)

// JSONAPIParamsInfo interface should be implement by all grpc-gateway services
// that supports JSON API specifications.
type JSONAPIParamsInfo interface {
	// Relationships that could be included
	AllowedInclude() []string
	// Attribute fields that are allowed
	AllowedFields() []string
	// Filter fields that are allowed
	AllowedFilter() []string
	// FilterToColumns provides mapping between filter and storage columns
	FilterToColumns() map[string]string
	// RequiredAttrs are the mandatory attributes for creating a new resource
	RequiredAttrs() []string
}

// JSONAPIResource interface provides information about HTTP resource. All
// grpc-gateway services that supports JSONAPI should implement this interface.
type JSONAPIResource interface {
	//GetResourceName returns canonical resource name
	GetResourceName() string
	// GetBaseURL returns the base url with the scheme
	GetBaseURL() string
	// GetPrefix returns the path that could be appended to base url
	GetPathPrefix() string
}

// GetTotalPageNum calculate total no of pages from total no. records and page size
func GetTotalPageNum(record, pagesize int64) int64 {
	total := int64(math.Floor(float64(record) / float64(pagesize)))
	if math.Mod(float64(record), float64(pagesize)) > 0 {
		total += 1
	}
	return total
}

// GetPaginatedLinks gets paginated links and total page number for collection resources
func GetPaginatedLinks(rs JSONAPIResource, lastpage, pagenum, pagesize int64) map[string]string {
	var links map[string]string
	links["self"] = GenPaginatedResourceLink(rs, pagenum, pagesize)
	links["first"] = GenPaginatedResourceLink(rs, 1, pagesize)
	if pagenum != 1 {
		links["previous"] = GenPaginatedResourceLink(rs, pagenum-1, pagesize)
	}
	links["last"] = GenPaginatedResourceLink(rs, lastpage, pagesize)
	if pagenum != lastpage {
		links["next"] = GenPaginatedResourceLink(rs, pagenum+1, pagesize)
	}
	return links
}

func GenBaseLink(rs JSONAPIResource) string {
	return fmt.Sprintf(
		"%s/%s",
		strings.Trim(rs.GetBaseURL(), "/"),
		strings.Trim(rs.GetPathPrefix(), "/"),
	)
}

func GenSingleResourceLink(rs JSONAPIResource, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
	)
}

func GenMultiResourceLink(rs JSONAPIResource) string {
	return fmt.Sprintf(
		"%s/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
	)
}

func GenPaginatedResourceLink(rs JSONAPIResource, pagenum, pagesize int64) string {
	return fmt.Sprintf(
		"%s/%s?pagenum=%d&pagesize=%d",
		GenBaseLink(rs),
		rs.GetResourceName(),
		pagenum,
		pagesize,
	)
}

func GenSelfRelationshipLink(rs JSONAPIResource, rel string, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d/relationships/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
		rel,
	)
}

func GenRelatedRelationshipLink(rs JSONAPIResource, rel string, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
		rel,
	)
}

//GetDefinedTagsWithValue check for fields that are initialized and returns a map
//with the tag and their values
func GetDefinedTagsWithValue(i interface{}, key string) map[string]interface{} {
	m := make(map[string]interface{})
	s := structs.New(i)
	for _, f := range s.Fields() {
		if !f.IsZero() {
			m[f.Tag(key)] = f.Value()
		}
	}
	return m
}

//GetDefinedTags check for fields that are initialized and returns a slice of
//their matching tag values
func GetDefinedTags(i interface{}, tag string) []string {
	var v []string
	s := structs.New(i)
	for _, f := range s.Fields() {
		if !f.IsZero() {
			v = append(v, f.Tag(tag))
		}
	}
	return v
}

// HandleCreateResponse modifies the grpc gateway filter which adds the JSON API header and
// modifies the http status response for POST request
func HandleCreateResponse(ctx context.Context, w http.ResponseWriter, resp proto.Message) error {
	w.Header().Set("Content-Type", "application/vnd.api+json")
	md, ok := runtime.ServerMetadataFromContext(ctx)
	if ok {
		trMD := md.TrailerMD
		if _, ok := trMD["method"]; ok {
			switch trMD["method"][0] {
			case "POST":
				w.WriteHeader(http.StatusCreated)
			case "POST_NO_CONTENT":
				w.WriteHeader(http.StatusNoContent)
			}
		}
	}
	return nil
}

// ConvertAllToAny generates slice of arbitrary serialized protocol buffer
// message
func ConvertAllToAny(msg []proto.Message) ([]*any.Any, error) {
	as := make([]*any.Any, len(msg))
	for i, p := range msg {
		pkg, err := ptypes.MarshalAny(p)
		if err != nil {
			return as, err
		}
		as[i] = pkg
	}
	return as, nil
}

type Service struct {
	Dbh             *runner.DB
	PathPrefix      string
	Include         []string
	IncludeStr      string
	FieldsToColumns map[string]string
	FieldsStr       string
	Resource        string
	BaseURL         string
	FilToColumns    map[string]string
	FilterStr       string
	Params          *JSONAPIParams
	ListMethod      bool
	ReqAttrs        []string
}

func (s *Service) RequiredAttrs() []string {
	return s.ReqAttrs
}

func (s *Service) IsListMethod() bool {
	return s.ListMethod
}

func (s *Service) FilterToColumns() map[string]string {
	return s.FilToColumns
}

func (s *Service) AllowedFilter() []string {
	var f []string
	for k, _ := range s.FilterToColumns() {
		f = append(f, k)
	}
	return f
}

func (s *Service) AllowedInclude() []string {
	return s.Include
}

func (s *Service) AllowedFields() []string {
	var f []string
	for k, _ := range s.FieldsToColumns {
		f = append(f, k)
	}
	return f
}

func (s *Service) GetResourceName() string {
	return s.Resource
}

func (s *Service) GetBaseURL() string {
	return s.BaseURL
}

func (s *Service) GetPathPrefix() string {
	return s.PathPrefix
}

func (s *Service) SetBaseURL(ctx context.Context) error {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return ErrRetrieveMetadata
	}
	slice, ok := md["x-forwarded-host"]
	if !ok {
		return ErrXForwardedHost
	}
	s.BaseURL = slice[0]
	return nil
}

func (s *Service) MapFieldsToColumns(fields []string) []string {
	var columns []string
	for _, v := range fields {
		columns = append(columns, s.FieldsToColumns[v])
	}
	return columns
}

func (s *Service) GetCount(table string) (int64, error) {
	var count int64
	err := s.Dbh.Select("COUNT(*)").From(table).QueryScalar(&count)
	return count, err
}

func (s *Service) GetAllFilteredCount(table string) (int64, error) {
	var count int64
	err := s.Dbh.Select("COUNT(*)").
		From(table).
		Scope(
			FilterToWhereClause(s, s.Params.Filters),
			FilterToBindValue(s.Params.Filters)...,
		).QueryScalar(&count)
	return count, err
}

func (s *Service) GetPagination(record, pagenum, pagesize int64) (*jsonapi.PaginationLinks, int64) {
	pages := GetTotalPageNum(record, pagesize)
	pageLinks := GetPaginatedLinks(s, pages, pagenum, pagesize)
	pageType := []string{"self", "last", "first", "previous", "next"}
	params := s.Params
	switch {
	case params.HasFields && params.HasInclude && params.HasFilter:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&fields=%s&include=%s&filter=%s", s.FieldsStr, s.IncludeStr, s.FilterStr)
			}
		}
	case params.HasFields && params.HasInclude:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
			}
		}
	case params.HasFields && params.HasFilter:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&fields=%s&filter=%s", s.FieldsStr, s.FilterStr)
			}
		}
	case params.HasInclude && params.HasFilter:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&include=%s&filter=%s", s.IncludeStr, s.FilterStr)
			}
		}
	case params.HasInclude:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&include=%s", s.IncludeStr)
			}
		}
	case params.HasFilter:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&filter=%s", s.FilterStr)
			}
		}
	case params.HasFields:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&fields=%s", s.FieldsStr)
			}
		}
	}
	jsapiLinks := &jsonapi.PaginationLinks{
		Self:  pageLinks["self"],
		Last:  pageLinks["last"],
		First: pageLinks["first"],
	}
	if _, ok := pageLinks["previous"]; ok {
		jsapiLinks.Prev = pageLinks["previous"]
	}
	if _, ok := pageLinks["next"]; ok {
		jsapiLinks.Next = pageLinks["next"]
	}
	return jsapiLinks, pages
}

func (s *Service) GenCollResourceSelfLink() string {
	link := GenMultiResourceLink(s)
	params := s.Params
	switch {
	case params.HasFields && params.HasFilter && params.HasInclude:
		link += fmt.Sprintf("?fields=%s&include=%s&filter=%s", s.FieldsStr, s.IncludeStr, s.FilterStr)
	case params.HasFields && params.HasFilter:
		link += fmt.Sprintf("?fields=%s&filter=%s", s.FieldsStr, s.FilterStr)
	case params.HasFields && params.HasInclude:
		link += fmt.Sprintf("?fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
	case params.HasFilter && params.HasInclude:
		link += fmt.Sprintf("?filter=%s&include=%s", s.FilterStr, s.IncludeStr)
	case params.HasInclude:
		link += fmt.Sprintf("?include=%s", s.IncludeStr)
	case params.HasFilter:
		link += fmt.Sprintf("?filter=%s", s.FilterStr)
	case params.HasFields:
		link += fmt.Sprintf("?fields=%s", s.FieldsStr)
	}
	return link
}

func (s *Service) GenResourceSelfLink(id int64) string {
	links := GenSingleResourceLink(s, id)
	if !s.IsListMethod() && s.Params != nil {
		params := s.Params
		switch {
		case params.HasFields && params.HasInclude:
			links += fmt.Sprintf("?fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
		case params.HasFields:
			links += fmt.Sprintf("?fields=%s", s.FieldsStr)
		case params.HasInclude:
			links += fmt.Sprintf("?include=%s", s.IncludeStr)
		}
	}
	return links
}
<commit_msg>Added nullstring to string converter<commit_after>package aphgrpc

import (
	"fmt"
	"math"
	"net/http"
	"strings"

	"gopkg.in/mgutz/dat.v1"
	"gopkg.in/mgutz/dat.v1/sqlx-runner"

	"github.com/dictyBase/go-genproto/dictybaseapis/api/jsonapi"
	"github.com/fatih/structs"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	"github.com/golang/protobuf/ptypes/any"
	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	context "golang.org/x/net/context"
	"google.golang.org/grpc/metadata"
)

const (
	DefaultPagenum  int64 = 1
	DefaultPagesize int64 = 10
)

// JSONAPIParamsInfo interface should be implement by all grpc-gateway services
// that supports JSON API specifications.
type JSONAPIParamsInfo interface {
	// Relationships that could be included
	AllowedInclude() []string
	// Attribute fields that are allowed
	AllowedFields() []string
	// Filter fields that are allowed
	AllowedFilter() []string
	// FilterToColumns provides mapping between filter and storage columns
	FilterToColumns() map[string]string
	// RequiredAttrs are the mandatory attributes for creating a new resource
	RequiredAttrs() []string
}

// JSONAPIResource interface provides information about HTTP resource. All
// grpc-gateway services that supports JSONAPI should implement this interface.
type JSONAPIResource interface {
	//GetResourceName returns canonical resource name
	GetResourceName() string
	// GetBaseURL returns the base url with the scheme
	GetBaseURL() string
	// GetPrefix returns the path that could be appended to base url
	GetPathPrefix() string
}

func NullToString(s dat.NullString) string {
	if s.Valid {
		return s.String
	}
	return ""
}

// GetTotalPageNum calculate total no of pages from total no. records and page size
func GetTotalPageNum(record, pagesize int64) int64 {
	total := int64(math.Floor(float64(record) / float64(pagesize)))
	if math.Mod(float64(record), float64(pagesize)) > 0 {
		total += 1
	}
	return total
}

// GetPaginatedLinks gets paginated links and total page number for collection resources
func GetPaginatedLinks(rs JSONAPIResource, lastpage, pagenum, pagesize int64) map[string]string {
	var links map[string]string
	links["self"] = GenPaginatedResourceLink(rs, pagenum, pagesize)
	links["first"] = GenPaginatedResourceLink(rs, 1, pagesize)
	if pagenum != 1 {
		links["previous"] = GenPaginatedResourceLink(rs, pagenum-1, pagesize)
	}
	links["last"] = GenPaginatedResourceLink(rs, lastpage, pagesize)
	if pagenum != lastpage {
		links["next"] = GenPaginatedResourceLink(rs, pagenum+1, pagesize)
	}
	return links
}

func GenBaseLink(rs JSONAPIResource) string {
	return fmt.Sprintf(
		"%s/%s",
		strings.Trim(rs.GetBaseURL(), "/"),
		strings.Trim(rs.GetPathPrefix(), "/"),
	)
}

func GenSingleResourceLink(rs JSONAPIResource, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
	)
}

func GenMultiResourceLink(rs JSONAPIResource) string {
	return fmt.Sprintf(
		"%s/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
	)
}

func GenPaginatedResourceLink(rs JSONAPIResource, pagenum, pagesize int64) string {
	return fmt.Sprintf(
		"%s/%s?pagenum=%d&pagesize=%d",
		GenBaseLink(rs),
		rs.GetResourceName(),
		pagenum,
		pagesize,
	)
}

func GenSelfRelationshipLink(rs JSONAPIResource, rel string, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d/relationships/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
		rel,
	)
}

func GenRelatedRelationshipLink(rs JSONAPIResource, rel string, id int64) string {
	return fmt.Sprintf(
		"%s/%s/%d/%s",
		GenBaseLink(rs),
		rs.GetResourceName(),
		id,
		rel,
	)
}

//GetDefinedTagsWithValue check for fields that are initialized and returns a map
//with the tag and their values
func GetDefinedTagsWithValue(i interface{}, key string) map[string]interface{} {
	m := make(map[string]interface{})
	s := structs.New(i)
	for _, f := range s.Fields() {
		if !f.IsZero() {
			m[f.Tag(key)] = f.Value()
		}
	}
	return m
}

//GetDefinedTags check for fields that are initialized and returns a slice of
//their matching tag values
func GetDefinedTags(i interface{}, tag string) []string {
	var v []string
	s := structs.New(i)
	for _, f := range s.Fields() {
		if !f.IsZero() {
			v = append(v, f.Tag(tag))
		}
	}
	return v
}

// HandleCreateResponse modifies the grpc gateway filter which adds the JSON API header and
// modifies the http status response for POST request
func HandleCreateResponse(ctx context.Context, w http.ResponseWriter, resp proto.Message) error {
	w.Header().Set("Content-Type", "application/vnd.api+json")
	md, ok := runtime.ServerMetadataFromContext(ctx)
	if ok {
		trMD := md.TrailerMD
		if _, ok := trMD["method"]; ok {
			switch trMD["method"][0] {
			case "POST":
				w.WriteHeader(http.StatusCreated)
			case "POST_NO_CONTENT":
				w.WriteHeader(http.StatusNoContent)
			}
		}
	}
	return nil
}

// ConvertAllToAny generates slice of arbitrary serialized protocol buffer
// message
func ConvertAllToAny(msg []proto.Message) ([]*any.Any, error) {
	as := make([]*any.Any, len(msg))
	for i, p := range msg {
		pkg, err := ptypes.MarshalAny(p)
		if err != nil {
			return as, err
		}
		as[i] = pkg
	}
	return as, nil
}

type Service struct {
	Dbh             *runner.DB
	PathPrefix      string
	Include         []string
	IncludeStr      string
	FieldsToColumns map[string]string
	FieldsStr       string
	Resource        string
	BaseURL         string
	FilToColumns    map[string]string
	FilterStr       string
	Params          *JSONAPIParams
	ListMethod      bool
	ReqAttrs        []string
}

func (s *Service) RequiredAttrs() []string {
	return s.ReqAttrs
}

func (s *Service) IsListMethod() bool {
	return s.ListMethod
}

func (s *Service) FilterToColumns() map[string]string {
	return s.FilToColumns
}

func (s *Service) AllowedFilter() []string {
	var f []string
	for k, _ := range s.FilterToColumns() {
		f = append(f, k)
	}
	return f
}

func (s *Service) AllowedInclude() []string {
	return s.Include
}

func (s *Service) AllowedFields() []string {
	var f []string
	for k, _ := range s.FieldsToColumns {
		f = append(f, k)
	}
	return f
}

func (s *Service) GetResourceName() string {
	return s.Resource
}

func (s *Service) GetBaseURL() string {
	return s.BaseURL
}

func (s *Service) GetPathPrefix() string {
	return s.PathPrefix
}

func (s *Service) SetBaseURL(ctx context.Context) error {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return ErrRetrieveMetadata
	}
	slice, ok := md["x-forwarded-host"]
	if !ok {
		return ErrXForwardedHost
	}
	s.BaseURL = slice[0]
	return nil
}

func (s *Service) MapFieldsToColumns(fields []string) []string {
	var columns []string
	for _, v := range fields {
		columns = append(columns, s.FieldsToColumns[v])
	}
	return columns
}

func (s *Service) GetCount(table string) (int64, error) {
	var count int64
	err := s.Dbh.Select("COUNT(*)").From(table).QueryScalar(&count)
	return count, err
}

func (s *Service) GetAllFilteredCount(table string) (int64, error) {
	var count int64
	err := s.Dbh.Select("COUNT(*)").
		From(table).
		Scope(
			FilterToWhereClause(s, s.Params.Filters),
			FilterToBindValue(s.Params.Filters)...,
		).QueryScalar(&count)
	return count, err
}

func (s *Service) GetPagination(record, pagenum, pagesize int64) (*jsonapi.PaginationLinks, int64) {
	pages := GetTotalPageNum(record, pagesize)
	pageLinks := GetPaginatedLinks(s, pages, pagenum, pagesize)
	pageType := []string{"self", "last", "first", "previous", "next"}
	params := s.Params
	switch {
	case params.HasFields && params.HasInclude && params.HasFilter:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&fields=%s&include=%s&filter=%s", s.FieldsStr, s.IncludeStr, s.FilterStr)
			}
		}
	case params.HasFields && params.HasInclude:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
			}
		}
	case params.HasFields && params.HasFilter:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&fields=%s&filter=%s", s.FieldsStr, s.FilterStr)
			}
		}
	case params.HasInclude && params.HasFilter:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&include=%s&filter=%s", s.IncludeStr, s.FilterStr)
			}
		}
	case params.HasInclude:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&include=%s", s.IncludeStr)
			}
		}
	case params.HasFilter:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&filter=%s", s.FilterStr)
			}
		}
	case params.HasFields:
		for _, v := range pageType {
			if _, ok := pageLinks[v]; ok {
				pageLinks[v] += fmt.Sprintf("&fields=%s", s.FieldsStr)
			}
		}
	}
	jsapiLinks := &jsonapi.PaginationLinks{
		Self:  pageLinks["self"],
		Last:  pageLinks["last"],
		First: pageLinks["first"],
	}
	if _, ok := pageLinks["previous"]; ok {
		jsapiLinks.Prev = pageLinks["previous"]
	}
	if _, ok := pageLinks["next"]; ok {
		jsapiLinks.Next = pageLinks["next"]
	}
	return jsapiLinks, pages
}

func (s *Service) GenCollResourceSelfLink() string {
	link := GenMultiResourceLink(s)
	params := s.Params
	switch {
	case params.HasFields && params.HasFilter && params.HasInclude:
		link += fmt.Sprintf("?fields=%s&include=%s&filter=%s", s.FieldsStr, s.IncludeStr, s.FilterStr)
	case params.HasFields && params.HasFilter:
		link += fmt.Sprintf("?fields=%s&filter=%s", s.FieldsStr, s.FilterStr)
	case params.HasFields && params.HasInclude:
		link += fmt.Sprintf("?fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
	case params.HasFilter && params.HasInclude:
		link += fmt.Sprintf("?filter=%s&include=%s", s.FilterStr, s.IncludeStr)
	case params.HasInclude:
		link += fmt.Sprintf("?include=%s", s.IncludeStr)
	case params.HasFilter:
		link += fmt.Sprintf("?filter=%s", s.FilterStr)
	case params.HasFields:
		link += fmt.Sprintf("?fields=%s", s.FieldsStr)
	}
	return link
}

func (s *Service) GenResourceSelfLink(id int64) string {
	links := GenSingleResourceLink(s, id)
	if !s.IsListMethod() && s.Params != nil {
		params := s.Params
		switch {
		case params.HasFields && params.HasInclude:
			links += fmt.Sprintf("?fields=%s&include=%s", s.FieldsStr, s.IncludeStr)
		case params.HasFields:
			links += fmt.Sprintf("?fields=%s", s.FieldsStr)
		case params.HasInclude:
			links += fmt.Sprintf("?include=%s", s.IncludeStr)
		}
	}
	return links
}
<|endoftext|>


<commit_before>//
// boltdbweb is a webserver base GUI for interacting with BoltDB databases.
//
// For authorship see https://github.com/evnix/boltdbweb
// MIT license is included in repository
//
package main

//go:generate go-bindata-assetfs -o web_static.go web/...

import (
	"flag"
	"fmt"
	"os"
	"path"
	"time"

	"github.com/evnix/boltdbweb/web"
	"github.com/gin-gonic/gin"

	log "github.com/Sirupsen/logrus"
	"github.com/boltdb/bolt"
)

const version = "v0.0.0"

var (
	showHelp   bool
	db         *bolt.DB
	dbName     string
	port       string
	staticPath string
)

func usage(appName, version string) {
	fmt.Printf("Usage: %s [OPTIONS] [DB_NAME]", appName)
	fmt.Printf("\nOPTIONS:\n\n")
	flag.VisitAll(func(f *flag.Flag) {
		if len(f.Name) > 1 {
			fmt.Printf("    -%s, -%s\t%s\n", f.Name[0:1], f.Name, f.Usage)
		}
	})
	fmt.Printf("\n\nVersion %s\n", version)
}

func init() {
	// Read the static path from the environment if set.
	dbName = os.Getenv("BOLTDBWEB_DB_NAME")
	port = os.Getenv("BOLTDBWEB_PORT")
	// Use default values if environment not set.
	if port == "" {
		port = "8080"
	}
	// Setup for command line processing
	flag.BoolVar(&showHelp, "h", false, "display help")
	flag.BoolVar(&showHelp, "help", false, "display help")
	flag.StringVar(&dbName, "d", dbName, "Name of the database")
	flag.StringVar(&dbName, "db-name", dbName, "Name of the database")
	flag.StringVar(&port, "p", port, "Port for the web-ui")
	flag.StringVar(&port, "port", port, "Port for the web-ui")
}

func main() {
	appName := path.Base(os.Args[0])
	flag.Parse()
	args := flag.Args()

	if showHelp == true {
		usage(appName, version)
		os.Exit(0)
	}

	// If non-flag options are included assume bolt db is specified.
	if len(args) > 0 {
		dbName = args[0]
	}

	if dbName == "" {
		usage(appName, version)
		log.Printf("\nERROR: Missing boltdb name\n")
		os.Exit(1)
	}

	fmt.Print(" ")
	log.Info("starting boltdb-browser..")

	var err error
	db, err = bolt.Open(dbName, 0600, &bolt.Options{Timeout: 2 * time.Second})
	boltbrowserweb.Db = db

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// OK, we should be ready to define/run web server safely.
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})

	r.GET("/", boltbrowserweb.Index)

	r.GET("/buckets", boltbrowserweb.Buckets)
	r.POST("/createBucket", boltbrowserweb.CreateBucket)
	r.POST("/put", boltbrowserweb.Put)
	r.POST("/get", boltbrowserweb.Get)
	r.POST("/deleteKey", boltbrowserweb.DeleteKey)
	r.POST("/deleteBucket", boltbrowserweb.DeleteBucket)
	r.POST("/prefixScan", boltbrowserweb.PrefixScan)

	r.StaticFS("/web", assetFS())

	r.Run(":" + port)
}
<commit_msg>lowercased module path<commit_after>//
// boltdbweb is a webserver base GUI for interacting with BoltDB databases.
//
// For authorship see https://github.com/evnix/boltdbweb
// MIT license is included in repository
//
package main

//go:generate go-bindata-assetfs -o web_static.go web/...

import (
	"flag"
	"fmt"
	"os"
	"path"
	"time"

	"github.com/evnix/boltdbweb/web"
	"github.com/gin-gonic/gin"

	log "github.com/sirupsen/logrus"
	"github.com/boltdb/bolt"
)

const version = "v0.0.0"

var (
	showHelp   bool
	db         *bolt.DB
	dbName     string
	port       string
	staticPath string
)

func usage(appName, version string) {
	fmt.Printf("Usage: %s [OPTIONS] [DB_NAME]", appName)
	fmt.Printf("\nOPTIONS:\n\n")
	flag.VisitAll(func(f *flag.Flag) {
		if len(f.Name) > 1 {
			fmt.Printf("    -%s, -%s\t%s\n", f.Name[0:1], f.Name, f.Usage)
		}
	})
	fmt.Printf("\n\nVersion %s\n", version)
}

func init() {
	// Read the static path from the environment if set.
	dbName = os.Getenv("BOLTDBWEB_DB_NAME")
	port = os.Getenv("BOLTDBWEB_PORT")
	// Use default values if environment not set.
	if port == "" {
		port = "8080"
	}
	// Setup for command line processing
	flag.BoolVar(&showHelp, "h", false, "display help")
	flag.BoolVar(&showHelp, "help", false, "display help")
	flag.StringVar(&dbName, "d", dbName, "Name of the database")
	flag.StringVar(&dbName, "db-name", dbName, "Name of the database")
	flag.StringVar(&port, "p", port, "Port for the web-ui")
	flag.StringVar(&port, "port", port, "Port for the web-ui")
}

func main() {
	appName := path.Base(os.Args[0])
	flag.Parse()
	args := flag.Args()

	if showHelp == true {
		usage(appName, version)
		os.Exit(0)
	}

	// If non-flag options are included assume bolt db is specified.
	if len(args) > 0 {
		dbName = args[0]
	}

	if dbName == "" {
		usage(appName, version)
		log.Printf("\nERROR: Missing boltdb name\n")
		os.Exit(1)
	}

	fmt.Print(" ")
	log.Info("starting boltdb-browser..")

	var err error
	db, err = bolt.Open(dbName, 0600, &bolt.Options{Timeout: 2 * time.Second})
	boltbrowserweb.Db = db

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// OK, we should be ready to define/run web server safely.
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})

	r.GET("/", boltbrowserweb.Index)

	r.GET("/buckets", boltbrowserweb.Buckets)
	r.POST("/createBucket", boltbrowserweb.CreateBucket)
	r.POST("/put", boltbrowserweb.Put)
	r.POST("/get", boltbrowserweb.Get)
	r.POST("/deleteKey", boltbrowserweb.DeleteKey)
	r.POST("/deleteBucket", boltbrowserweb.DeleteBucket)
	r.POST("/prefixScan", boltbrowserweb.PrefixScan)

	r.StaticFS("/web", assetFS())

	r.Run(":" + port)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
)

func main() {
	// flags
	rawHostAddress := flag.String("host", "127.0.0.1", "Enter an address to hit for this check")
	rawPortNumber := flag.Int("port", 9200, "What port is ES running on?")

	// say, what's in those flags? LETTUCE PARSING
	flag.Parse()

	// if it.IsLegit? { return congratulations }
	validPort, err := validatePort(*rawPortNumber)
	if !validPort {
		fmt.Println("Try using a valid port number between 1 and 65535. Thrown error:", err)
		os.Exit(2)
	}

	// we're going to start off simple, just curling address:port/_cluster/health
	// which gives us a little info that's fairly indicative of general node/cluster health

	curlAddress := fmt.Sprintf("http://%v:%v/_cluster/health", *rawHostAddress, *rawPortNumber)

	jsonBody := curlAndReturn(curlAddress)

	// set up the struct to parse the JSON
	type Elascheck struct {
		Status           string `json:"status"`
		Numberofnodes    int    `json:"number_of_nodes"`
		Unassignedshards int    `json:"unassigned_shards"`
	}
	// and now we have a way of accessing it once we marshal the data
	var elascheck Elascheck

	marshalerr := json.Unmarshal(jsonBody, &elascheck)
	if marshalerr != nil {
		fmt.Println("You messed up bad:", marshalerr)
	}
	fmt.Println("status output:", elascheck.Status)
	fmt.Println("number of nodes:", elascheck.Numberofnodes)
	fmt.Println("and finally unassigned shards:", elascheck.Unassignedshards)

	if strings.ToLower(elascheck.Status) == "green" && elascheck.Unassignedshards == 0 {
		fmt.Println("OK - all is clear")
		os.Exit(0)
	} else {
		fmt.Println("Critical - something is messed up") // some overcomplicated if/else if or case statement here
		os.Exit(2)
	}
}

func curlAndReturn(target string) []byte {
	esCurlReq, esCurlErr := http.NewRequest("GET", target, nil)
	if esCurlErr != nil {
		fmt.Println(esCurlErr) // really I don't care, but you're welcome to uncomment
	}
	esCurlRes, _ := http.DefaultClient.Do(esCurlReq)
	rawEsCurlBody, _ := ioutil.ReadAll(esCurlRes.Body)

	defer esCurlRes.Body.Close()

	return rawEsCurlBody
}

func validatePort(port int) (bool, error) {
	if port < 1 || port > 65535 {
		return false, errors.New("Port out of range")

	}

	return true, errors.New("no errors")

}
<commit_msg>useless-ish file just to explore how to do this.<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
)

func main() {
	// flags
	rawHostAddress := flag.String("host", "127.0.0.1", "Enter an address to hit for this check")
	rawPortNumber := flag.Int("port", 9200, "What port is ES running on?")

	// say, what's in those flags? LETTUCE PARSING
	flag.Parse()

	// if it.IsLegit? { return congratulations }
	validPort, err := validatePort(*rawPortNumber)
	if !validPort {
		fmt.Println("Try using a valid port number between 1 and 65535. Thrown error:", err)
		os.Exit(2)
	}

	// we're going to start off simple, just curling address:port/_cluster/health
	// which gives us a little info that's fairly indicative of general node/cluster health

	curlAddress := fmt.Sprintf("http://%v:%v/_cluster/health", *rawHostAddress, *rawPortNumber)

	jsonBody := curlAndReturn(curlAddress)

	// set up the struct to parse the JSON
	// changing the left value arbitrarily just to demonstrate to myself
	// how unbound that is to the `json:"fieldname"` value. NBD, this should have been obv to me
	type Elascheck struct {
		Stat     string `json:"status"`
		Numnodes int    `json:"number_of_nodes"`
		Unshards int    `json:"unassigned_shards"`
	}
	// and now we have a way of accessing it once we marshal the data
	var elascheck Elascheck

	marshalerr := json.Unmarshal(jsonBody, &elascheck)
	if marshalerr != nil {
		fmt.Println("You messed up bad:", marshalerr)
	}
	fmt.Println("status output:", elascheck.Stat)
	fmt.Println("number of nodes:", elascheck.Numnodes)
	fmt.Println("and finally unassigned shards:", elascheck.Unshards)

	if strings.ToLower(elascheck.Stat) == "green" && elascheck.Unshards == 0 {
		fmt.Println("OK - all is clear")
		os.Exit(0)
	} else {
		fmt.Println("Critical - something is messed up") // some overcomplicated if/else if or case statement here
		os.Exit(2)
	}
}

func curlAndReturn(target string) []byte {
	esCurlReq, esCurlErr := http.NewRequest("GET", target, nil)
	if esCurlErr != nil {
		fmt.Println(esCurlErr) // really I don't care, but you're welcome to uncomment
	}
	esCurlRes, _ := http.DefaultClient.Do(esCurlReq)
	rawEsCurlBody, _ := ioutil.ReadAll(esCurlRes.Body)

	defer esCurlRes.Body.Close()

	return rawEsCurlBody
}

func validatePort(port int) (bool, error) {
	if port < 1 || port > 65535 {
		return false, errors.New("Port out of range")

	}

	return true, errors.New("no errors")

}
<|endoftext|>


<commit_before>package imageprocessor

import (
    "github.com/Imgur/mandible/uploadedfile"
    "testing"
    "errors"
    "os"
    "io/ioutil"
    "io"
)

func TestStandardOCR(t *testing.T) {
    image, err := getUploadedFileObject()
    if err != nil {
        t.Fatalf("Could not initialize standard OCR test")
    }

    ocrStratagy := StandardOCRStratagy()
    ocrStratagy.Process(image)

    if image.GetOCRText() != "hello"  {
        t.Fatalf("Did not get proper standard OCR text back %s != hello", image.GetOCRText())
    }
}

func TestDuelOCR(t *testing.T) {
    image, err := getUploadedFileObject()
    if err != nil {
        t.Fatalf("Could not initialize standard OCR test")
    }

    ocrStratagy := DuelOCRStratagy()
    ocrStratagy.Process(image)

    if image.GetOCRText() != "hello"  {
        t.Fatalf("Did not get proper Duel OCR text back %s != hello", image.GetOCRText())
    }
}

func getUploadedFileObject() (*uploadedfile.UploadedFile, error) {
    filename, err := copyTestImage("testdata/ocrtestimage.png")
    if err != nil {
        return nil, err
    }

    image, err := uploadedfile.NewUploadedFile("ocrtestimage.png", filename, nil)
    if err != nil {
        return nil, errors.New("Could not initialize standard OCR test")
    }

    return image, nil
}

func copyTestImage(filename string) (string, error) {
    uploadFile, err := os.Open(filename)
    if err != nil {
        return "", err
    }
    defer uploadFile.Close()

    tmpFile, err := ioutil.TempFile(os.TempDir(), "image")
    if err != nil {
        return "", errors.New("Unable to write to /tmp")
    }
    defer tmpFile.Close()

    _, err = io.Copy(tmpFile, uploadFile)
    if err != nil {
        return "", err
    }

    return tmpFile.Name(), nil
}<commit_msg>go imports<commit_after>package imageprocessor

import (
	"errors"
	"io"
	"io/ioutil"
	"os"
	"testing"

	"github.com/Imgur/mandible/uploadedfile"
)

func TestStandardOCR(t *testing.T) {
	image, err := getUploadedFileObject()
	if err != nil {
		t.Fatalf("Could not initialize standard OCR test")
	}

	ocrStratagy := StandardOCRStratagy()
	ocrStratagy.Process(image)

	if image.GetOCRText() != "hello" {
		t.Fatalf("Did not get proper standard OCR text back %s != hello", image.GetOCRText())
	}
}

func TestDuelOCR(t *testing.T) {
	image, err := getUploadedFileObject()
	if err != nil {
		t.Fatalf("Could not initialize standard OCR test")
	}

	ocrStratagy := DuelOCRStratagy()
	ocrStratagy.Process(image)

	if image.GetOCRText() != "hello" {
		t.Fatalf("Did not get proper Duel OCR text back %s != hello", image.GetOCRText())
	}
}

func getUploadedFileObject() (*uploadedfile.UploadedFile, error) {
	filename, err := copyTestImage("testdata/ocrtestimage.png")
	if err != nil {
		return nil, err
	}

	image, err := uploadedfile.NewUploadedFile("ocrtestimage.png", filename, nil)
	if err != nil {
		return nil, errors.New("Could not initialize standard OCR test")
	}

	return image, nil
}

func copyTestImage(filename string) (string, error) {
	uploadFile, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer uploadFile.Close()

	tmpFile, err := ioutil.TempFile(os.TempDir(), "image")
	if err != nil {
		return "", errors.New("Unable to write to /tmp")
	}
	defer tmpFile.Close()

	_, err = io.Copy(tmpFile, uploadFile)
	if err != nil {
		return "", err
	}

	return tmpFile.Name(), nil
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pflag

import (
	"bytes"
	"fmt"
	"strconv"
	"testing"
)

// This value can be a boolean ("true", "false") or "maybe"
type triStateValue int

const (
	triStateFalse triStateValue = 0
	triStateTrue  triStateValue = 1
	triStateMaybe triStateValue = 2
)

const strTriStateMaybe = "maybe"

func (v *triStateValue) IsBoolFlag() bool {
	return true
}

func (v *triStateValue) Get() interface{} {
	return triStateValue(*v)
}

func (v *triStateValue) Set(s string) error {
	if s == strTriStateMaybe {
		*v = triStateMaybe
		return nil
	}
	boolVal, err := strconv.ParseBool(s)
	if boolVal {
		*v = triStateTrue
	} else {
		*v = triStateFalse
	}
	return err
}

func (v *triStateValue) String() string {
	if *v == triStateMaybe {
		return strTriStateMaybe
	}
	return fmt.Sprintf("%v", bool(*v == triStateTrue))
}

// The type of the flag as required by the pflag.Value interface
func (v *triStateValue) Type() string {
	return "version"
}

func setUpFlagSet(tristate *triStateValue) *FlagSet {
	f := NewFlagSet("test", ContinueOnError)
	*tristate = triStateFalse
	flag := f.VarPF(tristate, "tristate", "t", "tristate value (true, maybe or false)")
	flag.NoOptDefVal = "true"
	return f
}

func TestExplicitTrue(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"--tristate=true"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateTrue {
		t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
	}
}

func TestImplicitTrue(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"--tristate"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateTrue {
		t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
	}
}

func TestShortFlag(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"-t"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateTrue {
		t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
	}
}

func TestShortFlagExtraArgument(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	// The"maybe"turns into an arg, since short boolean options will only do true/false
	err := f.Parse([]string{"-t", "maybe"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateTrue {
		t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
	}
	args := f.Args()
	if len(args) != 1 || args[0] != "maybe" {
		t.Fatal("expected an extra 'maybe' argument to stick around")
	}
}

func TestExplicitMaybe(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"--tristate=maybe"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateMaybe {
		t.Fatal("expected", triStateMaybe, "(triStateMaybe) but got", tristate, "instead")
	}
}

func TestExplicitFalse(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"--tristate=false"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateFalse {
		t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
	}
}

func TestImplicitFalse(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateFalse {
		t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
	}
}

func TestInvalidValue(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	var buf bytes.Buffer
	f.SetOutput(&buf)
	err := f.Parse([]string{"--tristate=invalid"})
	if err == nil {
		t.Fatal("expected an error but did not get any, tristate has value", tristate)
	}
}

func TestBoolP(t *testing.T) {
	b := BoolP("bool", "b", false, "bool value in CommandLine")
	c := BoolP("c", "c", false, "other bool value")
	args := []string{"--bool"}
	if err := CommandLine.Parse(args); err != nil {
		t.Error("expected no error, got ", err)
	}
	if *b != true {
		t.Errorf("expected b=true got b=%s", b)
	}
	if *c != false {
		t.Errorf("expect c=false got c=%s", c)
	}
}
<commit_msg>Fix verbs for *bool in bool test<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pflag

import (
	"bytes"
	"fmt"
	"strconv"
	"testing"
)

// This value can be a boolean ("true", "false") or "maybe"
type triStateValue int

const (
	triStateFalse triStateValue = 0
	triStateTrue  triStateValue = 1
	triStateMaybe triStateValue = 2
)

const strTriStateMaybe = "maybe"

func (v *triStateValue) IsBoolFlag() bool {
	return true
}

func (v *triStateValue) Get() interface{} {
	return triStateValue(*v)
}

func (v *triStateValue) Set(s string) error {
	if s == strTriStateMaybe {
		*v = triStateMaybe
		return nil
	}
	boolVal, err := strconv.ParseBool(s)
	if boolVal {
		*v = triStateTrue
	} else {
		*v = triStateFalse
	}
	return err
}

func (v *triStateValue) String() string {
	if *v == triStateMaybe {
		return strTriStateMaybe
	}
	return fmt.Sprintf("%v", bool(*v == triStateTrue))
}

// The type of the flag as required by the pflag.Value interface
func (v *triStateValue) Type() string {
	return "version"
}

func setUpFlagSet(tristate *triStateValue) *FlagSet {
	f := NewFlagSet("test", ContinueOnError)
	*tristate = triStateFalse
	flag := f.VarPF(tristate, "tristate", "t", "tristate value (true, maybe or false)")
	flag.NoOptDefVal = "true"
	return f
}

func TestExplicitTrue(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"--tristate=true"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateTrue {
		t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
	}
}

func TestImplicitTrue(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"--tristate"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateTrue {
		t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
	}
}

func TestShortFlag(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"-t"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateTrue {
		t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
	}
}

func TestShortFlagExtraArgument(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	// The"maybe"turns into an arg, since short boolean options will only do true/false
	err := f.Parse([]string{"-t", "maybe"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateTrue {
		t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
	}
	args := f.Args()
	if len(args) != 1 || args[0] != "maybe" {
		t.Fatal("expected an extra 'maybe' argument to stick around")
	}
}

func TestExplicitMaybe(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"--tristate=maybe"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateMaybe {
		t.Fatal("expected", triStateMaybe, "(triStateMaybe) but got", tristate, "instead")
	}
}

func TestExplicitFalse(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{"--tristate=false"})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateFalse {
		t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
	}
}

func TestImplicitFalse(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	err := f.Parse([]string{})
	if err != nil {
		t.Fatal("expected no error; got", err)
	}
	if tristate != triStateFalse {
		t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
	}
}

func TestInvalidValue(t *testing.T) {
	var tristate triStateValue
	f := setUpFlagSet(&tristate)
	var buf bytes.Buffer
	f.SetOutput(&buf)
	err := f.Parse([]string{"--tristate=invalid"})
	if err == nil {
		t.Fatal("expected an error but did not get any, tristate has value", tristate)
	}
}

func TestBoolP(t *testing.T) {
	b := BoolP("bool", "b", false, "bool value in CommandLine")
	c := BoolP("c", "c", false, "other bool value")
	args := []string{"--bool"}
	if err := CommandLine.Parse(args); err != nil {
		t.Error("expected no error, got ", err)
	}
	if *b != true {
		t.Errorf("expected b=true got b=%v", *b)
	}
	if *c != false {
		t.Errorf("expect c=false got c=%v", *c)
	}
}
<|endoftext|>


<commit_before>package lib

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

// Plan on Vultr
type Plan struct {
	ID        int    `json:"VPSPLANID,string"`
	Name      string `json:"name"`
	VCpus     int    `json:"vcpu_count,string"`
	RAM       string `json:"ram"`
	Disk      string `json:"disk"`
	Bandwidth string `json:"bandwidth"`
	Price     string `json:"price_per_month"`
	Regions   []int  `json:"available_locations"`
}

type plans []Plan

func (p plans) Len() int      { return len(p) }
func (p plans) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p plans) Less(i, j int) bool {
	pa, _ := strconv.ParseFloat(strings.TrimSpace(p[i].Price), 64)
	pb, _ := strconv.ParseFloat(strings.TrimSpace(p[j].Price), 64)
	ra, _ := strconv.ParseInt(strings.TrimSpace(p[i].RAM), 10, 64)
	rb, _ := strconv.ParseInt(strings.TrimSpace(p[j].RAM), 10, 64)
	da, _ := strconv.ParseInt(strings.TrimSpace(p[i].Disk), 10, 64)
	db, _ := strconv.ParseInt(strings.TrimSpace(p[j].Disk), 10, 64)

	// sort order: price, vcpu, ram, disk
	if pa < pb {
		return true
	} else if pa > pb {
		return false
	}

	if p[i].VCpus < p[j].VCpus {
		return true
	} else if p[i].VCpus > p[j].VCpus {
		return false
	}

	if ra < rb {
		return true
	} else if ra > rb {
		return false
	}

	return da < db
}

// GetPlans returns a list of all available plans on Vultr account
func (c *Client) GetPlans() ([]Plan, error) {
	var planMap map[string]Plan
	if err := c.get(`plans/list`, &planMap); err != nil {
		return nil, err
	}

	var p plans
	for _, plan := range planMap {
		p = append(p, plan)
	}

	sort.Sort(plans(p))
	return p, nil
}

// GetAvailablePlansForRegion returns available plans for specified region
func (c *Client) GetAvailablePlansForRegion(id int) (planIDs []int, err error) {
	if err := c.get(fmt.Sprintf(`regions/availability?DCID=%v`, id), &planIDs); err != nil {
		return nil, err
	}
	return
}
<commit_msg>Update plans.go<commit_after>package lib

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

// Plan on Vultr
type Plan struct {
	ID        int    `json:"VPSPLANID,string"`
	Name      string `json:"name"`
	VCpus     int    `json:"vcpu_count,string"`
	RAM       string `json:"ram"`
	Disk      string `json:"disk"`
	Bandwidth string `json:"bandwidth"`
	Price     string `json:"price_per_month"`
	PlanType  string `json:"plan_type"`
	Windows   bool   `json:"windows"`
	Regions   []int  `json:"available_locations"`
}

type plans []Plan

func (p plans) Len() int      { return len(p) }
func (p plans) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p plans) Less(i, j int) bool {
	pa, _ := strconv.ParseFloat(strings.TrimSpace(p[i].Price), 64)
	pb, _ := strconv.ParseFloat(strings.TrimSpace(p[j].Price), 64)
	ra, _ := strconv.ParseInt(strings.TrimSpace(p[i].RAM), 10, 64)
	rb, _ := strconv.ParseInt(strings.TrimSpace(p[j].RAM), 10, 64)
	da, _ := strconv.ParseInt(strings.TrimSpace(p[i].Disk), 10, 64)
	db, _ := strconv.ParseInt(strings.TrimSpace(p[j].Disk), 10, 64)

	// sort order: price, vcpu, ram, disk
	if pa < pb {
		return true
	} else if pa > pb {
		return false
	}

	if p[i].VCpus < p[j].VCpus {
		return true
	} else if p[i].VCpus > p[j].VCpus {
		return false
	}

	if ra < rb {
		return true
	} else if ra > rb {
		return false
	}

	return da < db
}

// GetPlans returns a list of all available plans on Vultr account
func (c *Client) GetPlans() ([]Plan, error) {
	var planMap map[string]Plan
	if err := c.get(`plans/list`, &planMap); err != nil {
		return nil, err
	}

	var p plans
	for _, plan := range planMap {
		p = append(p, plan)
	}

	sort.Sort(plans(p))
	return p, nil
}

// GetAvailablePlansForRegion returns available plans for specified region
func (c *Client) GetAvailablePlansForRegion(id int) (planIDs []int, err error) {
	if err := c.get(fmt.Sprintf(`regions/availability?DCID=%v`, id), &planIDs); err != nil {
		return nil, err
	}
	return
}
<|endoftext|>


<commit_before>package types

import (
	"testing"
	//"fmt"
	"os"
	"reflect"
	"regexp"
	"github.com/stretchrcom/testify/assert"
	"fubsy/testutils"
)

func Test_translateGlob(t *testing.T) {
	tests := []struct {glob string; re string} {
		{"", "$"},
		{"foo", "foo$"},
		{"foo/bar", "foo/bar$"},

		{"foo?bar", "foo[^/]bar$"},
		{"*.c", "[^/]*\\.c$"},
		{"foo[abc]", "foo[abc]$"},
		{"foo[a-m]*.bop", "foo[a-m][^/]*\\.bop$"},
		{"foo/**/bar", "foo/.*/bar$"},
		{"**/foo/bar", ".*/foo/bar$"},
		{"foo/bar/**", "foo/bar/.*$"},
		{"foo/**/bar/**/baz/**", "foo/.*/bar/.*/baz/.*$"},
	}

	for _, pair := range tests {
		actual, err := translateGlob(pair.glob)
		assert.Nil(t, err)
		assert.Equal(t, pair.re, actual)
	}

	// make sure one of those regexps actually works as intended
	pat, err := translateGlob("foo[a-m]/p*g/*.[ch]")
	assert.Nil(t, err)
	re, err := regexp.Compile("^" + pat)
	assert.Nil(t, err)
	match := []string {
		"foom/pong/bop.c",
		"foog/pig/abc.c",
		"foog/pig/a.c.-af#@0(.h",
		"foob/pg/a_b&.c",
	}
	for _, fn := range match {
		assert.Equal(t, fn, re.FindString(fn))
	}

	nomatch := []string {
		"foo/pong/bop.c",
		"foom/pongx/bop.c",
		"foom/pong/bop.cpp",
		"foom/pong/bop.c/x",
		"fooz/pong/bop.c",
		"foom/pg/bop.d",
	}
	for _, fn := range nomatch {
		assert.Equal(t, "", re.FindString(fn))
	}
}

func Test_translateGlob_error(t *testing.T) {
	_, err := translateGlob("foo[a-f*.c")
	assert.Equal(t, "unterminated character range", err.Error())
}

func Test_splitPattern_no_recursive(t *testing.T) {
	patterns := []string {
		"",
		"foobar",
		"foo/b?r/*/blah/*.[ch]",
	}
	for _, pattern := range patterns {
		recursive, _, _, err := splitPattern(pattern)
		assert.False(t, recursive)
		assert.Nil(t, err)
	}
}

func Test_splitPattern_valid_recursive(t *testing.T) {
	tests := []struct {glob string; prefix string; tail string} {
		{"**/*.c", ".", "*.c"},
		{"**/foo/b?r/*.[ch]", ".", "foo/b?r/*.[ch]"},
		{"foo/**/*.c", "foo", "*.c"},
		{"f?o/*/**/?eep/*.[ch]", "f?o/*", "?eep/*.[ch]"},
	}

	for _, test := range tests {
		recursive, prefix, tail, err := splitPattern(test.glob)
		assert.True(t, recursive)
		assert.Nil(t, err)
		assert.Equal(t, test.prefix, prefix)
		assert.Equal(t, test.tail, tail)
	}
}

func Test_splitPattern_invalid(t *testing.T) {
	patterns := []string {
		"**",
		"**/",
		"foo/**",
		"foo/**/",
		"foo**/x",
		"foo/**x",
	}

	for _, pattern := range patterns {
		_, _, _, err := splitPattern(pattern)
		assert.NotNil(t, err)
	}
}

func Test_FuFileFinder_String(t *testing.T) {
	var ff FuObject
	ff = &FuFileFinder{includes: []string {"*.c", "**/*.h"}}
	assert.Equal(t, "<*.c **/*.h>", ff.String())
}

func Test_FuFileFinder_Expand_empty(t *testing.T) {
	cleanup := testutils.Chtemp()
	defer cleanup()

	// no patterns, no files: of course we find nothing
	ff := &FuFileFinder{}
	assertExpand(t, []string {}, ff)

	// patterns, but no files: still nothing
	ff.includes = []string {"**/*.c", "include/*.h", "*/*.txt"}
	assertExpand(t, []string {}, ff)

	// no patterns, some files: still nothing
	ff.includes = ff.includes[0:0]
	mkdirs("lib1", "lib1/sub", "lib2", "include")
	touchfiles(
		"lib1/foo.c", "lib1/sub/blah.c", "include/bop.h", "include/bip.h")
	assertExpand(t, []string {}, ff)
}

func Test_FuFileFinder_Expand_single_include(t *testing.T) {
	cleanup := testutils.Chtemp()
	defer cleanup()

	mkdirs("lib1", "lib1/sub", "lib2", "include")
	touchfiles(
		"lib1/foo.c", "lib1/sub/blah.c", "include/bop.h", "include/bip.h")

	ff := &FuFileFinder{includes: []string {"*/*.c"}}
	assertExpand(t, []string {"lib1/foo.c"}, ff)

	ff.includes[0] = "**/*.c"
	assertExpand(t, []string {"lib1/foo.c", "lib1/sub/blah.c"}, ff)
	return

	ff.includes[0] = "l?b?/**/*.c"
	assertExpand(t, []string {"lib1/foo.c", "lib1/sub/blah.c"}, ff)

	ff.includes[0] = "in?lu?e/*.h"
	assertExpand(t, []string {"include/bip.h", "include/bop.h"}, ff)

	ff.includes[0] = "inc*/?i*.h"
	assertExpand(t, []string {"include/bip.h"}, ff)
}

func Test_FuFileFinder_Expand_double_recursion(t *testing.T) {
	// Java programmers love this sort of insanely deep structure, and
	// Ant supports patterns with multiple occurences of "**" ... so I
	// guess Fubsy has to support them too!
	cleanup := testutils.Chtemp()
	defer cleanup()

	mkdirs(
		"app1/src/main/org/example/app1/subpkg",
		"app1/src/test/org/example/app1/subpkg",
		"misc/app2/src/main/org/example/app2",
		"misc/app3/src/main/org/example/app3",
		"misc/app3/src/test/org/example/app3",
		)
	touchfiles(
		"app1/src/main/org/example/app1/App1.java",
		"app1/src/main/org/example/app1/Util.java",
		"app1/src/main/org/example/app1/doc.txt",
		"app1/src/main/org/example/app1/subpkg/Stuff.java",
		"app1/src/main/org/example/app1/subpkg/MoreStuff.java",
		"app1/src/test/org/example/app1/StuffTest.java",
		"misc/app2/src/main/org/example/app2/App2.java",
		"misc/app3/src/main/org/example/app3/App3.java",
		"misc/app3/src/main/org/example/app3/Helpers.java",
		"misc/app3/src/test/org/example/app3/TestHelpers.java",
		"misc/app3/src/test/org/example/app3/testdata",
		)

	var ff *FuFileFinder
	var expect []string
	ff = NewFileFinder([]string {"**/test/**/*.java"})
	expect = []string {
		"app1/src/test/org/example/app1/StuffTest.java",
		"misc/app3/src/test/org/example/app3/TestHelpers.java",
	}
	assertExpand(t, expect, ff)

	ff = NewFileFinder([]string {"**/test/**/*"})
	expect = []string {
		"app1/src/test/org/example/app1/StuffTest.java",
		"misc/app3/src/test/org/example/app3/TestHelpers.java",
		"misc/app3/src/test/org/example/app3/testdata",
	}
	assertExpand(t, expect, ff)

	ff = NewFileFinder([]string {"**/test/**"})
	assertExpand(t, expect, ff)
}

func Test_FileFinder_Add(t *testing.T) {
	cleanup := testutils.Chtemp()
	defer cleanup()
	mkdirs("src", "include", "doc")
	touchfiles(
		"src/foo.c", "src/foo.h", "main.c", "include/bop.h",
		"doc.txt", "doc/stuff.txt", "doc/blahblah.rst")

	ff1 := NewFileFinder([]string {"**/*.c"})
	ff2 := NewFileFinder([]string {"doc/*.txt"})

	// simulate sum = <**/*.c> + <doc/*.txt>
	expect := []string {
		"main.c", "src/foo.c", "doc/stuff.txt"}
	sum, err := ff1.Add(ff2)
	//fmt.Printf("ff1 = %v\nff2 = %v\nsum = %v\n", ff1, ff2, sum)
	assert.Nil(t, err)
	assertExpand(t, expect, sum)

	// simulate sum + <"*c*/?o?.h">
	ff3 := NewFileFinder([]string {"*c*/?o?.h"})
	expect = append(expect, "include/bop.h", "src/foo.h")
	sum, err = sum.Add(ff3)
	//fmt.Printf("ff3 = %v\nnew sum = %v\n", ff3, sum)
	assert.Nil(t, err)
	assertExpand(t, expect, sum)
	return

	// simulate <doc/*.txt> + (<*c*/?o?.h> + <**/*.c>)
	// (same as before, just different order)
	expect = []string {
		//"doc/stuff.txt", "include/bop.h", "src/foo.h", "main.c", "src/foo.c"}
		"include/bop.h", "src/foo.h", "main.c", "src/foo.c"}
	sum, err = ff3.Add(ff1)
	assert.Nil(t, err)
	assertExpand(t, expect, sum)

	expect = append([]string {"doc/stuff.txt"}, expect...)
	sum, err = ff2.Add(sum)
	assert.Nil(t, err)
	assertExpand(t, expect, sum)
}

func Test_FinderList_misc(t *testing.T) {
	ff1 := NewFileFinder([]string {"*.c", "*.h"})
	ff2 := NewFileFinder([]string {"doc/???.txt"})
	ff3 := NewFileFinder([]string {})

	sum1, err := ff1.Add(ff2)
	assert.Nil(t, err)
	assert.Equal(t, "<*.c *.h> + <doc/???.txt>", sum1.String())

	sum2, err := ff3.Add(sum1)
	assert.Nil(t, err)
	assert.Equal(t, "<> + <*.c *.h> + <doc/???.txt>", sum2.String())

	assert.False(t, sum1.Equal(sum2))

	sum2b, err := ff3.Add(sum1)
	assert.Nil(t, err)
	assert.True(t, sum2.Equal(sum2b))
}

func mkdirs(dirs ...string) {
	for _, dir := range dirs {
		if err := os.MkdirAll(dir, 0755); err != nil {
			panic(err)
		}
	}
}

func touchfiles(filenames ...string) {
	for _, fn := range filenames {
		file, err := os.Create(fn)
		if err != nil {
			panic(err)
		}
		file.Close()
	}
}

func assertExpand(t *testing.T, expect []string, obj FuObject) {
	actual, err := obj.Expand()
	assert.Nil(t, err)

	expectobj := makeFuList(expect...)
	if !reflect.DeepEqual(expectobj, actual) {
		t.Errorf("%v Expand(): " +
			"expected\n%v\nbut got\n%v",
			obj, expectobj, actual)
	}
}
<commit_msg>filefinder: increase test coverage a bit more<commit_after>package types

import (
	"testing"
	//"fmt"
	"os"
	"reflect"
	"regexp"
	"github.com/stretchrcom/testify/assert"
	"fubsy/testutils"
)

func Test_translateGlob(t *testing.T) {
	tests := []struct {glob string; re string} {
		{"", "$"},
		{"foo", "foo$"},
		{"foo/bar", "foo/bar$"},

		{"foo?bar", "foo[^/]bar$"},
		{"*.c", "[^/]*\\.c$"},
		{"foo[abc]", "foo[abc]$"},
		{"foo[a-m]*.bop", "foo[a-m][^/]*\\.bop$"},
		{"foo/**/bar", "foo/.*/bar$"},
		{"**/foo/bar", ".*/foo/bar$"},
		{"foo/bar/**", "foo/bar/.*$"},
		{"foo/**/bar/**/baz/**", "foo/.*/bar/.*/baz/.*$"},
	}

	for _, pair := range tests {
		actual, err := translateGlob(pair.glob)
		assert.Nil(t, err)
		assert.Equal(t, pair.re, actual)
	}

	// make sure one of those regexps actually works as intended
	pat, err := translateGlob("foo[a-m]/p*g/*.[ch]")
	assert.Nil(t, err)
	re, err := regexp.Compile("^" + pat)
	assert.Nil(t, err)
	match := []string {
		"foom/pong/bop.c",
		"foog/pig/abc.c",
		"foog/pig/a.c.-af#@0(.h",
		"foob/pg/a_b&.c",
	}
	for _, fn := range match {
		assert.Equal(t, fn, re.FindString(fn))
	}

	nomatch := []string {
		"foo/pong/bop.c",
		"foom/pongx/bop.c",
		"foom/pong/bop.cpp",
		"foom/pong/bop.c/x",
		"fooz/pong/bop.c",
		"foom/pg/bop.d",
	}
	for _, fn := range nomatch {
		assert.Equal(t, "", re.FindString(fn))
	}
}

func Test_translateGlob_error(t *testing.T) {
	_, err := translateGlob("foo[a-f*.c")
	assert.Equal(t, "unterminated character range", err.Error())
}

func Test_splitPattern_no_recursive(t *testing.T) {
	patterns := []string {
		"",
		"foobar",
		"foo/b?r/*/blah/*.[ch]",
	}
	for _, pattern := range patterns {
		recursive, _, _, err := splitPattern(pattern)
		assert.False(t, recursive)
		assert.Nil(t, err)
	}
}

func Test_splitPattern_valid_recursive(t *testing.T) {
	tests := []struct {glob string; prefix string; tail string} {
		{"**/*.c", ".", "*.c"},
		{"**/foo/b?r/*.[ch]", ".", "foo/b?r/*.[ch]"},
		{"foo/**/*.c", "foo", "*.c"},
		{"f?o/*/**/?eep/*.[ch]", "f?o/*", "?eep/*.[ch]"},
	}

	for _, test := range tests {
		recursive, prefix, tail, err := splitPattern(test.glob)
		assert.True(t, recursive)
		assert.Nil(t, err)
		assert.Equal(t, test.prefix, prefix)
		assert.Equal(t, test.tail, tail)
	}
}

func Test_splitPattern_invalid(t *testing.T) {
	patterns := []string {
		"**",
		"**/",
		"foo/**",
		"foo/**/",
		"foo**/x",
		"foo/**x",
	}

	for _, pattern := range patterns {
		_, _, _, err := splitPattern(pattern)
		assert.NotNil(t, err)
	}
}

func Test_FuFileFinder_String(t *testing.T) {
	var ff FuObject
	ff = &FuFileFinder{includes: []string {"*.c", "**/*.h"}}
	assert.Equal(t, "<*.c **/*.h>", ff.String())
}

func Test_FuFileFinder_Equal(t *testing.T) {
	ff1 := NewFileFinder([]string {"*.c", "*.h"})
	ff2 := NewFileFinder([]string {"*.c", "*.h"})
	ff3 := NewFileFinder([]string {"*.h", "*.c"})

	assert.True(t, ff1.Equal(ff1))
	assert.True(t, ff1.Equal(ff2))
	assert.False(t, ff1.Equal(ff3))
}

func Test_FuFileFinder_Expand_empty(t *testing.T) {
	cleanup := testutils.Chtemp()
	defer cleanup()

	// no patterns, no files: of course we find nothing
	ff := &FuFileFinder{}
	assertExpand(t, []string {}, ff)

	// patterns, but no files: still nothing
	ff.includes = []string {"**/*.c", "include/*.h", "*/*.txt"}
	assertExpand(t, []string {}, ff)

	// no patterns, some files: still nothing
	ff.includes = ff.includes[0:0]
	mkdirs("lib1", "lib1/sub", "lib2", "include")
	touchfiles(
		"lib1/foo.c", "lib1/sub/blah.c", "include/bop.h", "include/bip.h")
	assertExpand(t, []string {}, ff)
}

func Test_FuFileFinder_Expand_single_include(t *testing.T) {
	cleanup := testutils.Chtemp()
	defer cleanup()

	mkdirs("lib1", "lib1/sub", "lib2", "include")
	touchfiles(
		"lib1/foo.c", "lib1/sub/blah.c", "include/bop.h", "include/bip.h")

	ff := &FuFileFinder{includes: []string {"*/*.c"}}
	assertExpand(t, []string {"lib1/foo.c"}, ff)

	ff.includes[0] = "**/*.c"
	assertExpand(t, []string {"lib1/foo.c", "lib1/sub/blah.c"}, ff)
	return

	ff.includes[0] = "l?b?/**/*.c"
	assertExpand(t, []string {"lib1/foo.c", "lib1/sub/blah.c"}, ff)

	ff.includes[0] = "in?lu?e/*.h"
	assertExpand(t, []string {"include/bip.h", "include/bop.h"}, ff)

	ff.includes[0] = "inc*/?i*.h"
	assertExpand(t, []string {"include/bip.h"}, ff)
}

func Test_FuFileFinder_Expand_double_recursion(t *testing.T) {
	// Java programmers love this sort of insanely deep structure, and
	// Ant supports patterns with multiple occurences of "**" ... so I
	// guess Fubsy has to support them too!
	cleanup := testutils.Chtemp()
	defer cleanup()

	mkdirs(
		"app1/src/main/org/example/app1/subpkg",
		"app1/src/test/org/example/app1/subpkg",
		"misc/app2/src/main/org/example/app2",
		"misc/app3/src/main/org/example/app3",
		"misc/app3/src/test/org/example/app3",
		)
	touchfiles(
		"app1/src/main/org/example/app1/App1.java",
		"app1/src/main/org/example/app1/Util.java",
		"app1/src/main/org/example/app1/doc.txt",
		"app1/src/main/org/example/app1/subpkg/Stuff.java",
		"app1/src/main/org/example/app1/subpkg/MoreStuff.java",
		"app1/src/test/org/example/app1/StuffTest.java",
		"misc/app2/src/main/org/example/app2/App2.java",
		"misc/app3/src/main/org/example/app3/App3.java",
		"misc/app3/src/main/org/example/app3/Helpers.java",
		"misc/app3/src/test/org/example/app3/TestHelpers.java",
		"misc/app3/src/test/org/example/app3/testdata",
		)

	var ff *FuFileFinder
	var expect []string
	ff = NewFileFinder([]string {"**/test/**/*.java"})
	expect = []string {
		"app1/src/test/org/example/app1/StuffTest.java",
		"misc/app3/src/test/org/example/app3/TestHelpers.java",
	}
	assertExpand(t, expect, ff)

	ff = NewFileFinder([]string {"**/test/**/*"})
	expect = []string {
		"app1/src/test/org/example/app1/StuffTest.java",
		"misc/app3/src/test/org/example/app3/TestHelpers.java",
		"misc/app3/src/test/org/example/app3/testdata",
	}
	assertExpand(t, expect, ff)

	ff = NewFileFinder([]string {"**/test/**"})
	assertExpand(t, expect, ff)
}

func Test_FileFinder_Add(t *testing.T) {
	cleanup := testutils.Chtemp()
	defer cleanup()
	mkdirs("src", "include", "doc")
	touchfiles(
		"src/foo.c", "src/foo.h", "main.c", "include/bop.h",
		"doc.txt", "doc/stuff.txt", "doc/blahblah.rst")

	ff1 := NewFileFinder([]string {"**/*.c"})
	ff2 := NewFileFinder([]string {"doc/*.txt"})

	// simulate sum = <**/*.c> + <doc/*.txt>
	expect := []string {
		"main.c", "src/foo.c", "doc/stuff.txt"}
	sum, err := ff1.Add(ff2)
	//fmt.Printf("ff1 = %v\nff2 = %v\nsum = %v\n", ff1, ff2, sum)
	assert.Nil(t, err)
	assertExpand(t, expect, sum)

	// simulate sum + <"*c*/?o?.h">
	ff3 := NewFileFinder([]string {"*c*/?o?.h"})
	expect = append(expect, "include/bop.h", "src/foo.h")
	sum, err = sum.Add(ff3)
	//fmt.Printf("ff3 = %v\nnew sum = %v\n", ff3, sum)
	assert.Nil(t, err)
	assertExpand(t, expect, sum)

	// simulate <doc/*.txt> + (<*c*/?o?.h> + <**/*.c>)
	// (same as before, just different order)
	expect = []string {
		//"doc/stuff.txt", "include/bop.h", "src/foo.h", "main.c", "src/foo.c"}
		"include/bop.h", "src/foo.h", "main.c", "src/foo.c"}
	sum, err = ff3.Add(ff1)
	assert.Nil(t, err)
	assertExpand(t, expect, sum)

	expect = append([]string {"doc/stuff.txt"}, expect...)
	sum, err = ff2.Add(sum)
	assert.Nil(t, err)
	assertExpand(t, expect, sum)

	sum, err = ff1.Add(FuString("urgh"))
	assert.Equal(t,
		"unsupported operation: cannot add string to file finder", err.Error())
	assert.Nil(t, sum)
}

func Test_FinderList_misc(t *testing.T) {
	ff1 := NewFileFinder([]string {"*.c", "*.h"})
	ff2 := NewFileFinder([]string {"doc/???.txt"})
	ff3 := NewFileFinder([]string {})

	sum1, err := ff1.Add(ff2)
	assert.Nil(t, err)
	assert.Equal(t, "<*.c *.h> + <doc/???.txt>", sum1.String())

	sum2, err := ff3.Add(sum1)
	assert.Nil(t, err)
	assert.Equal(t, "<> + <*.c *.h> + <doc/???.txt>", sum2.String())

	assert.False(t, sum1.Equal(sum2))

	sum2b, err := ff3.Add(sum1)
	assert.Nil(t, err)
	assert.True(t, sum2.Equal(sum2b))

	// This is a silly thing to do, and perhaps we should filter out
	// the duplicate patterns... but I don't think so. If the user
	// constructs something silly, we do something silly.
	sum3, err := sum1.Add(sum2)
	assert.Nil(t, err)
	assert.Equal(t,
		"<*.c *.h> + <doc/???.txt> + <> + <*.c *.h> + <doc/???.txt>",
		sum3.String())
}

func mkdirs(dirs ...string) {
	for _, dir := range dirs {
		if err := os.MkdirAll(dir, 0755); err != nil {
			panic(err)
		}
	}
}

func touchfiles(filenames ...string) {
	for _, fn := range filenames {
		file, err := os.Create(fn)
		if err != nil {
			panic(err)
		}
		file.Close()
	}
}

func assertExpand(t *testing.T, expect []string, obj FuObject) {
	actual, err := obj.Expand()
	assert.Nil(t, err)

	expectobj := makeFuList(expect...)
	if !reflect.DeepEqual(expectobj, actual) {
		t.Errorf("%v Expand(): " +
			"expected\n%v\nbut got\n%v",
			obj, expectobj, actual)
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package imageconversion

import (
	"fmt"
	"github.com/nfnt/resize"
	"image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io"
	"strings"
)

func MimeTypeIsSupported(mimeType string) bool {

	switch mimeType {
	case "image/png", "image/jpeg", "image/gif":
		return true

	default:
		return false
	}

	panic("Unreachable")
}

func GetFileExtensionFromMimeType(mimeType string) string {
	switch mimeType {

	case "image/png":
		return "png"

	case "image/jpeg":
		return "jpg"

	case "image/gif":
		return "gif"

	default:
		return strings.ToLower(strings.Replace(mimeType, "image/", "", 1))

	}

	panic("Unreachable")
}

func Resize(source io.Reader, mimeType string, width, height uint, target io.Writer) error {

	// check the mime type
	if !MimeTypeIsSupported(mimeType) {
		return fmt.Errorf("The mime-type %q is currently not supported.", mimeType)
	}

	// read the source image
	img, err := decode(source, mimeType)
	if err != nil {
		return err
	}

	// resize the source image
	thumb := resize.Thumbnail(width, height, img, resize.Lanczos3)

	// write the thumbnail to the target
	return encode(mimeType, thumb, target)
}

func encode(mimeType string, thumb image.Image, target io.Writer) error {

	switch mimeType {

	case "image/png":
		return png.Encode(target, thumb)

	case "image/jpeg":
		return jpeg.Encode(target, thumb, nil)

	case "image/gif":
		return gif.Encode(target, thumb, nil)

	default:
		return fmt.Errorf("Unsupported mime type %s", mimeType)

	}

	panic("Unreachable")
}

func decode(source io.Reader, mimeType string) (image.Image, error) {

	switch mimeType {

	case "image/png":
		return png.Decode(source)

	case "image/jpeg":
		return jpeg.Decode(source)

	case "image/gif":
		return gif.Decode(source)

	default:
		return nil, fmt.Errorf("Unsupported mime type %s", mimeType)

	}

	panic("Unreachable")
}
<commit_msg>Don't create thumbnails for gifs.<commit_after>// Copyright 2014 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package imageconversion

import (
	"fmt"
	"github.com/nfnt/resize"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"strings"
)

func MimeTypeIsSupported(mimeType string) bool {

	switch mimeType {
	case "image/png", "image/jpeg":
		return true

	default:
		return false
	}

	panic("Unreachable")
}

func GetFileExtensionFromMimeType(mimeType string) string {
	switch mimeType {

	case "image/png":
		return "png"

	case "image/jpeg":
		return "jpg"

	default:
		return strings.ToLower(strings.Replace(mimeType, "image/", "", 1))

	}

	panic("Unreachable")
}

func Resize(source io.Reader, mimeType string, width, height uint, target io.Writer) error {

	// check the mime type
	if !MimeTypeIsSupported(mimeType) {
		return fmt.Errorf("The mime-type %q is currently not supported.", mimeType)
	}

	// read the source image
	img, err := decode(source, mimeType)
	if err != nil {
		return err
	}

	// resize the source image
	thumb := resize.Thumbnail(width, height, img, resize.Lanczos3)

	// write the thumbnail to the target
	return encode(mimeType, thumb, target)
}

func encode(mimeType string, thumb image.Image, target io.Writer) error {

	switch mimeType {

	case "image/png":
		return png.Encode(target, thumb)

	case "image/jpeg":
		return jpeg.Encode(target, thumb, nil)

	default:
		return fmt.Errorf("Unsupported mime type %s", mimeType)

	}

	panic("Unreachable")
}

func decode(source io.Reader, mimeType string) (image.Image, error) {

	switch mimeType {

	case "image/png":
		return png.Decode(source)

	case "image/jpeg":
		return jpeg.Decode(source)

	default:
		return nil, fmt.Errorf("Unsupported mime type %s", mimeType)

	}

	panic("Unreachable")
}
<|endoftext|>


<commit_before>// @author       sigu-399
// @description  An implementation of JSON Schema, draft v4 - Go language
// @created      26-02-2013

package gojsonschema

import (
	"encoding/json"
	"errors"
	"fmt"
	"gojsonreference"
	"io/ioutil"
	"net/http"
	"reflect"
)

func NewJsonSchemaDocument(documentReferenceString string) (*JsonSchemaDocument, error) {

	var err error

	d := JsonSchemaDocument{}
	d.documentReference, err = gojsonreference.NewJsonReference(documentReferenceString)

	resp, err := http.Get(documentReferenceString)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusOK {
		return nil, errors.New("Could not access schema " + resp.Status)
	}

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

	var document interface{}
	err = json.Unmarshal(bodyBuff, &document)
	if err != nil {
		return nil, err
	}

	err = d.parse(document)
	return &d, err
}

type JsonSchemaDocument struct {
	documentReference gojsonreference.JsonReference
	rootSchema        *JsonSchema
}

func (d *JsonSchemaDocument) parse(document interface{}) error {
	d.rootSchema = &JsonSchema{}
	return d.parseSchema(document, d.rootSchema)
}

func (d *JsonSchemaDocument) parseSchema(documentNode interface{}, currentSchema *JsonSchema) error {

	if !isKind(documentNode, reflect.Map) {
		return errors.New("Schema must be an object")
	}

	m := documentNode.(map[string]interface{})

	// id
	if existsMapKey(m, "id") && !isKind(m["id"], reflect.String) {
		return errors.New(fmt.Sprintf(ERROR_MESSAGE_MUST_BE_OF_TYPE, "id", "string"))
	}
	if k, ok := m["id"].(string); ok {
		currentSchema.id = &k
	}

	// title
	if existsMapKey(m, "title") && !isKind(m["title"], reflect.String) {
		return errors.New(fmt.Sprintf(ERROR_MESSAGE_MUST_BE_OF_TYPE, "title", "string"))
	}
	if k, ok := m["title"].(string); ok {
		currentSchema.title = &k
	}

	// description
	if existsMapKey(m, "description") && !isKind(m["description"], reflect.String) {
		return errors.New(fmt.Sprintf(ERROR_MESSAGE_MUST_BE_OF_TYPE, "description", "string"))
	}
	if k, ok := m["description"].(string); ok {
		currentSchema.description = &k
	}

	// ref
	if existsMapKey(m, "$ref") && !isKind(m["$ref"], reflect.String) {
		return errors.New(fmt.Sprintf(ERROR_MESSAGE_MUST_BE_OF_TYPE, "$ref", "string"))
	}
	if k, ok := m["$ref"].(string); ok {
		currentSchema.ref = &k
	}

	// properties
	/*	if !existsMapKey(m, "properties") {
			return errors.New(fmt.Sprintf(ERROR_MESSAGE_IS_REQUIRED, "properties"))
		}
	*/
	for k := range m {
		if k == "properties" {
			err := d.parseProperties(m[k], currentSchema)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func (d *JsonSchemaDocument) parseProperties(documentNode interface{}, currentSchema *JsonSchema) error {

	if !isKind(documentNode, reflect.Map) {
		return errors.New("Properties must be an object")
	}

	m := documentNode.(map[string]interface{})
	for k := range m {
		newSchema := &JsonSchema{property: &k}
		currentSchema.AddChild(newSchema)
		err := d.parseSchema(m[k], newSchema)
		if err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>fixed property name retrieving<commit_after>// @author       sigu-399
// @description  An implementation of JSON Schema, draft v4 - Go language
// @created      26-02-2013

package gojsonschema

import (
	"encoding/json"
	"errors"
	"fmt"
	"gojsonreference"
	"io/ioutil"
	"net/http"
	"reflect"
)

func NewJsonSchemaDocument(documentReferenceString string) (*JsonSchemaDocument, error) {

	var err error

	d := JsonSchemaDocument{}
	d.documentReference, err = gojsonreference.NewJsonReference(documentReferenceString)

	resp, err := http.Get(documentReferenceString)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusOK {
		return nil, errors.New("Could not access schema " + resp.Status)
	}

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

	var document interface{}
	err = json.Unmarshal(bodyBuff, &document)
	if err != nil {
		return nil, err
	}

	err = d.parse(document)
	return &d, err
}

type JsonSchemaDocument struct {
	documentReference gojsonreference.JsonReference
	rootSchema        *JsonSchema
}

func (d *JsonSchemaDocument) parse(document interface{}) error {
	d.rootSchema = &JsonSchema{}
	return d.parseSchema(document, d.rootSchema)
}

func (d *JsonSchemaDocument) parseSchema(documentNode interface{}, currentSchema *JsonSchema) error {

	if !isKind(documentNode, reflect.Map) {
		return errors.New("Schema must be an object")
	}

	m := documentNode.(map[string]interface{})

	// id
	if existsMapKey(m, "id") && !isKind(m["id"], reflect.String) {
		return errors.New(fmt.Sprintf(ERROR_MESSAGE_MUST_BE_OF_TYPE, "id", "string"))
	}
	if k, ok := m["id"].(string); ok {
		currentSchema.id = &k
	}

	// title
	if existsMapKey(m, "title") && !isKind(m["title"], reflect.String) {
		return errors.New(fmt.Sprintf(ERROR_MESSAGE_MUST_BE_OF_TYPE, "title", "string"))
	}
	if k, ok := m["title"].(string); ok {
		currentSchema.title = &k
	}

	// description
	if existsMapKey(m, "description") && !isKind(m["description"], reflect.String) {
		return errors.New(fmt.Sprintf(ERROR_MESSAGE_MUST_BE_OF_TYPE, "description", "string"))
	}
	if k, ok := m["description"].(string); ok {
		currentSchema.description = &k
	}

	// ref
	if existsMapKey(m, "$ref") && !isKind(m["$ref"], reflect.String) {
		return errors.New(fmt.Sprintf(ERROR_MESSAGE_MUST_BE_OF_TYPE, "$ref", "string"))
	}
	if k, ok := m["$ref"].(string); ok {
		currentSchema.ref = &k
	}

	// properties
	/*	if !existsMapKey(m, "properties") {
			return errors.New(fmt.Sprintf(ERROR_MESSAGE_IS_REQUIRED, "properties"))
		}
	*/
	for k := range m {
		if k == "properties" {
			err := d.parseProperties(m[k], currentSchema)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func (d *JsonSchemaDocument) parseProperties(documentNode interface{}, currentSchema *JsonSchema) error {

	if !isKind(documentNode, reflect.Map) {
		return errors.New("Properties must be an object")
	}

	m := documentNode.(map[string]interface{})
	for k := range m {
		schemaProperty := k
		newSchema := &JsonSchema{property: &schemaProperty}
		currentSchema.AddChild(newSchema)
		err := d.parseSchema(m[k], newSchema)
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>