<commit_before>// Package gotest is a standard Go test output parser.
package gotest

import (
	"bufio"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/jstemmer/go-junit-report/v2/pkg/gtr"
)

var (
	// regexBenchmark captures 3-5 groups: benchmark name, number of times ran, ns/op (with or without decimal), MB/sec (optional), B/op (optional), and allocs/op (optional).
	regexBenchmark = regexp.MustCompile(`^(Benchmark[^ -]+)(?:-\d+\s+|\s+)(\d+)\s+(\d+|\d+\.\d+)\sns\/op(?:\s+(\d+|\d+\.\d+)\sMB\/s)?(?:\s+(\d+)\sB\/op)?(?:\s+(\d+)\sallocs/op)?`)
	regexCoverage  = regexp.MustCompile(`^coverage:\s+(\d+|\d+\.\d+)%\s+of\s+statements(?:\sin\s(.+))?$`)
	regexEndTest   = regexp.MustCompile(`((?:    )*)--- (PASS|FAIL|SKIP): ([^ ]+) \((\d+\.\d+)(?: seconds|s)\)`)
	regexStatus    = regexp.MustCompile(`^(PASS|FAIL|SKIP)$`)
	regexSummary   = regexp.MustCompile(`` +
		// 1: result
		`^(\?|ok|FAIL)` +
		// 2: package name
		`\s+([^ \t]+)` +
		// 3: duration (optional)
		`(?:\s+(\d+\.\d+)s)?` +
		// 4: cached indicator (optional)
		`(?:\s+(\(cached\)))?` +
		// 5: [status message] (optional)
		`(?:\s+(\[[^\]]+\]))?` +
		// 6: coverage percentage (optional)
		// 7: coverage package list (optional)
		`(?:\s+coverage:\s+(\d+\.\d+)%\sof\sstatements(?:\sin\s(.+))?)?$`)
)

// Option defines options that can be passed to gotest.New.
type Option func(*Parser)

// PackageName sets the default package name to use when it cannot be
// determined from the test output.
func PackageName(name string) Option {
	return func(p *Parser) {
		p.packageName = name
	}
}

// New returns a new Go test output parser.
func New(options ...Option) *Parser {
	p := &Parser{}
	for _, option := range options {
		option(p)
	}
	return p
}

// Parser is a Go test output Parser.
type Parser struct {
	packageName string

	events []Event
}

// Parse parses Go test output from the given io.Reader r and returns
// gtr.Report.
func (p *Parser) Parse(r io.Reader) (gtr.Report, error) {
	p.events = nil
	s := bufio.NewScanner(r)
	for s.Scan() {
		p.parseLine(s.Text())
	}
	return p.report(p.events), s.Err()
}

// report generates a gtr.Report from the given list of events.
func (p *Parser) report(events []Event) gtr.Report {
	rb := gtr.NewReportBuilder()
	rb.PackageName = p.packageName
	for _, ev := range events {
		switch ev.Type {
		case "run_test":
			rb.CreateTest(ev.Name)
		case "pause_test":
			rb.PauseTest(ev.Name)
		case "cont_test":
			rb.ContinueTest(ev.Name)
		case "end_test":
			rb.EndTest(ev.Name, ev.Result, ev.Duration, ev.Indent)
		case "benchmark":
			rb.Benchmark(ev.Name, ev.Iterations, ev.NsPerOp, ev.MBPerSec, ev.BytesPerOp, ev.AllocsPerOp)
		case "status":
			rb.End()
		case "summary":
			rb.CreatePackage(ev.Name, ev.Result, ev.Duration, ev.Data)
		case "coverage":
			rb.Coverage(ev.CovPct, ev.CovPackages)
		case "build_output":
			rb.CreateBuildError(ev.Name)
		case "output":
			rb.AppendOutput(ev.Data)
		default:
			fmt.Printf("unhandled event type: %v\n", ev.Type)
		}
	}
	return rb.Build()
}

// Events returns the events created by the parser.
func (p *Parser) Events() []Event {
	events := make([]Event, len(p.events))
	copy(events, p.events)
	return events
}

func (p *Parser) parseLine(line string) {
	if strings.HasPrefix(line, "=== RUN ") {
		p.runTest(strings.TrimSpace(line[8:]))
	} else if strings.HasPrefix(line, "=== PAUSE ") {
		p.pauseTest(strings.TrimSpace(line[10:]))
	} else if strings.HasPrefix(line, "=== CONT ") {
		p.contTest(strings.TrimSpace(line[9:]))
	} else if matches := regexEndTest.FindStringSubmatch(line); len(matches) == 5 {
		p.endTest(line, matches[1], matches[2], matches[3], matches[4])
	} else if matches := regexStatus.FindStringSubmatch(line); len(matches) == 2 {
		p.status(matches[1])
	} else if matches := regexSummary.FindStringSubmatch(line); len(matches) == 8 {
		p.summary(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], matches[7])
	} else if matches := regexCoverage.FindStringSubmatch(line); len(matches) == 3 {
		p.coverage(matches[1], matches[2])
	} else if matches := regexBenchmark.FindStringSubmatch(line); len(matches) == 7 {
		p.benchmark(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6])
	} else if strings.HasPrefix(line, "# ") {
		// TODO(jstemmer): this should just be output; we should detect build output when building report
		fields := strings.Fields(strings.TrimPrefix(line, "# "))
		if len(fields) == 1 || len(fields) == 2 {
			p.buildOutput(fields[0])
		} else {
			p.output(line)
		}
	} else {
		p.output(line)
	}
}

func (p *Parser) add(event Event) {
	p.events = append(p.events, event)
}

func (p *Parser) runTest(name string) {
	p.add(Event{Type: "run_test", Name: name})
}

func (p *Parser) pauseTest(name string) {
	p.add(Event{Type: "pause_test", Name: name})
}

func (p *Parser) contTest(name string) {
	p.add(Event{Type: "cont_test", Name: name})
}

func (p *Parser) endTest(line, indent, result, name, duration string) {
	if idx := strings.Index(line, fmt.Sprintf("%s--- %s:", indent, result)); idx > 0 {
		p.output(line[:idx])
	}
	_, n := stripIndent(indent)
	p.add(Event{
		Type:     "end_test",
		Name:     name,
		Result:   result,
		Indent:   n,
		Duration: parseSeconds(duration),
	})
}

func (p *Parser) status(result string) {
	p.add(Event{Type: "status", Result: result})
}

func (p *Parser) summary(result, name, duration, cached, status, covpct, packages string) {
	p.add(Event{
		Type:        "summary",
		Result:      result,
		Name:        name,
		Duration:    parseSeconds(duration),
		Data:        strings.TrimSpace(cached + " " + status),
		CovPct:      parseFloat(covpct),
		CovPackages: parsePackages(packages),
	})
}

func (p *Parser) coverage(percent, packages string) {
	p.add(Event{
		Type:        "coverage",
		CovPct:      parseFloat(percent),
		CovPackages: parsePackages(packages),
	})
}

func (p *Parser) benchmark(name, iterations, nsPerOp, mbPerSec, bytesPerOp, allocsPerOp string) {
	p.add(Event{
		Type:        "benchmark",
		Name:        name,
		Iterations:  parseInt(iterations),
		NsPerOp:     parseFloat(nsPerOp),
		MBPerSec:    parseFloat(mbPerSec),
		BytesPerOp:  parseInt(bytesPerOp),
		AllocsPerOp: parseInt(allocsPerOp),
	})
}

func (p *Parser) buildOutput(packageName string) {
	p.add(Event{
		Type: "build_output",
		Name: packageName,
	})
}

func (p *Parser) output(line string) {
	p.add(Event{Type: "output", Data: line})
}

func parseSeconds(s string) time.Duration {
	if s == "" {
		return time.Duration(0)
	}
	// ignore error
	d, _ := time.ParseDuration(s + "s")
	return d
}

func parseFloat(s string) float64 {
	if s == "" {
		return 0
	}
	// ignore error
	pct, _ := strconv.ParseFloat(s, 64)
	return pct
}

func parsePackages(pkgList string) []string {
	if len(pkgList) == 0 {
		return nil
	}
	return strings.Split(pkgList, ", ")
}

func parseInt(s string) int64 {
	// ignore error
	n, _ := strconv.ParseInt(s, 10, 64)
	return n
}

func stripIndent(line string) (string, int) {
	var indent int
	for indent = 0; strings.HasPrefix(line, "    "); indent++ {
		line = line[4:]
	}
	return line, indent
}
<commit_msg>parser/gotest: Add Option to override the timestamp function<commit_after>// Package gotest is a standard Go test output parser.
package gotest

import (
	"bufio"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/jstemmer/go-junit-report/v2/pkg/gtr"
)

var (
	// regexBenchmark captures 3-5 groups: benchmark name, number of times ran, ns/op (with or without decimal), MB/sec (optional), B/op (optional), and allocs/op (optional).
	regexBenchmark = regexp.MustCompile(`^(Benchmark[^ -]+)(?:-\d+\s+|\s+)(\d+)\s+(\d+|\d+\.\d+)\sns\/op(?:\s+(\d+|\d+\.\d+)\sMB\/s)?(?:\s+(\d+)\sB\/op)?(?:\s+(\d+)\sallocs/op)?`)
	regexCoverage  = regexp.MustCompile(`^coverage:\s+(\d+|\d+\.\d+)%\s+of\s+statements(?:\sin\s(.+))?$`)
	regexEndTest   = regexp.MustCompile(`((?:    )*)--- (PASS|FAIL|SKIP): ([^ ]+) \((\d+\.\d+)(?: seconds|s)\)`)
	regexStatus    = regexp.MustCompile(`^(PASS|FAIL|SKIP)$`)
	regexSummary   = regexp.MustCompile(`` +
		// 1: result
		`^(\?|ok|FAIL)` +
		// 2: package name
		`\s+([^ \t]+)` +
		// 3: duration (optional)
		`(?:\s+(\d+\.\d+)s)?` +
		// 4: cached indicator (optional)
		`(?:\s+(\(cached\)))?` +
		// 5: [status message] (optional)
		`(?:\s+(\[[^\]]+\]))?` +
		// 6: coverage percentage (optional)
		// 7: coverage package list (optional)
		`(?:\s+coverage:\s+(\d+\.\d+)%\sof\sstatements(?:\sin\s(.+))?)?$`)
)

// Option defines options that can be passed to gotest.New.
type Option func(*Parser)

// PackageName is an Option that sets the default package name to use when it
// cannot be determined from the test output.
func PackageName(name string) Option {
	return func(p *Parser) {
		p.packageName = name
	}
}

// TimestampFunc is an Option that sets the timestamp function that is used to
// determine the current time when creating the Report. This can be used to
// override the default behaviour of using time.Now().
func TimestampFunc(f func() time.Time) Option {
	return func(p *Parser) {
		p.timestampFunc = f
	}
}

// New returns a new Go test output parser.
func New(options ...Option) *Parser {
	p := &Parser{}
	for _, option := range options {
		option(p)
	}
	return p
}

// Parser is a Go test output Parser.
type Parser struct {
	packageName   string
	timestampFunc func() time.Time

	events []Event
}

// Parse parses Go test output from the given io.Reader r and returns
// gtr.Report.
func (p *Parser) Parse(r io.Reader) (gtr.Report, error) {
	p.events = nil
	s := bufio.NewScanner(r)
	for s.Scan() {
		p.parseLine(s.Text())
	}
	return p.report(p.events), s.Err()
}

// report generates a gtr.Report from the given list of events.
func (p *Parser) report(events []Event) gtr.Report {
	rb := gtr.NewReportBuilder()
	rb.PackageName = p.packageName
	rb.TimestampFunc = p.timestampFunc
	for _, ev := range events {
		switch ev.Type {
		case "run_test":
			rb.CreateTest(ev.Name)
		case "pause_test":
			rb.PauseTest(ev.Name)
		case "cont_test":
			rb.ContinueTest(ev.Name)
		case "end_test":
			rb.EndTest(ev.Name, ev.Result, ev.Duration, ev.Indent)
		case "benchmark":
			rb.Benchmark(ev.Name, ev.Iterations, ev.NsPerOp, ev.MBPerSec, ev.BytesPerOp, ev.AllocsPerOp)
		case "status":
			rb.End()
		case "summary":
			rb.CreatePackage(ev.Name, ev.Result, ev.Duration, ev.Data)
		case "coverage":
			rb.Coverage(ev.CovPct, ev.CovPackages)
		case "build_output":
			rb.CreateBuildError(ev.Name)
		case "output":
			rb.AppendOutput(ev.Data)
		default:
			fmt.Printf("unhandled event type: %v\n", ev.Type)
		}
	}
	return rb.Build()
}

// Events returns the events created by the parser.
func (p *Parser) Events() []Event {
	events := make([]Event, len(p.events))
	copy(events, p.events)
	return events
}

func (p *Parser) parseLine(line string) {
	if strings.HasPrefix(line, "=== RUN ") {
		p.runTest(strings.TrimSpace(line[8:]))
	} else if strings.HasPrefix(line, "=== PAUSE ") {
		p.pauseTest(strings.TrimSpace(line[10:]))
	} else if strings.HasPrefix(line, "=== CONT ") {
		p.contTest(strings.TrimSpace(line[9:]))
	} else if matches := regexEndTest.FindStringSubmatch(line); len(matches) == 5 {
		p.endTest(line, matches[1], matches[2], matches[3], matches[4])
	} else if matches := regexStatus.FindStringSubmatch(line); len(matches) == 2 {
		p.status(matches[1])
	} else if matches := regexSummary.FindStringSubmatch(line); len(matches) == 8 {
		p.summary(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], matches[7])
	} else if matches := regexCoverage.FindStringSubmatch(line); len(matches) == 3 {
		p.coverage(matches[1], matches[2])
	} else if matches := regexBenchmark.FindStringSubmatch(line); len(matches) == 7 {
		p.benchmark(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6])
	} else if strings.HasPrefix(line, "# ") {
		// TODO(jstemmer): this should just be output; we should detect build output when building report
		fields := strings.Fields(strings.TrimPrefix(line, "# "))
		if len(fields) == 1 || len(fields) == 2 {
			p.buildOutput(fields[0])
		} else {
			p.output(line)
		}
	} else {
		p.output(line)
	}
}

func (p *Parser) add(event Event) {
	p.events = append(p.events, event)
}

func (p *Parser) runTest(name string) {
	p.add(Event{Type: "run_test", Name: name})
}

func (p *Parser) pauseTest(name string) {
	p.add(Event{Type: "pause_test", Name: name})
}

func (p *Parser) contTest(name string) {
	p.add(Event{Type: "cont_test", Name: name})
}

func (p *Parser) endTest(line, indent, result, name, duration string) {
	if idx := strings.Index(line, fmt.Sprintf("%s--- %s:", indent, result)); idx > 0 {
		p.output(line[:idx])
	}
	_, n := stripIndent(indent)
	p.add(Event{
		Type:     "end_test",
		Name:     name,
		Result:   result,
		Indent:   n,
		Duration: parseSeconds(duration),
	})
}

func (p *Parser) status(result string) {
	p.add(Event{Type: "status", Result: result})
}

func (p *Parser) summary(result, name, duration, cached, status, covpct, packages string) {
	p.add(Event{
		Type:        "summary",
		Result:      result,
		Name:        name,
		Duration:    parseSeconds(duration),
		Data:        strings.TrimSpace(cached + " " + status),
		CovPct:      parseFloat(covpct),
		CovPackages: parsePackages(packages),
	})
}

func (p *Parser) coverage(percent, packages string) {
	p.add(Event{
		Type:        "coverage",
		CovPct:      parseFloat(percent),
		CovPackages: parsePackages(packages),
	})
}

func (p *Parser) benchmark(name, iterations, nsPerOp, mbPerSec, bytesPerOp, allocsPerOp string) {
	p.add(Event{
		Type:        "benchmark",
		Name:        name,
		Iterations:  parseInt(iterations),
		NsPerOp:     parseFloat(nsPerOp),
		MBPerSec:    parseFloat(mbPerSec),
		BytesPerOp:  parseInt(bytesPerOp),
		AllocsPerOp: parseInt(allocsPerOp),
	})
}

func (p *Parser) buildOutput(packageName string) {
	p.add(Event{
		Type: "build_output",
		Name: packageName,
	})
}

func (p *Parser) output(line string) {
	p.add(Event{Type: "output", Data: line})
}

func parseSeconds(s string) time.Duration {
	if s == "" {
		return time.Duration(0)
	}
	// ignore error
	d, _ := time.ParseDuration(s + "s")
	return d
}

func parseFloat(s string) float64 {
	if s == "" {
		return 0
	}
	// ignore error
	pct, _ := strconv.ParseFloat(s, 64)
	return pct
}

func parsePackages(pkgList string) []string {
	if len(pkgList) == 0 {
		return nil
	}
	return strings.Split(pkgList, ", ")
}

func parseInt(s string) int64 {
	// ignore error
	n, _ := strconv.ParseInt(s, 10, 64)
	return n
}

func stripIndent(line string) (string, int) {
	var indent int
	for indent = 0; strings.HasPrefix(line, "    "); indent++ {
		line = line[4:]
	}
	return line, indent
}
<|endoftext|>


<commit_before>package ratelimit

import (
	"net/http"
	"time"

	"github.com/didip/tollbooth"
)

func RateLimit(h http.Handler) http.Handler {
	return tollbooth.LimitHandler(tollbooth.NewLimiter(5, time.Second, nil), h)
}
<commit_msg>updated tollbooth<commit_after>package ratelimit

import (
	"net/http"

	"time"

	"github.com/didip/tollbooth"
	"github.com/didip/tollbooth/limiter"
)

func RateLimit(h http.Handler) http.Handler {
	return tollbooth.LimitHandler(tollbooth.NewLimiter(5, &limiter.ExpirableOptions{
		DefaultExpirationTTL: time.Second,
	}), h)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"time"

	"github.com/anacrolix/torrent"
	"github.com/dustin/go-humanize"
	"github.com/julienschmidt/httprouter"
)

var t torrent.Torrent
var seed *bool
var vlc *bool
var progress int64

const clearScreen = "\033[H\033[2J"

func main() {
	seed = flag.Bool("seed", true, "Seed after finished downloading")
	vlc = flag.Bool("vlc", false, "Open vlc to play the file")
	flag.Parse()
	if len(flag.Args()) == 0 {
		usage()
		os.Exit(1)
	}

	client, err := torrent.NewClient(&torrent.Config{
		DataDir:  os.TempDir(),
		NoUpload: !(*seed),
	})

	if err != nil {
		log.Fatal(err)
		os.Exit(3)
	}

	if t, err = client.AddMagnet(flag.Arg(0)); err != nil {
		log.Fatal(err)
		os.Exit(2)
	}

	// Start downloading files.
	go func() {
		<-t.GotInfo()
		t.DownloadAll()
	}()

	// Http handler.
	go func() {
		router := httprouter.New()
		router.GET("/", getFile)
		log.Fatal(http.ListenAndServe(":8080", router))
	}()

	if *vlc {
		go func() {
			for !readyForPlayback() {
				time.Sleep(time.Second)
			}
			log.Printf("Playing in vlc")

			// @todo decide command to run based on os.
			exec.Command("open", "-a", "vlc", "http://localhost:8080").Start()
		}()
	}

	// Cli render loop.
	for true {
		render()
		time.Sleep(time.Second)
	}
}

func readyForPlayback() bool {
	percentage := float64(t.BytesCompleted()) / float64(t.Length())

	return percentage > 0.05
}

func render() {
	var currentProgress = t.BytesCompleted()
	speed := humanize.Bytes(uint64(currentProgress-progress)) + "/s"
	progress = currentProgress

	percentage := float64(t.BytesCompleted()) / float64(t.Length()) * 100
	complete := humanize.Bytes(uint64(t.BytesCompleted()))
	size := humanize.Bytes(uint64(t.Length()))
	connections := len(t.Conns)

	print(clearScreen)
	fmt.Println(t.Name())
	fmt.Println("=============================================================")
	if t.BytesCompleted() > 0 {
		fmt.Printf("Progress: \t%s / %s  %.2f%%\n", complete, size, percentage)
	}
	if t.BytesCompleted() < t.Length() {
		fmt.Printf("Download speed: %s\n", speed)
	}
	fmt.Printf("Connections: \t%d\n", connections)
}

func usage() {
	flag.Usage()
}

func getLargestFile() torrent.File {
	var target torrent.File
	var maxSize int64

	for _, file := range t.Files() {
		if maxSize < file.Length() {
			maxSize = file.Length()
			target = file
		}
	}

	return target
}

func getFile(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	target := getLargestFile()
	entry, err := NewFileReader(target)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	defer entry.Close()

	http.ServeContent(w, r, target.DisplayPath(), time.Now(), entry)
}
<commit_msg>Clean up error statuses<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"time"

	"github.com/anacrolix/torrent"
	"github.com/dustin/go-humanize"
	"github.com/julienschmidt/httprouter"
)

var t torrent.Torrent
var seed *bool
var vlc *bool
var progress int64

const clearScreen = "\033[H\033[2J"

// Exit statuses.
const (
	_                       = iota
	exitNoTorrentProvided   = iota
	exitErrorCreatingClient = iota
	exitErrorAddingTorrent  = iota
)

func main() {
	// Set up flags.
	seed = flag.Bool("seed", true, "Seed after finished downloading")
	vlc = flag.Bool("vlc", false, "Open vlc to play the file")

	flag.Parse()
	if len(flag.Args()) == 0 {
		usage()
		os.Exit(exitNoTorrentProvided)
	}

	// Start up the torrent client.
	client, err := torrent.NewClient(&torrent.Config{
		DataDir:  os.TempDir(),
		NoUpload: !(*seed),
	})

	if err != nil {
		log.Fatal(err)
		os.Exit(exitErrorCreatingClient)
	}

	// Add the magnet url.
	if t, err = client.AddMagnet(flag.Arg(0)); err != nil {
		log.Fatal(err)
		os.Exit(exitErrorAddingTorrent)
	}

	// Start downloading files.
	go func() {
		<-t.GotInfo()
		t.DownloadAll()
	}()

	// Http handler.
	go func() {
		router := httprouter.New()
		router.GET("/", getFile)
		log.Fatal(http.ListenAndServe(":8080", router))
	}()

	if *vlc {
		go func() {
			for !readyForPlayback() {
				time.Sleep(time.Second)
			}
			log.Printf("Playing in vlc")

			// @todo decide command to run based on os.
			exec.Command("open", "-a", "vlc", "http://localhost:8080").Start()
		}()
	}

	// Cli render loop.
	for true {
		render()
		time.Sleep(time.Second)
	}
}

func readyForPlayback() bool {
	percentage := float64(t.BytesCompleted()) / float64(t.Length())

	return percentage > 0.05
}

func render() {
	var currentProgress = t.BytesCompleted()
	speed := humanize.Bytes(uint64(currentProgress-progress)) + "/s"
	progress = currentProgress

	percentage := float64(t.BytesCompleted()) / float64(t.Length()) * 100
	complete := humanize.Bytes(uint64(t.BytesCompleted()))
	size := humanize.Bytes(uint64(t.Length()))
	connections := len(t.Conns)

	print(clearScreen)
	fmt.Println(t.Name())
	fmt.Println("=============================================================")
	if t.BytesCompleted() > 0 {
		fmt.Printf("Progress: \t%s / %s  %.2f%%\n", complete, size, percentage)
	}
	if t.BytesCompleted() < t.Length() {
		fmt.Printf("Download speed: %s\n", speed)
	}
	fmt.Printf("Connections: \t%d\n", connections)
}

func usage() {
	flag.Usage()
}

func getLargestFile() torrent.File {
	var target torrent.File
	var maxSize int64

	for _, file := range t.Files() {
		if maxSize < file.Length() {
			maxSize = file.Length()
			target = file
		}
	}

	return target
}

func getFile(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	target := getLargestFile()
	entry, err := NewFileReader(target)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	defer entry.Close()

	http.ServeContent(w, r, target.DisplayPath(), time.Now(), entry)
}
<|endoftext|>


<commit_before>package ratelimit

import (
	"net/http"
	"time"

	"github.com/didip/tollbooth"
)

func RateLimit(h http.Handler) http.Handler {
	return tollbooth.LimitHandler(tollbooth.NewLimiter(1, time.Second*30, nil), h)
}
<commit_msg>Changed rate limit parameters<commit_after>package ratelimit

import (
	"net/http"
	"time"

	"github.com/didip/tollbooth"
)

func RateLimit(h http.Handler) http.Handler {
	return tollbooth.LimitHandler(tollbooth.NewLimiter(5, time.Second, nil), h)
}
<|endoftext|>


<commit_before>package main

import (
  "os"
  "fmt"
  "time"
  "strings"
  "net/http"
  "io/ioutil"
  "regexp"
  "encoding/json"
  "gopkg.in/mgo.v2"
  "github.com/gorilla/mux"
)

/**
 *  Shuttle Tracker
 *   Auto Updater - send request to iTrak API,
 *                  get updated shuttle info,
 *                  store updated records in db
 */

type VehicleUpdate struct {
  vehicleId   string  `json:"vehicleId"   bson:"vehicleId,omitempty"`
  lat         string  `json:"lat"         bson:"lat"`
  lng         string  `json:"lng"         bson:"lng"`
  heading     string  `json:"heading"     bson:"heading"`
  speed       string  `json:"speed"       bson:"speed"`
  lock        string  `json:"lock"        bson:"lock"`
  time        string  `json:"time"        bson:"time"`
  date        string  `json:"date"        bson:"date"`
  status      string  `json:"status"      bson:"status"`
}

func UpdateShuttles(dataFeed string, updateInterval int, session *mgo.Session) {
  for {
    // Reference updates collection and close db session upon exit
    UpdatesCollection := session.DB("shuttle_tracking").C("updates")
    defer session.Close()

    // Make request to our tracking data feed
    resp, err := http.Get(dataFeed)
    if err != nil {
      continue;
    }
    defer resp.Body.Close()

    // Read response body content
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
      continue;
    }

    delim := "eof"
    // Iterate through all vehicles returned by data feed
    vehicles_data := strings.Split(string(body), delim)
    for i := 1; i < len(vehicles_data)-1; i++ {

      // Match eatch API field with any number (+)
      //   of the previous expressions (\d digit, \. escaped period, - negative number)
      //   Specify named capturing groups to store each field from data feed
      re := regexp.MustCompile(`(?P<id>Vehicle ID:([\d\.]+)) (?P<lat>lat:([\d\.-]+)) (?P<lng>lon:([\d\.-]+)) (?P<heading>dir:([\d\.-]+)) (?P<speed>spd:([\d\.-]+)) (?P<lock>lck:([\d\.-]+)) (?P<time>time:([\d]+)) (?P<date>date:([\d]+)) (?P<status>trig:([\d]+))`)
      n := re.SubexpNames()
      match := re.FindAllStringSubmatch(vehicles_data[i], -1)[0]

      // Store named capturing group and matching expression as a key value pair
      result := map[string]string{}
      for i, item := range match {
        result[n[i]] = item
      }

      // Create new vehicle update
      update := VehicleUpdate {
        strings.Replace(result["id"], "Vehicle ID:", "", -1),
        strings.Replace(result["lat"], "lat:", "", -1),
        strings.Replace(result["lng"], "lon:", "", -1),
        strings.Replace(result["heading"], "dir:", "", -1),
        strings.Replace(result["speed"], "spd:", "", -1),
        strings.Replace(result["lock"], "lck:", "", -1),
        strings.Replace(result["time"], "time:", "", -1),
        strings.Replace(result["date"], "date:", "", -1),
        strings.Replace(result["status"], "trig:", "", -1) }

      // Insert update into database
      err := UpdatesCollection.Insert(update)

      if err != nil {
        fmt.Println(err)
      } else {
        fmt.Println(update)
      }
    }

    // Sleep for n seconds before updating again
    time.Sleep(time.Duration(updateInterval) * time.Second)
  }
}

/**
 *  Route handlers - API requests,
 *                   serve view files
 */

func IndexHandler(w http.ResponseWriter, r *http.Request) {
  http.ServeFile(w, r, "index.html")
}

func VehiclesHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Vehicles")
}

/**
 *  Main - connect to database,
 *         handle routing,
 *         start tracker go routine,
 *         serve requests
 */

type Configuration struct {
  DataFeed        string
  UpdateInterval  int
  MongoUrl        string
  MongoPort       string
}

func ReadConfiguration(fileName string) Configuration {
  // Open config file and decode JSON to Configuration struct
  file, _ := os.Open(fileName)
  decoder := json.NewDecoder(file)
  config := Configuration{}
  err := decoder.Decode(&config)
  if err != nil {
    fmt.Print("Unable to read config file: ")
    panic(err)
  }
  return config
}

func main() {
  // Read app configuration file
  config := ReadConfiguration("conf.json")

  // Connect to MongoDB
  session, err := mgo.Dial(config.MongoUrl + ":" + config.MongoPort)
  if err != nil {
    panic(err)
  }
  // close Mongo session when server terminates
  defer session.Close()

  // Start auto updater
  go UpdateShuttles(config.DataFeed, config.UpdateInterval, session.Copy())

  // Routing
  r := mux.NewRouter()
  r.HandleFunc("/", IndexHandler).Methods("GET")
  r.HandleFunc("/admin", IndexHandler).Methods("GET")
  r.HandleFunc("/vehicles", VehiclesHandler).Methods("GET")
  // Static files
  r.PathPrefix("/bower_components/").Handler(http.StripPrefix("/bower_components/", http.FileServer(http.Dir("bower_components/"))))
  r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))
  // Serve requests
  http.Handle("/", r)
  http.ListenAndServe(":8080", r)
}<commit_msg>Fix issue with struct field names that prevented storing new updates with MongoDB<commit_after>package main

import (
  "os"
  "fmt"
  "time"
  "strings"
  "net/http"
  "io/ioutil"
  "regexp"
  "encoding/json"
  "gopkg.in/mgo.v2"
  "gopkg.in/mgo.v2/bson"
  "github.com/gorilla/mux"
)

/**
 *  Shuttle Tracker
 *   Auto Updater - send request to iTrak API,
 *                  get updated shuttle info,
 *                  store updated records in db
 */

type VehicleUpdate struct {
  Id          bson.ObjectId                 `bson:"_id,omitempty"`
  VehicleId   string     `json:"vehicleId"   bson:"vehicleId,omitempty"`
  Lat         string     `json:"lat"         bson:"lat"`
  Lng         string     `json:"lng"         bson:"lng"`
  Heading     string     `json:"heading"     bson:"heading"`
  Speed       string     `json:"speed"       bson:"speed"`
  Lock        string     `json:"lock"        bson:"lock"`
  Time        string     `json:"time"        bson:"time"`
  Date        string     `json:"date"        bson:"date"`
  Status      string     `json:"status"      bson:"status"`
  Created     time.Time  `json:"created"     bson:"created"`
}

func UpdateShuttles(dataFeed string, updateInterval int, session *mgo.Session) {
  for {
    // Reference updates collection and close db session upon exit
    UpdatesCollection := session.DB("shuttle_tracking").C("updates")
    defer session.Close()

    // Make request to our tracking data feed
    resp, err := http.Get(dataFeed)
    if err != nil {
      continue;
    }
    defer resp.Body.Close()

    // Read response body content
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
      continue;
    }

    delim := "eof"
    // Iterate through all vehicles returned by data feed
    vehicles_data := strings.Split(string(body), delim)
    for i := 1; i < len(vehicles_data)-1; i++ {

      // Match eatch API field with any number (+)
      //   of the previous expressions (\d digit, \. escaped period, - negative number)
      //   Specify named capturing groups to store each field from data feed
      re := regexp.MustCompile(`(?P<id>Vehicle ID:([\d\.]+)) (?P<lat>lat:([\d\.-]+)) (?P<lng>lon:([\d\.-]+)) (?P<heading>dir:([\d\.-]+)) (?P<speed>spd:([\d\.-]+)) (?P<lock>lck:([\d\.-]+)) (?P<time>time:([\d]+)) (?P<date>date:([\d]+)) (?P<status>trig:([\d]+))`)
      n := re.SubexpNames()
      match := re.FindAllStringSubmatch(vehicles_data[i], -1)[0]

      // Store named capturing group and matching expression as a key value pair
      result := map[string]string{}
      for i, item := range match {
        result[n[i]] = item
      }

      // Create new vehicle update & insert update into database
      update := VehicleUpdate {
        Id:        bson.NewObjectId(),
        VehicleId: strings.Replace(result["id"], "Vehicle ID:", "", -1),
        Lat:       strings.Replace(result["lat"], "lat:", "", -1),
        Lng:       strings.Replace(result["lng"], "lon:", "", -1),
        Heading:   strings.Replace(result["heading"], "dir:", "", -1),
        Speed:     strings.Replace(result["speed"], "spd:", "", -1),
        Lock:      strings.Replace(result["lock"], "lck:", "", -1),
        Time:      strings.Replace(result["time"], "time:", "", -1),
        Date:      strings.Replace(result["date"], "date:", "", -1),
        Status:    strings.Replace(result["status"], "trig:", "", -1),
        Created:   time.Now()}

      err := UpdatesCollection.Insert(&update)

      if err != nil {
        fmt.Println(err)
      } else {
        fmt.Println(update)
      }
    }

    // Sleep for n seconds before updating again
    time.Sleep(time.Duration(updateInterval) * time.Second)
  }
}

/**
 *  Route handlers - API requests,
 *                   serve view files
 */

func IndexHandler(w http.ResponseWriter, r *http.Request) {
  http.ServeFile(w, r, "index.html")
}

func VehiclesHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Vehicles")
}

/**
 *  Main - connect to database,
 *         handle routing,
 *         start tracker go routine,
 *         serve requests
 */

type Configuration struct {
  DataFeed        string
  UpdateInterval  int
  MongoUrl        string
  MongoPort       string
}

func ReadConfiguration(fileName string) Configuration {
  // Open config file and decode JSON to Configuration struct
  file, _ := os.Open(fileName)
  decoder := json.NewDecoder(file)
  config := Configuration{}
  err := decoder.Decode(&config)
  if err != nil {
    fmt.Print("Unable to read config file: ")
    panic(err)
  }
  return config
}

func main() {
  // Read app configuration file
  config := ReadConfiguration("conf.json")

  // Connect to MongoDB
  session, err := mgo.Dial(config.MongoUrl + ":" + config.MongoPort)
  if err != nil {
    panic(err)
  }
  // close Mongo session when server terminates
  defer session.Close()

  // Start auto updater
  go UpdateShuttles(config.DataFeed, config.UpdateInterval, session.Copy())

  // Routing
  r := mux.NewRouter()
  r.HandleFunc("/", IndexHandler).Methods("GET")
  r.HandleFunc("/admin", IndexHandler).Methods("GET")
  r.HandleFunc("/vehicles", VehiclesHandler).Methods("GET")
  // Static files
  r.PathPrefix("/bower_components/").Handler(http.StripPrefix("/bower_components/", http.FileServer(http.Dir("bower_components/"))))
  r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))
  // Serve requests
  http.Handle("/", r)
  http.ListenAndServe(":8080", r)
}<|endoftext|>


<commit_before>// Copyright 2013 mongoapi 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 main

import (
	"github.com/bmizerany/pat"
	"log"
	"net/http"
)

func main() {
	m := pat.New()
	m.Post("/resources", http.HandlerFunc(Add))
	m.Post("/resources/:name", Handler(Bind))
	m.Del("/resources/:name/hostname/:hostname", Handler(Unbind))
	m.Del("/resources/:name", Handler(Remove))
	m.Get("/resources/:name/status", Handler(Status))
	listen := coalesceEnv("0.0.0.0:3333", "MONGODB_API_LISTEN")
	log.Fatal(http.ListenAndServe(listen, m))
}
<commit_msg>main: add flag to print version information<commit_after>// Copyright 2013 mongoapi 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 main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"log"
	"net/http"
)

const version = "0.1"

var printVersion bool

func init() {
	flag.BoolVar(&printVersion, "v", false, "Print version and exit")
	flag.Parse()
}

func buildMux() *pat.PatternServeMux {
	m := pat.New()
	m.Post("/resources", http.HandlerFunc(Add))
	m.Post("/resources/:name", Handler(Bind))
	m.Del("/resources/:name/hostname/:hostname", Handler(Unbind))
	m.Del("/resources/:name", Handler(Remove))
	m.Get("/resources/:name/status", Handler(Status))
	return m
}

func main() {
	if printVersion {
		fmt.Printf("mongoapi version %s", version)
		return
	}
	listen := coalesceEnv("0.0.0.0:3333", "MONGODB_API_LISTEN")
	log.Fatal(http.ListenAndServe(listen, buildMux()))
}
<|endoftext|>


<commit_before>package router

import (
	"context"
	"fmt"
	"net/http"

	"github.com/containous/alice"
	"github.com/containous/traefik/pkg/config"
	"github.com/containous/traefik/pkg/log"
	"github.com/containous/traefik/pkg/middlewares/accesslog"
	"github.com/containous/traefik/pkg/middlewares/recovery"
	"github.com/containous/traefik/pkg/middlewares/tracing"
	"github.com/containous/traefik/pkg/responsemodifiers"
	"github.com/containous/traefik/pkg/rules"
	"github.com/containous/traefik/pkg/server/internal"
	"github.com/containous/traefik/pkg/server/middleware"
	"github.com/containous/traefik/pkg/server/service"
)

const (
	recoveryMiddlewareName = "traefik-internal-recovery"
)

// NewManager Creates a new Manager
func NewManager(routers map[string]*config.Router,
	serviceManager *service.Manager, middlewaresBuilder *middleware.Builder, modifierBuilder *responsemodifiers.Builder,
) *Manager {
	return &Manager{
		routerHandlers:     make(map[string]http.Handler),
		configs:            routers,
		serviceManager:     serviceManager,
		middlewaresBuilder: middlewaresBuilder,
		modifierBuilder:    modifierBuilder,
	}
}

// Manager A route/router manager
type Manager struct {
	routerHandlers     map[string]http.Handler
	configs            map[string]*config.Router
	serviceManager     *service.Manager
	middlewaresBuilder *middleware.Builder
	modifierBuilder    *responsemodifiers.Builder
}

// BuildHandlers Builds handler for all entry points
func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string, tls bool) map[string]http.Handler {
	entryPointsRouters := m.filteredRouters(rootCtx, entryPoints, tls)

	entryPointHandlers := make(map[string]http.Handler)
	for entryPointName, routers := range entryPointsRouters {
		entryPointName := entryPointName
		ctx := log.With(rootCtx, log.Str(log.EntryPointName, entryPointName))

		handler, err := m.buildEntryPointHandler(ctx, routers)
		if err != nil {
			log.FromContext(ctx).Error(err)
			continue
		}

		handlerWithAccessLog, err := alice.New(func(next http.Handler) (http.Handler, error) {
			return accesslog.NewFieldHandler(next, log.EntryPointName, entryPointName, accesslog.AddOriginFields), nil
		}).Then(handler)
		if err != nil {
			log.FromContext(ctx).Error(err)
			entryPointHandlers[entryPointName] = handler
		} else {
			entryPointHandlers[entryPointName] = handlerWithAccessLog
		}
	}

	m.serviceManager.LaunchHealthCheck()

	return entryPointHandlers
}

func contains(entryPoints []string, entryPointName string) bool {
	for _, name := range entryPoints {
		if name == entryPointName {
			return true
		}
	}
	return false
}

func (m *Manager) filteredRouters(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*config.Router {
	entryPointsRouters := make(map[string]map[string]*config.Router)

	for rtName, rt := range m.configs {
		if (tls && rt.TLS == nil) || (!tls && rt.TLS != nil) {
			continue
		}

		eps := rt.EntryPoints
		if len(eps) == 0 {
			eps = entryPoints
		}
		for _, entryPointName := range eps {
			if !contains(entryPoints, entryPointName) {
				log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))).
					Errorf("entryPoint %q doesn't exist", entryPointName)
				continue
			}

			if _, ok := entryPointsRouters[entryPointName]; !ok {
				entryPointsRouters[entryPointName] = make(map[string]*config.Router)
			}

			entryPointsRouters[entryPointName][rtName] = rt
		}
	}

	return entryPointsRouters
}

func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string]*config.Router) (http.Handler, error) {
	router, err := rules.NewRouter()
	if err != nil {
		return nil, err
	}

	for routerName, routerConfig := range configs {
		ctxRouter := log.With(ctx, log.Str(log.RouterName, routerName))
		logger := log.FromContext(ctxRouter)

		ctxRouter = internal.AddProviderInContext(ctxRouter, routerName)

		handler, err := m.buildRouterHandler(ctxRouter, routerName)
		if err != nil {
			logger.Error(err)
			continue
		}

		err = router.AddRoute(routerConfig.Rule, routerConfig.Priority, handler)
		if err != nil {
			logger.Error(err)
			continue
		}
	}

	router.SortRoutes()

	chain := alice.New()
	chain = chain.Append(func(next http.Handler) (http.Handler, error) {
		return recovery.New(ctx, next, recoveryMiddlewareName)
	})

	return chain.Then(router)
}

func (m *Manager) buildRouterHandler(ctx context.Context, routerName string) (http.Handler, error) {
	if handler, ok := m.routerHandlers[routerName]; ok {
		return handler, nil
	}

	configRouter, ok := m.configs[routerName]
	if !ok {
		return nil, fmt.Errorf("no configuration for %s", routerName)
	}

	handler, err := m.buildHTTPHandler(ctx, configRouter, routerName)
	if err != nil {
		return nil, err
	}

	handlerWithAccessLog, err := alice.New(func(next http.Handler) (http.Handler, error) {
		return accesslog.NewFieldHandler(next, accesslog.RouterName, routerName, nil), nil
	}).Then(handler)
	if err != nil {
		log.FromContext(ctx).Error(err)
		m.routerHandlers[routerName] = handler
	} else {
		m.routerHandlers[routerName] = handlerWithAccessLog
	}

	return m.routerHandlers[routerName], nil
}

func (m *Manager) buildHTTPHandler(ctx context.Context, router *config.Router, routerName string) (http.Handler, error) {
	rm := m.modifierBuilder.Build(ctx, router.Middlewares)

	sHandler, err := m.serviceManager.BuildHTTP(ctx, router.Service, rm)
	if err != nil {
		return nil, err
	}

	mHandler := m.middlewaresBuilder.BuildChain(ctx, router.Middlewares)

	tHandler := func(next http.Handler) (http.Handler, error) {
		return tracing.NewForwarder(ctx, routerName, router.Service, next), nil
	}

	return alice.New().Extend(*mHandler).Append(tHandler).Then(sHandler)
}
<commit_msg>Fix response modifier initial building<commit_after>package router

import (
	"context"
	"fmt"
	"net/http"

	"github.com/containous/alice"
	"github.com/containous/traefik/pkg/config"
	"github.com/containous/traefik/pkg/log"
	"github.com/containous/traefik/pkg/middlewares/accesslog"
	"github.com/containous/traefik/pkg/middlewares/recovery"
	"github.com/containous/traefik/pkg/middlewares/tracing"
	"github.com/containous/traefik/pkg/responsemodifiers"
	"github.com/containous/traefik/pkg/rules"
	"github.com/containous/traefik/pkg/server/internal"
	"github.com/containous/traefik/pkg/server/middleware"
	"github.com/containous/traefik/pkg/server/service"
)

const (
	recoveryMiddlewareName = "traefik-internal-recovery"
)

// NewManager Creates a new Manager
func NewManager(routers map[string]*config.Router,
	serviceManager *service.Manager, middlewaresBuilder *middleware.Builder, modifierBuilder *responsemodifiers.Builder,
) *Manager {
	return &Manager{
		routerHandlers:     make(map[string]http.Handler),
		configs:            routers,
		serviceManager:     serviceManager,
		middlewaresBuilder: middlewaresBuilder,
		modifierBuilder:    modifierBuilder,
	}
}

// Manager A route/router manager
type Manager struct {
	routerHandlers     map[string]http.Handler
	configs            map[string]*config.Router
	serviceManager     *service.Manager
	middlewaresBuilder *middleware.Builder
	modifierBuilder    *responsemodifiers.Builder
}

// BuildHandlers Builds handler for all entry points
func (m *Manager) BuildHandlers(rootCtx context.Context, entryPoints []string, tls bool) map[string]http.Handler {
	entryPointsRouters := m.filteredRouters(rootCtx, entryPoints, tls)

	entryPointHandlers := make(map[string]http.Handler)
	for entryPointName, routers := range entryPointsRouters {
		entryPointName := entryPointName
		ctx := log.With(rootCtx, log.Str(log.EntryPointName, entryPointName))

		handler, err := m.buildEntryPointHandler(ctx, routers)
		if err != nil {
			log.FromContext(ctx).Error(err)
			continue
		}

		handlerWithAccessLog, err := alice.New(func(next http.Handler) (http.Handler, error) {
			return accesslog.NewFieldHandler(next, log.EntryPointName, entryPointName, accesslog.AddOriginFields), nil
		}).Then(handler)
		if err != nil {
			log.FromContext(ctx).Error(err)
			entryPointHandlers[entryPointName] = handler
		} else {
			entryPointHandlers[entryPointName] = handlerWithAccessLog
		}
	}

	m.serviceManager.LaunchHealthCheck()

	return entryPointHandlers
}

func contains(entryPoints []string, entryPointName string) bool {
	for _, name := range entryPoints {
		if name == entryPointName {
			return true
		}
	}
	return false
}

func (m *Manager) filteredRouters(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*config.Router {
	entryPointsRouters := make(map[string]map[string]*config.Router)

	for rtName, rt := range m.configs {
		if (tls && rt.TLS == nil) || (!tls && rt.TLS != nil) {
			continue
		}

		eps := rt.EntryPoints
		if len(eps) == 0 {
			eps = entryPoints
		}
		for _, entryPointName := range eps {
			if !contains(entryPoints, entryPointName) {
				log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))).
					Errorf("entryPoint %q doesn't exist", entryPointName)
				continue
			}

			if _, ok := entryPointsRouters[entryPointName]; !ok {
				entryPointsRouters[entryPointName] = make(map[string]*config.Router)
			}

			entryPointsRouters[entryPointName][rtName] = rt
		}
	}

	return entryPointsRouters
}

func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string]*config.Router) (http.Handler, error) {
	router, err := rules.NewRouter()
	if err != nil {
		return nil, err
	}

	for routerName, routerConfig := range configs {
		ctxRouter := log.With(ctx, log.Str(log.RouterName, routerName))
		logger := log.FromContext(ctxRouter)

		ctxRouter = internal.AddProviderInContext(ctxRouter, routerName)

		handler, err := m.buildRouterHandler(ctxRouter, routerName)
		if err != nil {
			logger.Error(err)
			continue
		}

		err = router.AddRoute(routerConfig.Rule, routerConfig.Priority, handler)
		if err != nil {
			logger.Error(err)
			continue
		}
	}

	router.SortRoutes()

	chain := alice.New()
	chain = chain.Append(func(next http.Handler) (http.Handler, error) {
		return recovery.New(ctx, next, recoveryMiddlewareName)
	})

	return chain.Then(router)
}

func (m *Manager) buildRouterHandler(ctx context.Context, routerName string) (http.Handler, error) {
	if handler, ok := m.routerHandlers[routerName]; ok {
		return handler, nil
	}

	configRouter, ok := m.configs[routerName]
	if !ok {
		return nil, fmt.Errorf("no configuration for %s", routerName)
	}

	handler, err := m.buildHTTPHandler(ctx, configRouter, routerName)
	if err != nil {
		return nil, err
	}

	handlerWithAccessLog, err := alice.New(func(next http.Handler) (http.Handler, error) {
		return accesslog.NewFieldHandler(next, accesslog.RouterName, routerName, nil), nil
	}).Then(handler)
	if err != nil {
		log.FromContext(ctx).Error(err)
		m.routerHandlers[routerName] = handler
	} else {
		m.routerHandlers[routerName] = handlerWithAccessLog
	}

	return m.routerHandlers[routerName], nil
}

func (m *Manager) buildHTTPHandler(ctx context.Context, router *config.Router, routerName string) (http.Handler, error) {
	qualifiedNames := make([]string, len(router.Middlewares))
	for i, name := range router.Middlewares {
		qualifiedNames[i] = internal.GetQualifiedName(ctx, name)
	}
	rm := m.modifierBuilder.Build(ctx, qualifiedNames)

	sHandler, err := m.serviceManager.BuildHTTP(ctx, router.Service, rm)
	if err != nil {
		return nil, err
	}

	mHandler := m.middlewaresBuilder.BuildChain(ctx, router.Middlewares)

	tHandler := func(next http.Handler) (http.Handler, error) {
		return tracing.NewForwarder(ctx, routerName, router.Service, next), nil
	}

	return alice.New().Extend(*mHandler).Append(tHandler).Then(sHandler)
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/albertyw/reaction-pics/server"
	"github.com/albertyw/reaction-pics/tumblr"
	"github.com/joho/godotenv"
	newrelic "github.com/newrelic/go-agent"
	"github.com/stvp/rollbar"
)

func setupEnv() {
	err := godotenv.Load()
	if err != nil {
		fmt.Println("Cannot load dotenv")
		fmt.Println(err)
		os.Exit(1)
	}
}

func getNewRelicApp() newrelic.Application {
	newrelicKey := os.Getenv("NEWRELIC_KEY")
	config := newrelic.NewConfig("Reaction.pics", newrelicKey)
	app, err := newrelic.NewApplication(config)
	if err != nil {
		panic(err)
	}
	return app
}

func setupRollbar() {
	rollbar.Token = os.Getenv("ROLLBAR_SERVER_TOKEN")
	rollbar.Environment = os.Getenv("ENVIRONMENT")
}

func main() {
	setupEnv()
	newrelicApp := getNewRelicApp()
	posts := make(chan tumblr.Post)
	go tumblr.GetPosts(posts)
	server.Run(posts, newrelicApp)
}
<commit_msg>Fix env loading<commit_after>package main

import (
	"os"

	"github.com/albertyw/reaction-pics/server"
	"github.com/albertyw/reaction-pics/tumblr"
	"github.com/joho/godotenv"
	newrelic "github.com/newrelic/go-agent"
	"github.com/stvp/rollbar"
)

func setupEnv() {
	err := godotenv.Load()
	if err != nil {
		panic(err)
	}
}

func getNewRelicApp() newrelic.Application {
	newrelicKey := os.Getenv("NEWRELIC_KEY")
	config := newrelic.NewConfig("Reaction.pics", newrelicKey)
	app, err := newrelic.NewApplication(config)
	if err != nil {
		panic(err)
	}
	return app
}

func setupRollbar() {
	rollbar.Token = os.Getenv("ROLLBAR_SERVER_TOKEN")
	rollbar.Environment = os.Getenv("ENVIRONMENT")
}

func main() {
	setupEnv()
	newrelicApp := getNewRelicApp()
	posts := make(chan tumblr.Post)
	go tumblr.GetPosts(posts)
	server.Run(posts, newrelicApp)
}
<|endoftext|>


<commit_before>package server

import (
	"fmt"
	"github.com/Frostman/aptomi/pkg/slinga"
	"net/http"
)

func endpointsHandler(w http.ResponseWriter, r *http.Request) {
	// Load the previous usage state
	state := slinga.LoadServiceUsageState()

	endpoints := state.Endpoints()

	writeJSON(w, endpoints)
}

// Serve starts http server on specified address that serves Aptomi API and WebUI
func Serve(host string, port int) {
	// redirect from "/" to "/ui/"
	http.Handle("/", http.RedirectHandler("/ui/", http.StatusPermanentRedirect))

	// serve all files from "webui" folder and require auth for everything except login.html
	http.Handle("/ui/", staticFilesHandler("/ui/", http.Dir("./webui/")))

	// serve all API endpoints at /api/ path and require auth
	http.Handle("/api/endpoints", requireAuth(endpointsHandler))

	// serve login/logout api without auth
	http.HandleFunc("/api/login", loginHandler)
	http.HandleFunc("/api/logout", logoutHandler)

	listenAddr := fmt.Sprintf("%s:%d", host, port)
	fmt.Println("Serving at", listenAddr)
	// todo better handle error returned from ListenAndServe (path to Fatal??)
	panic(http.ListenAndServe(listenAddr, nil))
}
<commit_msg>Serve favicon.ico on the root<commit_after>package server

import (
	"fmt"
	"github.com/Frostman/aptomi/pkg/slinga"
	"net/http"
)

func faviconHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "./webui/favicon.ico")
}

func endpointsHandler(w http.ResponseWriter, r *http.Request) {
	// Load the previous usage state
	state := slinga.LoadServiceUsageState()

	endpoints := state.Endpoints()

	writeJSON(w, endpoints)
}

// Serve starts http server on specified address that serves Aptomi API and WebUI
func Serve(host string, port int) {
	http.HandleFunc("/favicon.ico", faviconHandler)

	// redirect from "/" to "/ui/"
	http.Handle("/", http.RedirectHandler("/ui/", http.StatusPermanentRedirect))

	// serve all files from "webui" folder and require auth for everything except login.html
	http.Handle("/ui/", staticFilesHandler("/ui/", http.Dir("./webui/")))

	// serve all API endpoints at /api/ path and require auth
	http.Handle("/api/endpoints", requireAuth(endpointsHandler))

	// serve login/logout api without auth
	http.HandleFunc("/api/login", loginHandler)
	http.HandleFunc("/api/logout", logoutHandler)

	listenAddr := fmt.Sprintf("%s:%d", host, port)
	fmt.Println("Serving at", listenAddr)
	// todo better handle error returned from ListenAndServe (path to Fatal??)
	panic(http.ListenAndServe(listenAddr, nil))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"reflect"
	"sync"

	"github.com/docker/docker/pkg/units"
	"github.com/fsouza/go-dockerclient"
	"github.com/namsral/flag"
)

func main() {
	var dockerHost string
	var dockerTLSVerify bool
	var dockerCertPath string

	flag.StringVar(&dockerHost, "docker-host", "unix:///var/run/docker.sock", "address of Docker host")
	flag.BoolVar(&dockerTLSVerify, "docker-tls-verify", false, "use TLS client for Docker")
	flag.StringVar(&dockerCertPath, "docker-cert-path", "", "path to the cert.pem, key.pem, and ca.pem for authenticating to Docker")
	flag.Parse()

	client := dockerClient(dockerHost, dockerTLSVerify, dockerCertPath)

	s := newSelector()

	log.Println("Querying for stats...")

	containers, err := client.ListContainers(docker.ListContainersOptions{All: true})
	if err != nil {
		panic(err)
	}
	listenChan := make(chan *docker.APIEvents)
	client.AddEventListener(listenChan)
	go func() {
		for {
			event := <-listenChan

			if event.Status == "start" {
				w := newWatcher(event.ID[:12], client)
				s.Add(w)
				go w.Watch()
			}
		}
	}()

	for _, cont := range containers {
		w := newWatcher(cont.ID[:12], client)
		s.Add(w)
		go w.Watch()
	}

	log.Println("Waiting for stats...")
	s.Select()
}

type watcher struct {
	Name    string
	Stats   *stats
	Updates chan *docker.Stats
	client  *docker.Client
}

func newWatcher(name string, client *docker.Client) *watcher {
	return &watcher{
		Name:    name,
		Stats:   newStats(),
		Updates: make(chan *docker.Stats, 0),
		client:  client,
	}
}

func (w *watcher) Watch() {
	w.client.Stats(docker.StatsOptions{
		ID:    w.Name,
		Stats: w.Updates,
	})
}

type selector struct {
	cases    []reflect.SelectCase
	watchers []*watcher
	mu       sync.RWMutex
}

func newSelector() *selector {
	return &selector{
		cases:    make([]reflect.SelectCase, 0),
		watchers: make([]*watcher, 0),
	}
}

func (s *selector) Add(w *watcher) {
	s.mu.Lock()
	defer s.mu.Unlock()

	s.cases = append(s.cases, reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(w.Updates)})
	s.watchers = append(s.watchers, w)
}

func (s *selector) remove(i int) {
	s.mu.Lock()
	defer s.mu.Unlock()

	s.cases = append(s.cases[:i], s.cases[i+1:]...)
	s.watchers = append(s.watchers[:i], s.watchers[i+1:]...)
}

func (s *selector) Select() {
	for {
		chosen, value, ok := reflect.Select(s.cases)
		s.mu.Lock()
		w := s.watchers[chosen]
		s.mu.Unlock()

		if !ok {
			s.remove(chosen)
			continue
		}

		switch value.Kind() {
		case reflect.Ptr:
			ds := value.Elem().Interface().(docker.Stats)
			w.Stats.Update(&ds)
			w.Display()
		}

	}
}

type stats struct {
	CPUPercentage    float64
	Memory           float64
	MemoryLimit      float64
	MemoryPercentage float64
	NetworkRx        float64
	NetworkTx        float64

	previousCPUUsage       float64
	previousSystemCPUUsage float64
	cpuUsage               float64
	numberCPUs             float64
	systemCPUUsage         float64
	mu                     sync.RWMutex
}

func newStats() *stats {
	return &stats{
		cpuUsage:       0.0,
		systemCPUUsage: 0.0,
		CPUPercentage:  0.0,
	}
}

func (s *stats) Update(d *docker.Stats) {
	s.mu.Lock()
	s.previousCPUUsage = s.cpuUsage
	s.previousSystemCPUUsage = s.systemCPUUsage
	s.numberCPUs = float64(len(d.CPUStats.CPUUsage.PercpuUsage))
	s.cpuUsage = float64(d.CPUStats.CPUUsage.TotalUsage)
	s.systemCPUUsage = float64(d.CPUStats.SystemCPUUsage)
	s.calculateCPUPercentage()
	s.Memory = float64(d.MemoryStats.Usage)
	s.MemoryLimit = float64(d.MemoryStats.Limit)
	s.calculateMemoryPercentage()
	s.NetworkRx = float64(d.Network.RxBytes)
	s.NetworkTx = float64(d.Network.TxBytes)
	s.mu.Unlock()
}

func (s *stats) String() string {
	s.mu.RLock()
	defer s.mu.RUnlock()

	return fmt.Sprintf("%.2f%%\t%s/%s\t%.2f%%\t%s/%s",
		s.CPUPercentage,
		units.HumanSize(s.Memory), units.HumanSize(s.MemoryLimit),
		s.MemoryPercentage,
		units.HumanSize(s.NetworkRx), units.HumanSize(s.NetworkTx))
}

func (w *watcher) Display() {
	fmt.Printf("%s\t%s\n", w.Name, w.Stats.String())
}

func (s *stats) calculateMemoryPercentage() {
	s.MemoryPercentage = s.Memory / s.MemoryLimit * 100.0
}

func (s *stats) calculateCPUPercentage() {
	var (
		cpuPercent = 0.0
		// calculate the change for the cpu usage of the container in between readings
		cpuDelta = float64(s.cpuUsage - s.previousCPUUsage)
		// calculate the change for the entire system between readings
		systemDelta = float64(s.systemCPUUsage - s.previousSystemCPUUsage)
	)

	if systemDelta > 0.0 && cpuDelta > 0.0 {
		cpuPercent = (cpuDelta / systemDelta) * s.numberCPUs * 100.0
	}

	s.CPUPercentage = cpuPercent
}

func dockerClient(host string, tls bool, certPath string) *docker.Client {
	var client *docker.Client
	var err error

	if tls {
		cert := fmt.Sprintf("%s/cert.pem", certPath)
		key := fmt.Sprintf("%s/key.pem", certPath)
		ca := fmt.Sprintf("%s/ca.pem", certPath)
		client, err = docker.NewTLSClient(host, cert, key, ca)
	} else {
		client, err = docker.NewClient(host)
	}

	if err != nil {
		log.Fatal(err)
	}

	return client
}
<commit_msg>Make sure we only watch running containers and add some log output for what we're watching.<commit_after>package main

import (
	"fmt"
	"log"
	"reflect"
	"sync"

	"github.com/docker/docker/pkg/units"
	"github.com/fsouza/go-dockerclient"
	"github.com/namsral/flag"
)

func main() {
	var dockerHost string
	var dockerTLSVerify bool
	var dockerCertPath string

	flag.StringVar(&dockerHost, "docker-host", "unix:///var/run/docker.sock", "address of Docker host")
	flag.BoolVar(&dockerTLSVerify, "docker-tls-verify", false, "use TLS client for Docker")
	flag.StringVar(&dockerCertPath, "docker-cert-path", "", "path to the cert.pem, key.pem, and ca.pem for authenticating to Docker")
	flag.Parse()

	client := dockerClient(dockerHost, dockerTLSVerify, dockerCertPath)

	s := newSelector()

	log.Println("Querying for stats...")

	containers, err := client.ListContainers(docker.ListContainersOptions{
		All: true,
		Filters: map[string][]string{
			"status": []string{"running"},
		},
	})
	if err != nil {
		panic(err)
	}
	listenChan := make(chan *docker.APIEvents)
	client.AddEventListener(listenChan)
	go func() {
		for {
			event := <-listenChan

			if event.Status == "start" {
				w := newWatcher(event.ID[:12], client)
				s.Add(w)
				go w.Watch()
			}
		}
	}()

	for _, cont := range containers {
		w := newWatcher(cont.ID[:12], client)
		s.Add(w)
		go w.Watch()
	}

	log.Println("Waiting for stats...")
	s.Select()
}

type watcher struct {
	Name    string
	Stats   *stats
	Updates chan *docker.Stats
	client  *docker.Client
}

func newWatcher(name string, client *docker.Client) *watcher {
	return &watcher{
		Name:    name,
		Stats:   newStats(),
		Updates: make(chan *docker.Stats, 0),
		client:  client,
	}
}

func (w *watcher) Watch() {
	fmt.Printf("Watching %s...\n", w.Name)
	w.client.Stats(docker.StatsOptions{
		ID:    w.Name,
		Stats: w.Updates,
	})
}

type selector struct {
	cases    []reflect.SelectCase
	watchers []*watcher
	mu       sync.RWMutex
}

func newSelector() *selector {
	return &selector{
		cases:    make([]reflect.SelectCase, 0),
		watchers: make([]*watcher, 0),
	}
}

func (s *selector) Add(w *watcher) {
	s.mu.Lock()
	defer s.mu.Unlock()

	s.cases = append(s.cases, reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(w.Updates)})
	s.watchers = append(s.watchers, w)
}

func (s *selector) remove(i int) {
	s.mu.Lock()
	defer s.mu.Unlock()

	s.cases = append(s.cases[:i], s.cases[i+1:]...)
	s.watchers = append(s.watchers[:i], s.watchers[i+1:]...)
}

func (s *selector) Select() {
	for {
		chosen, value, ok := reflect.Select(s.cases)
		s.mu.Lock()
		w := s.watchers[chosen]
		s.mu.Unlock()

		if !ok {
			fmt.Printf("Closing %s...\n", w.Name)
			s.remove(chosen)
			continue
		}

		switch value.Kind() {
		case reflect.Ptr:
			ds := value.Elem().Interface().(docker.Stats)
			w.Stats.Update(&ds)
			w.Display()
		}

	}
}

type stats struct {
	CPUPercentage    float64
	Memory           float64
	MemoryLimit      float64
	MemoryPercentage float64
	NetworkRx        float64
	NetworkTx        float64

	previousCPUUsage       float64
	previousSystemCPUUsage float64
	cpuUsage               float64
	numberCPUs             float64
	systemCPUUsage         float64
	mu                     sync.RWMutex
}

func newStats() *stats {
	return &stats{
		cpuUsage:       0.0,
		systemCPUUsage: 0.0,
		CPUPercentage:  0.0,
	}
}

func (s *stats) Update(d *docker.Stats) {
	s.mu.Lock()
	s.previousCPUUsage = s.cpuUsage
	s.previousSystemCPUUsage = s.systemCPUUsage
	s.numberCPUs = float64(len(d.CPUStats.CPUUsage.PercpuUsage))
	s.cpuUsage = float64(d.CPUStats.CPUUsage.TotalUsage)
	s.systemCPUUsage = float64(d.CPUStats.SystemCPUUsage)
	s.calculateCPUPercentage()
	s.Memory = float64(d.MemoryStats.Usage)
	s.MemoryLimit = float64(d.MemoryStats.Limit)
	s.calculateMemoryPercentage()
	s.NetworkRx = float64(d.Network.RxBytes)
	s.NetworkTx = float64(d.Network.TxBytes)
	s.mu.Unlock()
}

func (s *stats) String() string {
	s.mu.RLock()
	defer s.mu.RUnlock()

	return fmt.Sprintf("%.2f%%\t%s/%s\t%.2f%%\t%s/%s",
		s.CPUPercentage,
		units.HumanSize(s.Memory), units.HumanSize(s.MemoryLimit),
		s.MemoryPercentage,
		units.HumanSize(s.NetworkRx), units.HumanSize(s.NetworkTx))
}

func (w *watcher) Display() {
	fmt.Printf("%s\t%s\n", w.Name, w.Stats.String())
}

func (s *stats) calculateMemoryPercentage() {
	s.MemoryPercentage = s.Memory / s.MemoryLimit * 100.0
}

func (s *stats) calculateCPUPercentage() {
	var (
		cpuPercent = 0.0
		// calculate the change for the cpu usage of the container in between readings
		cpuDelta = float64(s.cpuUsage - s.previousCPUUsage)
		// calculate the change for the entire system between readings
		systemDelta = float64(s.systemCPUUsage - s.previousSystemCPUUsage)
	)

	if systemDelta > 0.0 && cpuDelta > 0.0 {
		cpuPercent = (cpuDelta / systemDelta) * s.numberCPUs * 100.0
	}

	s.CPUPercentage = cpuPercent
}

func dockerClient(host string, tls bool, certPath string) *docker.Client {
	var client *docker.Client
	var err error

	if tls {
		cert := fmt.Sprintf("%s/cert.pem", certPath)
		key := fmt.Sprintf("%s/key.pem", certPath)
		ca := fmt.Sprintf("%s/ca.pem", certPath)
		client, err = docker.NewTLSClient(host, cert, key, ca)
	} else {
		client, err = docker.NewClient(host)
	}

	if err != nil {
		log.Fatal(err)
	}

	return client
}
<|endoftext|>


<commit_before>package stackit

import (
	"fmt"
	"github.com/fatih/color"
	"io"
	"os"
	"strings"
)

type TailPrinter struct {
	timestampFormat string
	successColor    *color.Color
	failureColor    *color.Color
	writer          io.Writer
}

func NewTailPrinter() TailPrinter {
	return NewTailPrinterWithOptions(true, true, os.Stderr)
}

func NewTailPrinterWithOptions(showTimestamp, showColors bool, writer io.Writer) TailPrinter {
	format := ""
	if showTimestamp {
		format = "[03:04:05]"
	}

	successColor := color.New(color.FgGreen)
	failureColor := color.New(color.FgRed)

	if !showColors {
		successColor = nil
		failureColor = nil
	}

	return TailPrinter{
		timestampFormat: format,
		successColor:    successColor,
		failureColor:    failureColor,
		writer:          writer,
	}
}

func (tp *TailPrinter) FormatTailEvent(tailEvent TailStackEvent) string {
	resourceNameLength := 20 // TODO: determine this from template/API

	timestampPrefix := tailEvent.Timestamp.Format(tp.timestampFormat)

	reasonPart := ""
	if tailEvent.ResourceStatusReason != nil {
		reasonPart = fmt.Sprintf("- %s", *tailEvent.ResourceStatusReason)
	}

	line := fmt.Sprintf("%s %s - %s %s", timestampPrefix, fixedLengthString(resourceNameLength, *tailEvent.LogicalResourceId), *tailEvent.ResourceStatus, reasonPart)

	if isBadStatus(*tailEvent.ResourceStatus) && tp.failureColor != nil {
		return tp.failureColor.Sprint(line)
	} else {
		return line
	}
}

func (tp *TailPrinter) PrintTailEvent(tailEvent TailStackEvent) {
	line := tp.FormatTailEvent(tailEvent)
	tp.writer.Write([]byte(line))
	tp.writer.Write([]byte("\n"))
}

func fixedLengthString(length int, str string) string {
	verb := fmt.Sprintf("%%%d.%ds", length, length)
	return fmt.Sprintf(verb, str)
}

func isBadStatus(status string) bool {
	return strings.HasSuffix(status, "_FAILED")
}
<commit_msg>successColor is unused<commit_after>package stackit

import (
	"fmt"
	"github.com/fatih/color"
	"io"
	"os"
	"strings"
)

type TailPrinter struct {
	timestampFormat string
	failureColor    *color.Color
	writer          io.Writer
}

func NewTailPrinter() TailPrinter {
	return NewTailPrinterWithOptions(true, true, os.Stderr)
}

func NewTailPrinterWithOptions(showTimestamp, showColors bool, writer io.Writer) TailPrinter {
	format := ""
	if showTimestamp {
		format = "[03:04:05]"
	}

	failureColor := color.New(color.FgRed)

	if !showColors {
		failureColor = nil
	}

	return TailPrinter{
		timestampFormat: format,
		failureColor:    failureColor,
		writer:          writer,
	}
}

func (tp *TailPrinter) FormatTailEvent(tailEvent TailStackEvent) string {
	resourceNameLength := 20 // TODO: determine this from template/API

	timestampPrefix := tailEvent.Timestamp.Format(tp.timestampFormat)

	reasonPart := ""
	if tailEvent.ResourceStatusReason != nil {
		reasonPart = fmt.Sprintf("- %s", *tailEvent.ResourceStatusReason)
	}

	line := fmt.Sprintf("%s %s - %s %s", timestampPrefix, fixedLengthString(resourceNameLength, *tailEvent.LogicalResourceId), *tailEvent.ResourceStatus, reasonPart)

	if isBadStatus(*tailEvent.ResourceStatus) && tp.failureColor != nil {
		return tp.failureColor.Sprint(line)
	} else {
		return line
	}
}

func (tp *TailPrinter) PrintTailEvent(tailEvent TailStackEvent) {
	line := tp.FormatTailEvent(tailEvent)
	tp.writer.Write([]byte(line))
	tp.writer.Write([]byte("\n"))
}

func fixedLengthString(length int, str string) string {
	verb := fmt.Sprintf("%%%d.%ds", length, length)
	return fmt.Sprintf(verb, str)
}

func isBadStatus(status string) bool {
	return strings.HasSuffix(status, "_FAILED")
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package etcd3

import (
	"fmt"

	"google.golang.org/grpc/grpclog"
	"k8s.io/klog/v2"
)

func init() {
	grpclog.SetLoggerV2(klogWrapper{})
}

type klogWrapper struct{}

const klogWrapperDepth = 4

func (klogWrapper) Info(args ...interface{}) {
	klog.InfoDepth(klogWrapperDepth, args...)
}

func (klogWrapper) Infoln(args ...interface{}) {
	klog.InfoDepth(klogWrapperDepth, fmt.Sprintln(args...))
}

func (klogWrapper) Infof(format string, args ...interface{}) {
	klog.InfoDepth(klogWrapperDepth, fmt.Sprintf(format, args...))
}

func (klogWrapper) Warning(args ...interface{}) {
	klog.WarningDepth(klogWrapperDepth, args...)
}

func (klogWrapper) Warningln(args ...interface{}) {
	klog.WarningDepth(klogWrapperDepth, fmt.Sprintln(args...))
}

func (klogWrapper) Warningf(format string, args ...interface{}) {
	klog.WarningDepth(klogWrapperDepth, fmt.Sprintf(format, args...))
}

func (klogWrapper) Error(args ...interface{}) {
	klog.ErrorDepth(klogWrapperDepth, args...)
}

func (klogWrapper) Errorln(args ...interface{}) {
	klog.ErrorDepth(klogWrapperDepth, fmt.Sprintln(args...))
}

func (klogWrapper) Errorf(format string, args ...interface{}) {
	klog.ErrorDepth(klogWrapperDepth, fmt.Sprintf(format, args...))
}

func (klogWrapper) Fatal(args ...interface{}) {
	klog.FatalDepth(klogWrapperDepth, args...)
}

func (klogWrapper) Fatalln(args ...interface{}) {
	klog.FatalDepth(klogWrapperDepth, fmt.Sprintln(args...))
}

func (klogWrapper) Fatalf(format string, args ...interface{}) {
	klog.FatalDepth(klogWrapperDepth, fmt.Sprintf(format, args...))
}

func (klogWrapper) V(l int) bool {
	return bool(klog.V(klog.Level(l)).Enabled())
}
<commit_msg>Quiet grpc info logs in apiserver<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

package etcd3

import (
	"fmt"

	"google.golang.org/grpc/grpclog"
	"k8s.io/klog/v2"
)

func init() {
	grpclog.SetLoggerV2(klogWrapper{})
}

type klogWrapper struct{}

const klogWrapperDepth = 4

func (klogWrapper) Info(args ...interface{}) {
	if klog.V(5).Enabled() {
		klog.InfoDepth(klogWrapperDepth, args...)
	}
}

func (klogWrapper) Infoln(args ...interface{}) {
	if klog.V(5).Enabled() {
		klog.InfoDepth(klogWrapperDepth, fmt.Sprintln(args...))
	}
}

func (klogWrapper) Infof(format string, args ...interface{}) {
	if klog.V(5).Enabled() {
		klog.InfoDepth(klogWrapperDepth, fmt.Sprintf(format, args...))
	}
}

func (klogWrapper) Warning(args ...interface{}) {
	klog.WarningDepth(klogWrapperDepth, args...)
}

func (klogWrapper) Warningln(args ...interface{}) {
	klog.WarningDepth(klogWrapperDepth, fmt.Sprintln(args...))
}

func (klogWrapper) Warningf(format string, args ...interface{}) {
	klog.WarningDepth(klogWrapperDepth, fmt.Sprintf(format, args...))
}

func (klogWrapper) Error(args ...interface{}) {
	klog.ErrorDepth(klogWrapperDepth, args...)
}

func (klogWrapper) Errorln(args ...interface{}) {
	klog.ErrorDepth(klogWrapperDepth, fmt.Sprintln(args...))
}

func (klogWrapper) Errorf(format string, args ...interface{}) {
	klog.ErrorDepth(klogWrapperDepth, fmt.Sprintf(format, args...))
}

func (klogWrapper) Fatal(args ...interface{}) {
	klog.FatalDepth(klogWrapperDepth, args...)
}

func (klogWrapper) Fatalln(args ...interface{}) {
	klog.FatalDepth(klogWrapperDepth, fmt.Sprintln(args...))
}

func (klogWrapper) Fatalf(format string, args ...interface{}) {
	klog.FatalDepth(klogWrapperDepth, fmt.Sprintf(format, args...))
}

func (klogWrapper) V(l int) bool {
	return bool(klog.V(klog.Level(l)).Enabled())
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/tomsteele/blacksheepwall/bsw"
	"log"
	"net"
	"os"
	"runtime"
)

var usage = `
  Usage: blacksheepwall [options] <ip address or CIDR>

  Options:
  -h, --help            Show Usage and exit.
  -version              Show version and exit.
  -debug                Enable debugging and show errors returned from tasks.
  -concurrency <int>    Max amount of concurrent tasks.    [default: 100]
  -cpus <int>           Max amount of cpus  for the go runtime.    [default: runtime.NumCPU()]
  -server <string>      DNS server address.    [default: "8.8.8.8"]
  -input <string>       Line separated file of networks (CIDR) or
                        IP Addresses.
  -ipv6	                Look for additional AAAA records where applicable.
  -domain <string>      Target domain to use for certain tasks.
  -dictionary <string>  Attempt to retrieve the CNAME and A record for
                        each subdomain in the line separated file.
  -yandex <string>      Provided a Yandex search XML API url. Use the Yandex
                        search 'rhost:' operator to find subdomains of a
                        provided domain..
  -bing	<string>        Provided a base64 encoded API key. Use the Bing search
                        API's 'ip:' operator to lookup hostnames for each host.
  -headers              Perform HTTP(s) requests to each host and look for
                        hostnames in a possible Location header.
  -reverse              Retrieve the PTR for each host.
  -tls                  Attempt to retrieve names from TLS certificates
                        (CommonName and Subject Alternative Name).
  -viewdns              Lookup each host using viewdns.info's Reverse IP
                        Lookup function.
  -fcrdns               Verify results by attempting to retrieve the A or AAAA record for
                        each result previously identified hostname.
  -clean                Print results as unique hostnames for each host.
  -csv                  Print results in csv format.
  -json                 Print results as JSON.

`

// Returns all ip addresses from each CIDR range in a list.
func linesToIpList(lines []string) ([]string, error) {
	ipList := make([]string, 0)
	for _, line := range lines {
		if net.ParseIP(line) != nil {
			ipList = append(ipList, line)
		} else if ip, network, err := net.ParseCIDR(line); err == nil {
			for ip := ip.Mask(network.Mask); network.Contains(ip); increaseIp(ip) {
				ipList = append(ipList, ip.String())
			}
		} else {
			return ipList, errors.New("\"" + line + "\" is not an IP Address or CIDR Network")
		}
	}
	return ipList, nil
}

// Increases each byte of a net.IP.
func increaseIp(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

// Reads lines from a file and returns as a slice.
func readFileLines(path string) ([]string, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	lines := make([]string, 0)
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	return lines, scanner.Err()
}

// Sets the max CPUS for the runtime.
func setMaxProcs(cpus int) {
	if cpus < 1 {
		log.Fatal("-cpus must be atleast 1")
	}
	if cpus > runtime.NumCPU() {
		log.Fatal("-cpus count too high")
	}
	runtime.GOMAXPROCS(cpus)
}

type task func() ([]bsw.Result, error)
type empty struct{}

func main() {
	flVersion := flag.Bool("version", false, "Show version and exit.")
	flConcurrency := flag.Int("concurrency", 100, "Max amount of concurrent tasks.")
	flCpus := flag.Int("cpus", runtime.NumCPU(), "Max amount of cpus  for the go runtime.")
	flDebug := flag.Bool("debug", false, "Enable debugging and show errors returned from tasks.")
	flipv6 := flag.Bool("ipv6", false, "Look for AAAA records where applicable.")
	flServerAddr := flag.String("server", "8.8.8.8", "DNS server address.")
	flIpFile := flag.String("input", "", "Line separated file of networks (CIDR) or IP Addresses.")
	flReverse := flag.Bool("reverse", false, "Retrieve the PTR for each host.")
	flHeader := flag.Bool("headers", false, "Perform HTTP(s) requests to each host and look for hostnames in a possible Location header.")
	flTLS := flag.Bool("tls", false, "Attempt to retrieve names from TLS certificates (CommonName and Subject Alternative Name).")
	flViewDnsInfo := flag.Bool("viewdns", false, "Lookup each host using viewdns.info's Reverse IP Lookup function.")
	flBing := flag.String("bing", "", "Provided a base64 encoded API key. Use the Bing search API's 'ip:' operator to lookup hostnames for each host.")
	flYandex := flag.String("yandex", "", "Provided a Yandex search XML API url. Use the Yandex search 'rhost:' operator to find subdomains of a provided domain.")
	flDomain := flag.String("domain", "", "Target domain to use for certain tasks.")
	flDictFile := flag.String("dictionary", "", "Attempt to retrieve the CNAME and A record for each subdomain in the line separated file.")
	flFcrdns := flag.Bool("fcrdns", false, "Verify results by attempting to retrieve the A or AAAA record for each result previously identified hostname.")
	flClean := flag.Bool("clean", false, "Print results as unique hostnames for each host.")
	flCsv := flag.Bool("csv", false, "Print results in csv format.")
	flJson := flag.Bool("json", false, "Print results as JSON.")
	flag.Usage = func() { fmt.Print(usage) }
	flag.Parse()

	if *flVersion {
		fmt.Println("blacksheepwall version ", bsw.VERSION)
		os.Exit(0)
	}

	setMaxProcs(*flCpus)

	// Holds all ip addresses for testing
	ipAddrList := make([]string, 0)

	// Used to hold a ip or CIDR range passed as fl.Arg(0)
	var flNetwork string

	// Verify that some sort of work load was given in commands
	if *flIpFile == "" && *flDomain == "" && len(flag.Args()) < 1 {
		log.Fatal("You didn't provide any work for me to do")
	}
	if *flYandex != "" && *flDomain == "" {
		log.Fatal("Yandex API requires domain set with -domain")
	}
	if *flDictFile != "" && *flDomain == "" {
		log.Fatal("Dictionary lookup requires domain set with -domain")
	}
	if *flDomain != "" && *flYandex == "" && *flDictFile == "" {
		log.Fatal("-domain provided but no methods provided that use it")
	}

	// Get first argument that is not an option and turn it into a list of ips
	if len(flag.Args()) > 0 {
		flNetwork = flag.Arg(0)
		list, err := linesToIpList([]string{flNetwork})
		if err != nil {
			log.Fatal(err.Error())
		}
		ipAddrList = append(ipAddrList, list...)
	}

	// If file given as -input, read lines and turn each possible ip or network into
	// a list of ips. Appends list to ipAddrList. Will fail fatally if line in file
	// is not a valid ip or CIDR range.
	if *flIpFile != "" {
		lines, err := readFileLines(*flIpFile)
		if err != nil {
			log.Fatal("Error reading " + *flIpFile + " " + err.Error())
		}
		list, err := linesToIpList(lines)
		if err != nil {
			log.Fatal(err.Error())
		}
		ipAddrList = append(ipAddrList, list...)
	}

	// tracker: Chanel uses an empty struct to track when all goroutines in the pool
	//          have completed as well as a single call from the gatherer.
	//
	// tasks:   Chanel used in the goroutine pool to manage incoming work. A task is
	//          a function wrapper that returns a slice of results and a possible error.
	//
	// res:     When each task is called in the pool, it will send valid results to
	//          the res channel. A goroutine manages this channel and appends results
	//          to results slice.
	tracker := make(chan empty)
	tasks := make(chan task, *flConcurrency)
	res := make(chan []bsw.Result, *flConcurrency)
	results := make([]bsw.Result, 0)

	// Start up *flConcurrency amount of goroutines
	log.Printf("Spreading tasks across %d goroutines", *flConcurrency)
	for i := 0; i < *flConcurrency; i++ {
		go func() {
			var c = 0
			for def := range tasks {
				result, err := def()
				if m := c % 2; m == 0 {
					c = 3
					os.Stderr.WriteString("\rWorking \\")
				} else {
					c = 2
					os.Stderr.WriteString("\rWorking /")
				}
				if err != nil && *flDebug {
					log.Println(err.Error())
				}
				if err == nil {
					res <- result
				}
			}
			e := empty{}
			tracker <- e
		}()
	}

	// Ingest incoming results
	go func() {
		for result := range res {
			if len(result) < 1 {
				continue
			}
			if *flFcrdns {
				for _, r := range result {
					ip, err := bsw.LookupName(r.Hostname, *flServerAddr)
					if err == nil && len(ip) > 0 {
						results = append(results, bsw.Result{Source: "fcrdns", IP: ip, Hostname: r.Hostname})
					}
					ip, err = bsw.LookupName6(r.Hostname, *flServerAddr)
					if err == nil && len(ip) > 0 {
						results = append(results, bsw.Result{Source: "fcrdns", IP: ip, Hostname: r.Hostname})
					}
				}
			} else {
				results = append(results, result...)
			}
		}
		e := empty{}
		tracker <- e
	}()

	// Bing has two possible search paths. We need to find which one is valid.
	var bingPath string
	if *flBing != "" {
		p, err := bsw.FindBingSearchPath(*flBing)
		if err != nil {
			log.Fatal(err.Error())
		}
		bingPath = p
	}

	// ip based functionality should be added to the pool here
	for _, h := range ipAddrList {
		host := h
		if *flReverse {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.Reverse(host, *flServerAddr)
			}
		}
		if *flTLS {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.TLS(host)
			}
		}
		if *flViewDnsInfo {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.ViewDnsInfo(host)
			}
		}
		if *flBing != "" && bingPath != "" {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.BingAPI(host, *flBing, bingPath)
			}
		}
		if *flHeader {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.Headers(host)
			}
		}

	}

	// Domain based functions will likely require separate blocks

	// Subdomain dictionary guessing
	if *flDictFile != "" && *flDomain != "" {
		nameList, err := readFileLines(*flDictFile)
		if err != nil {
			log.Fatal("Error reading " + *flDictFile + " " + err.Error())
		}
		// Get an ip for a possible wildcard domain and use it as a blacklist
		blacklist := bsw.GetWildCard(*flDomain, *flServerAddr)
		var blacklist6 string
		if *flipv6 {
			blacklist6 = bsw.GetWildCard6(*flDomain, *flServerAddr)
		}
		for _, n := range nameList {
			sub := n
			tasks <- func() ([]bsw.Result, error) {
				return bsw.Dictionary(*flDomain, sub, blacklist, *flServerAddr)
			}
			if *flipv6 {
				tasks <- func() ([]bsw.Result, error) {
					return bsw.Dictionary6(*flDomain, sub, blacklist6, *flServerAddr)
				}
			}
		}
	}

	if *flYandex != "" && *flDomain != "" {
		tasks <- func() ([]bsw.Result, error) {
			return bsw.YandexAPI(*flDomain, *flYandex, *flServerAddr)
		}
	}

	// Close the tasks channel after all jobs have completed and for each
	// goroutine in the pool receive an empty message from  tracker.
	close(tasks)
	for i := 0; i < *flConcurrency; i++ {
		<-tracker
	}
	close(res)
	// Receive and empty message from the result gatherer
	<-tracker

	os.Stderr.WriteString("\r")
	log.Println("All tasks completed\n")

	// Output options
	if *flJson {
		j, _ := json.MarshalIndent(results, "", "    ")
		fmt.Println(string(j))
	} else if *flCsv {
		for _, r := range results {
			fmt.Printf("%s,%s,%s\n", r.Hostname, r.IP, r.Source)
		}
	} else if *flClean {
		cleanSet := make(map[string][]string)
		for _, r := range results {
			cleanSet[r.Hostname] = append(cleanSet[r.Hostname], r.IP)
		}
		for k, v := range cleanSet {
			fmt.Printf("%s:\n", k)
			for _, ip := range v {
				fmt.Printf("\t%s\n", ip)
			}
		}
	} else {
		for _, r := range results {
			fmt.Printf("Hostname: %s IP: %s Source: %s\n", r.Hostname, r.IP, r.Source)
		}
	}
}
<commit_msg>Sorts and add tabwriter<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"sort"
	"github.com/tomsteele/blacksheepwall/bsw"
	"log"
	"net"
	"os"
	"runtime"
	"text/tabwriter"
)

var usage = `
  Usage: blacksheepwall [options] <ip address or CIDR>

  Options:
  -h, --help            Show Usage and exit.
  -version              Show version and exit.
  -debug                Enable debugging and show errors returned from tasks.
  -concurrency <int>    Max amount of concurrent tasks.    [default: 100]
  -cpus <int>           Max amount of cpus  for the go runtime.    [default: runtime.NumCPU()]
  -server <string>      DNS server address.    [default: "8.8.8.8"]
  -input <string>       Line separated file of networks (CIDR) or
                        IP Addresses.
  -ipv6	                Look for additional AAAA records where applicable.
  -domain <string>      Target domain to use for certain tasks.
  -dictionary <string>  Attempt to retrieve the CNAME and A record for
                        each subdomain in the line separated file.
  -yandex <string>      Provided a Yandex search XML API url. Use the Yandex
                        search 'rhost:' operator to find subdomains of a
                        provided domain..
  -bing	<string>        Provided a base64 encoded API key. Use the Bing search
                        API's 'ip:' operator to lookup hostnames for each host.
  -headers              Perform HTTP(s) requests to each host and look for
                        hostnames in a possible Location header.
  -reverse              Retrieve the PTR for each host.
  -tls                  Attempt to retrieve names from TLS certificates
                        (CommonName and Subject Alternative Name).
  -viewdns              Lookup each host using viewdns.info's Reverse IP
                        Lookup function.
  -fcrdns               Verify results by attempting to retrieve the A or AAAA record for
                        each result previously identified hostname.
  -clean                Print results as unique hostnames for each host.
  -csv                  Print results in csv format.
  -json                 Print results as JSON.

`

// Returns all ip addresses from each CIDR range in a list.
func linesToIpList(lines []string) ([]string, error) {
	ipList := make([]string, 0)
	for _, line := range lines {
		if net.ParseIP(line) != nil {
			ipList = append(ipList, line)
		} else if ip, network, err := net.ParseCIDR(line); err == nil {
			for ip := ip.Mask(network.Mask); network.Contains(ip); increaseIp(ip) {
				ipList = append(ipList, ip.String())
			}
		} else {
			return ipList, errors.New("\"" + line + "\" is not an IP Address or CIDR Network")
		}
	}
	return ipList, nil
}

// Increases each byte of a net.IP.
func increaseIp(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}

// Reads lines from a file and returns as a slice.
func readFileLines(path string) ([]string, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	lines := make([]string, 0)
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	return lines, scanner.Err()
}

// Sets the max CPUS for the runtime.
func setMaxProcs(cpus int) {
	if cpus < 1 {
		log.Fatal("-cpus must be atleast 1")
	}
	if cpus > runtime.NumCPU() {
		log.Fatal("-cpus count too high")
	}
	runtime.GOMAXPROCS(cpus)
}

type task func() ([]bsw.Result, error)
type empty struct{}

func main() {
	flVersion := flag.Bool("version", false, "Show version and exit.")
	flConcurrency := flag.Int("concurrency", 100, "Max amount of concurrent tasks.")
	flCpus := flag.Int("cpus", runtime.NumCPU(), "Max amount of cpus  for the go runtime.")
	flDebug := flag.Bool("debug", false, "Enable debugging and show errors returned from tasks.")
	flipv6 := flag.Bool("ipv6", false, "Look for AAAA records where applicable.")
	flServerAddr := flag.String("server", "8.8.8.8", "DNS server address.")
	flIpFile := flag.String("input", "", "Line separated file of networks (CIDR) or IP Addresses.")
	flReverse := flag.Bool("reverse", false, "Retrieve the PTR for each host.")
	flHeader := flag.Bool("headers", false, "Perform HTTP(s) requests to each host and look for hostnames in a possible Location header.")
	flTLS := flag.Bool("tls", false, "Attempt to retrieve names from TLS certificates (CommonName and Subject Alternative Name).")
	flViewDnsInfo := flag.Bool("viewdns", false, "Lookup each host using viewdns.info's Reverse IP Lookup function.")
	flBing := flag.String("bing", "", "Provided a base64 encoded API key. Use the Bing search API's 'ip:' operator to lookup hostnames for each host.")
	flYandex := flag.String("yandex", "", "Provided a Yandex search XML API url. Use the Yandex search 'rhost:' operator to find subdomains of a provided domain.")
	flDomain := flag.String("domain", "", "Target domain to use for certain tasks.")
	flDictFile := flag.String("dictionary", "", "Attempt to retrieve the CNAME and A record for each subdomain in the line separated file.")
	flFcrdns := flag.Bool("fcrdns", false, "Verify results by attempting to retrieve the A or AAAA record for each result previously identified hostname.")
	flClean := flag.Bool("clean", false, "Print results as unique hostnames for each host.")
	flCsv := flag.Bool("csv", false, "Print results in csv format.")
	flJson := flag.Bool("json", false, "Print results as JSON.")
	flag.Usage = func() { fmt.Print(usage) }
	flag.Parse()

	if *flVersion {
		fmt.Println("blacksheepwall version ", bsw.VERSION)
		os.Exit(0)
	}

	setMaxProcs(*flCpus)

	// Holds all ip addresses for testing
	ipAddrList := make([]string, 0)

	// Used to hold a ip or CIDR range passed as fl.Arg(0)
	var flNetwork string

	// Verify that some sort of work load was given in commands
	if *flIpFile == "" && *flDomain == "" && len(flag.Args()) < 1 {
		log.Fatal("You didn't provide any work for me to do")
	}
	if *flYandex != "" && *flDomain == "" {
		log.Fatal("Yandex API requires domain set with -domain")
	}
	if *flDictFile != "" && *flDomain == "" {
		log.Fatal("Dictionary lookup requires domain set with -domain")
	}
	if *flDomain != "" && *flYandex == "" && *flDictFile == "" {
		log.Fatal("-domain provided but no methods provided that use it")
	}

	// Get first argument that is not an option and turn it into a list of ips
	if len(flag.Args()) > 0 {
		flNetwork = flag.Arg(0)
		list, err := linesToIpList([]string{flNetwork})
		if err != nil {
			log.Fatal(err.Error())
		}
		ipAddrList = append(ipAddrList, list...)
	}

	// If file given as -input, read lines and turn each possible ip or network into
	// a list of ips. Appends list to ipAddrList. Will fail fatally if line in file
	// is not a valid ip or CIDR range.
	if *flIpFile != "" {
		lines, err := readFileLines(*flIpFile)
		if err != nil {
			log.Fatal("Error reading " + *flIpFile + " " + err.Error())
		}
		list, err := linesToIpList(lines)
		if err != nil {
			log.Fatal(err.Error())
		}
		ipAddrList = append(ipAddrList, list...)
	}

	// tracker: Chanel uses an empty struct to track when all goroutines in the pool
	//          have completed as well as a single call from the gatherer.
	//
	// tasks:   Chanel used in the goroutine pool to manage incoming work. A task is
	//          a function wrapper that returns a slice of results and a possible error.
	//
	// res:     When each task is called in the pool, it will send valid results to
	//          the res channel. A goroutine manages this channel and appends results
	//          to results slice.
	tracker := make(chan empty)
	tasks := make(chan task, *flConcurrency)
	res := make(chan []bsw.Result, *flConcurrency)
	results := bsw.Results{}

	// Start up *flConcurrency amount of goroutines
	log.Printf("Spreading tasks across %d goroutines", *flConcurrency)
	for i := 0; i < *flConcurrency; i++ {
		go func() {
			var c = 0
			for def := range tasks {
				result, err := def()
				if m := c % 2; m == 0 {
					c = 3
					os.Stderr.WriteString("\rWorking \\")
				} else {
					c = 2
					os.Stderr.WriteString("\rWorking /")
				}
				if err != nil && *flDebug {
					log.Println(err.Error())
				}
				if err == nil {
					res <- result
				}
			}
			e := empty{}
			tracker <- e
		}()
	}

	// Ingest incoming results
	go func() {
		for result := range res {
			if len(result) < 1 {
				continue
			}
			if *flFcrdns {
				for _, r := range result {
					ip, err := bsw.LookupName(r.Hostname, *flServerAddr)
					if err == nil && len(ip) > 0 {
						results = append(results, bsw.Result{Source: "fcrdns", IP: ip, Hostname: r.Hostname})
					}
					ip, err = bsw.LookupName6(r.Hostname, *flServerAddr)
					if err == nil && len(ip) > 0 {
						results = append(results, bsw.Result{Source: "fcrdns", IP: ip, Hostname: r.Hostname})
					}
				}
			} else {
				results = append(results, result...)
			}
		}
		e := empty{}
		tracker <- e
	}()

	// Bing has two possible search paths. We need to find which one is valid.
	var bingPath string
	if *flBing != "" {
		p, err := bsw.FindBingSearchPath(*flBing)
		if err != nil {
			log.Fatal(err.Error())
		}
		bingPath = p
	}

	// ip based functionality should be added to the pool here
	for _, h := range ipAddrList {
		host := h
		if *flReverse {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.Reverse(host, *flServerAddr)
			}
		}
		if *flTLS {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.TLS(host)
			}
		}
		if *flViewDnsInfo {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.ViewDnsInfo(host)
			}
		}
		if *flBing != "" && bingPath != "" {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.BingAPI(host, *flBing, bingPath)
			}
		}
		if *flHeader {
			tasks <- func() ([]bsw.Result, error) {
				return bsw.Headers(host)
			}
		}

	}

	// Domain based functions will likely require separate blocks

	// Subdomain dictionary guessing
	if *flDictFile != "" && *flDomain != "" {
		nameList, err := readFileLines(*flDictFile)
		if err != nil {
			log.Fatal("Error reading " + *flDictFile + " " + err.Error())
		}
		// Get an ip for a possible wildcard domain and use it as a blacklist
		blacklist := bsw.GetWildCard(*flDomain, *flServerAddr)
		var blacklist6 string
		if *flipv6 {
			blacklist6 = bsw.GetWildCard6(*flDomain, *flServerAddr)
		}
		for _, n := range nameList {
			sub := n
			tasks <- func() ([]bsw.Result, error) {
				return bsw.Dictionary(*flDomain, sub, blacklist, *flServerAddr)
			}
			if *flipv6 {
				tasks <- func() ([]bsw.Result, error) {
					return bsw.Dictionary6(*flDomain, sub, blacklist6, *flServerAddr)
				}
			}
		}
	}

	if *flYandex != "" && *flDomain != "" {
		tasks <- func() ([]bsw.Result, error) {
			return bsw.YandexAPI(*flDomain, *flYandex, *flServerAddr)
		}
	}

	// Close the tasks channel after all jobs have completed and for each
	// goroutine in the pool receive an empty message from  tracker.
	close(tasks)
	for i := 0; i < *flConcurrency; i++ {
		<-tracker
	}
	close(res)
	// Receive and empty message from the result gatherer
	<-tracker

	os.Stderr.WriteString("\r")
	log.Println("All tasks completed\n")
	sort.Sort(results)

	// Output options
	if *flJson {
		j, _ := json.MarshalIndent(results, "", "    ")
		fmt.Println(string(j))
	} else if *flCsv {
		for _, r := range results {
			fmt.Printf("%s,%s,%s\n", r.Hostname, r.IP, r.Source)
		}
	} else if *flClean {
		cleanSet := make(map[string][]string)
		for _, r := range results {
			cleanSet[r.Hostname] = append(cleanSet[r.Hostname], r.IP)
		}
		for k, v := range cleanSet {
			fmt.Printf("%s:\n", k)
			for _, ip := range v {
				fmt.Printf("\t%s\n", ip)
			}
		}
	} else {
		w := tabwriter.NewWriter(os.Stdout, 0, 8, 4, ' ', 0)
		fmt.Fprintln(w, "IP\tHostname\tSource")
		for _, r := range results {
			fmt.Fprintf(w, "%s\t%s\t%s\n", r.IP, r.Hostname, r.Source)
		}
		w.Flush()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/acomagu/dsns-go/dsns"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"github.com/julienschmidt/httprouter"
	_ "github.com/mattn/go-sqlite3"
	"github.com/pkg/errors"
)

// Response defines the JSON contents for response to resource request by HTTP.
type Response struct {
	Success          bool                     `json:"success"`
	Rows             []map[string]interface{} `json:"rows"`
	ErrorType        string                   `json:"errorType"`
	ErrorDescription string                   `json:"errorDescription"`
}

func main() {
	inputConfig, err := readConfigs()
	if err != nil {
		fmt.Println(err)
		return
	}

	config, err := inputConfig.Config()
	if err != nil {
		fmt.Printf("invalid configuration: %s\n", err)
		return
	}

	s := dsns.NewSource(config.DB.Name, config.DB.Username, config.DB.Password, config.DB.Filepath)
	dsn, err := s.ByDriverName(config.DB.Driver)
	db, err := openDB(config)
	if err != nil {
		fmt.Println(err)
		return
	}

	router := httprouter.New()
	for _, rule := range config.Rules {
		querySet, err := newQuerySet(db, rule)
		if err != nil {
			fmt.Println(errors.Wrap(err, "failed to compile query"))
			return
		}
		router.Handle(string(rule.Method), rule.Path, createHandler(db, querySet))
	}
	fmt.Println(http.ListenAndServe(fmt.Sprintf(":%d", config.Port), router))
}

func openDB(config Config) (*sqlx.DB, error) {
	dsn, err := config.DB.DSN()
	if err != nil {
		return nil, err
	}

	db, err := sqlx.Open(config.DB.Driver, dsn)
	if err != nil {
		return nil, err
	}
	return db, nil
}
func createHandler(db *sqlx.DB, q QuerySet) httprouter.Handle {
	return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.WriteHeader(http.StatusOK)
		paramMap, err := createParamMap(req, params)
		if err != nil {
			w.Write(createErrorResponseBytes(err))
			return
		}
		rowMaps, err := executeQuerySet(db, q, paramMap)
		if err != nil {
			w.Write(createErrorResponseBytes(err))
			return
		}

		bts, marshalErr := json.Marshal(Response{
			Success: true,
			Rows:    rowMaps,
		})
		if marshalErr != nil {
			panic(marshalErr)
		}
		w.Write(bts)
	}
}

func createErrorResponseBytes(err error) []byte {
	bts, marshalErr := json.Marshal(Response{
		Success:          false,
		ErrorType:        getErrorType(err),
		ErrorDescription: err.Error(),
	})
	if marshalErr != nil {
		panic(marshalErr)
	}
	return bts
}
<commit_msg>[Modify] remove dsns dependency<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/http"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"github.com/julienschmidt/httprouter"
	_ "github.com/mattn/go-sqlite3"
	"github.com/pkg/errors"
)

// Response defines the JSON contents for response to resource request by HTTP.
type Response struct {
	Success          bool                     `json:"success"`
	Rows             []map[string]interface{} `json:"rows"`
	ErrorType        string                   `json:"errorType"`
	ErrorDescription string                   `json:"errorDescription"`
}

func main() {
	inputConfig, err := readConfigs()
	if err != nil {
		fmt.Println(err)
		return
	}

	config, err := inputConfig.Config()
	if err != nil {
		fmt.Printf("invalid configuration: %s\n", err)
		return
	}

	db, err := openDB(config)
	if err != nil {
		fmt.Println(err)
		return
	}

	router := httprouter.New()
	for _, rule := range config.Rules {
		querySet, err := newQuerySet(db, rule)
		if err != nil {
			fmt.Println(errors.Wrap(err, "failed to compile query"))
			return
		}
		router.Handle(string(rule.Method), rule.Path, createHandler(db, querySet))
	}
	fmt.Println(http.ListenAndServe(fmt.Sprintf(":%d", config.Port), router))
}

func openDB(config Config) (*sqlx.DB, error) {
	dsn, err := config.DB.DSN()
	if err != nil {
		return nil, err
	}

	db, err := sqlx.Open(config.DB.Driver, dsn)
	if err != nil {
		return nil, err
	}
	return db, nil
}
func createHandler(db *sqlx.DB, q QuerySet) httprouter.Handle {
	return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.WriteHeader(http.StatusOK)
		paramMap, err := createParamMap(req, params)
		if err != nil {
			w.Write(createErrorResponseBytes(err))
			return
		}
		rowMaps, err := executeQuerySet(db, q, paramMap)
		if err != nil {
			w.Write(createErrorResponseBytes(err))
			return
		}

		bts, marshalErr := json.Marshal(Response{
			Success: true,
			Rows:    rowMaps,
		})
		if marshalErr != nil {
			panic(marshalErr)
		}
		w.Write(bts)
	}
}

func createErrorResponseBytes(err error) []byte {
	bts, marshalErr := json.Marshal(Response{
		Success:          false,
		ErrorType:        getErrorType(err),
		ErrorDescription: err.Error(),
	})
	if marshalErr != nil {
		panic(marshalErr)
	}
	return bts
}
<|endoftext|>