<commit_before>package main

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

	"github.com/gorilla/mux"

	neturl "net/url"
)

type server struct {
	// ShortURLPrefix is an optional prefix to return even shorter URLs than
	// using the request's hostname and path.
	ShortURLPrefix string

	DB database
}

// illegalChars is a string containing all characters that are illegal in short
// URL names. They are illegal because they have a special meaning when using
// the short URL link.
const illegalChars = "/?#"

func (s server) Save(response http.ResponseWriter, request *http.Request) {
	decoder := json.NewDecoder(request.Body)
	var data struct {
		Name string `json:"name"`
		URL  string `json:"url"`
	}
	if err := decoder.Decode(&data); err != nil {
		http.Error(response, `{"error":"Unable to parse json"}`, http.StatusBadRequest)
		return
	}

	if data.Name == "" {
		http.Error(response, `{"error":"Missing name"}`, http.StatusBadRequest)
		return
	}

	if strings.ContainsAny(data.Name, illegalChars) {
		if jsonData, ok := marshalJson(response, map[string]string{"error": fmt.Sprintf("Name (%q) contains an illegal character: %q", data.Name, illegalChars)}); ok {
			http.Error(response, string(jsonData), http.StatusBadRequest)
		}
		return
	}

	if data.URL == "" {
		if jsonData, ok := marshalJson(response, map[string]string{"error": fmt.Sprintf("Missing URL for %q", data.Name)}); ok {
			http.Error(response, string(jsonData), http.StatusBadRequest)
		}
		return
	}

	if _, err := neturl.Parse(data.URL); err != nil {
		if jsonData, ok := marshalJson(response, map[string]string{"error": fmt.Sprintf("Not a valid URL: %q.", data.URL)}); ok {
			http.Error(response, string(jsonData), http.StatusBadRequest)
		}
		return
	}

	if err := s.DB.SaveURL(data.Name, data.URL); err != nil {
		if jsonData, ok := marshalJson(response, map[string]string{"error": err.Error()}); ok {
			http.Error(response, string(jsonData), http.StatusInternalServerError)
		}
		return
	}

	resp := map[string]string{"name": data.Name}
	if s.ShortURLPrefix != "" {
		resp["url"] = s.ShortURLPrefix
	}
	if jsonData, ok := marshalJson(response, resp); ok {
		response.Write(jsonData)
	}
}

func (s server) Load(response http.ResponseWriter, request *http.Request) {
	name := mux.Vars(request)["name"]

	url, err := s.DB.LoadURL(name)
	if err != nil {
		if _, ok := err.(NotFoundError); ok {
			q := neturl.Values{}
			q.Add("name", name)
			q.Add("error", "No such URL yet. Feel free to add one.")
			http.Redirect(response, request, ".#/?"+q.Encode(), http.StatusFound)
		}

		if jsonData, ok := marshalJson(response, map[string]string{"error": err.Error()}); ok {
			http.Error(response, string(jsonData), http.StatusInternalServerError)
		}
		return
	}

	var u *neturl.URL
	if u, err = neturl.Parse(url); err != nil {
		http.Redirect(response, request, url, http.StatusMovedPermanently)
		return
	}

	var tinkered bool

	if folder := mux.Vars(request)["folder"]; folder != "" {
		u.Path += folder
		tinkered = true
	}

	if q := request.URL.RawQuery; q != "" && u.RawQuery == "" {
		u.RawQuery = q
		tinkered = true
	}

	if tinkered {
		url = u.String()
	}

	http.Redirect(response, request, url, http.StatusMovedPermanently)
}

func marshalJson(response http.ResponseWriter, reply map[string]string) ([]byte, bool) {
	jsonData, err := json.Marshal(reply)
	if err != nil {
		http.Error(response, `{"error":"Unable to encode json"}`, http.StatusInternalServerError)
		return nil, false
	}
	return jsonData, true
}
<commit_msg>Return just after the Redirection.<commit_after>package main

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

	"github.com/gorilla/mux"

	neturl "net/url"
)

type server struct {
	// ShortURLPrefix is an optional prefix to return even shorter URLs than
	// using the request's hostname and path.
	ShortURLPrefix string

	DB database
}

// illegalChars is a string containing all characters that are illegal in short
// URL names. They are illegal because they have a special meaning when using
// the short URL link.
const illegalChars = "/?#"

func (s server) Save(response http.ResponseWriter, request *http.Request) {
	decoder := json.NewDecoder(request.Body)
	var data struct {
		Name string `json:"name"`
		URL  string `json:"url"`
	}
	if err := decoder.Decode(&data); err != nil {
		http.Error(response, `{"error":"Unable to parse json"}`, http.StatusBadRequest)
		return
	}

	if data.Name == "" {
		http.Error(response, `{"error":"Missing name"}`, http.StatusBadRequest)
		return
	}

	if strings.ContainsAny(data.Name, illegalChars) {
		if jsonData, ok := marshalJson(response, map[string]string{"error": fmt.Sprintf("Name (%q) contains an illegal character: %q", data.Name, illegalChars)}); ok {
			http.Error(response, string(jsonData), http.StatusBadRequest)
		}
		return
	}

	if data.URL == "" {
		if jsonData, ok := marshalJson(response, map[string]string{"error": fmt.Sprintf("Missing URL for %q", data.Name)}); ok {
			http.Error(response, string(jsonData), http.StatusBadRequest)
		}
		return
	}

	if _, err := neturl.Parse(data.URL); err != nil {
		if jsonData, ok := marshalJson(response, map[string]string{"error": fmt.Sprintf("Not a valid URL: %q.", data.URL)}); ok {
			http.Error(response, string(jsonData), http.StatusBadRequest)
		}
		return
	}

	if err := s.DB.SaveURL(data.Name, data.URL); err != nil {
		if jsonData, ok := marshalJson(response, map[string]string{"error": err.Error()}); ok {
			http.Error(response, string(jsonData), http.StatusInternalServerError)
		}
		return
	}

	resp := map[string]string{"name": data.Name}
	if s.ShortURLPrefix != "" {
		resp["url"] = s.ShortURLPrefix
	}
	if jsonData, ok := marshalJson(response, resp); ok {
		response.Write(jsonData)
	}
}

func (s server) Load(response http.ResponseWriter, request *http.Request) {
	name := mux.Vars(request)["name"]

	url, err := s.DB.LoadURL(name)
	if err != nil {
		if _, ok := err.(NotFoundError); ok {
			q := neturl.Values{}
			q.Add("name", name)
			q.Add("error", "No such URL yet. Feel free to add one.")
			http.Redirect(response, request, ".#/?"+q.Encode(), http.StatusFound)
			return
		}

		if jsonData, ok := marshalJson(response, map[string]string{"error": err.Error()}); ok {
			http.Error(response, string(jsonData), http.StatusInternalServerError)
		}
		return
	}

	var u *neturl.URL
	if u, err = neturl.Parse(url); err != nil {
		http.Redirect(response, request, url, http.StatusMovedPermanently)
		return
	}

	var tinkered bool

	if folder := mux.Vars(request)["folder"]; folder != "" {
		u.Path += folder
		tinkered = true
	}

	if q := request.URL.RawQuery; q != "" && u.RawQuery == "" {
		u.RawQuery = q
		tinkered = true
	}

	if tinkered {
		url = u.String()
	}

	http.Redirect(response, request, url, http.StatusMovedPermanently)
}

func marshalJson(response http.ResponseWriter, reply map[string]string) ([]byte, bool) {
	jsonData, err := json.Marshal(reply)
	if err != nil {
		http.Error(response, `{"error":"Unable to encode json"}`, http.StatusInternalServerError)
		return nil, false
	}
	return jsonData, true
}
<|endoftext|>


<commit_before>package revel

import (
	"fmt"
	"io"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"golang.org/x/net/websocket"
)

var (
	MainRouter         *Router
	MainTemplateLoader *TemplateLoader
	MainWatcher        *Watcher
	Server             *http.Server
)

// This method handles all requests.  It dispatches to handleInternal after
// handling / adapting websocket connections.
func handle(w http.ResponseWriter, r *http.Request) {
	r.Body = http.MaxBytesReader(w, r.Body, int64(Config.IntDefault("http.maxRequestSize", 10000000)))
	upgrade := r.Header.Get("Upgrade")
	if upgrade == "websocket" || upgrade == "Websocket" {
		websocket.Handler(func(ws *websocket.Conn) {
			//Override default Read/Write timeout with sane value for a web socket request
			ws.SetDeadline(time.Now().Add(time.Hour * 24))
			r.Method = "WS"
			handleInternal(w, r, ws)
		}).ServeHTTP(w, r)
	} else {
		handleInternal(w, r, nil)
	}
}

func handleInternal(w http.ResponseWriter, r *http.Request, ws *websocket.Conn) {
	var (
		req  = NewRequest(r)
		resp = NewResponse(w)
		c    = NewController(req, resp)
	)
	req.Websocket = ws

	Filters[0](c, Filters[1:])
	if c.Result != nil {
		c.Result.Apply(req, resp)
	} else if c.Response.Status != 0 {
		c.Response.Out.WriteHeader(c.Response.Status)
	}
	// Close the Writer if we can
	if w, ok := resp.Out.(io.Closer); ok {
		w.Close()
	}
}

// Run the server.
// This is called from the generated main file.
// If port is non-zero, use that.  Else, read the port from app.conf.
func Run(port int) {
	address := HttpAddr
	if port == 0 {
		port = HttpPort
	}

	var network = "tcp"
	var localAddress string

	// If the port is zero, treat the address as a fully qualified local address.
	// This address must be prefixed with the network type followed by a colon,
	// e.g. unix:/tmp/app.socket or tcp6:::1 (equivalent to tcp6:0:0:0:0:0:0:0:1)
	if port == 0 {
		parts := strings.SplitN(address, ":", 2)
		network = parts[0]
		localAddress = parts[1]
	} else {
		localAddress = address + ":" + strconv.Itoa(port)
	}

	Server = &http.Server{
		Addr:         localAddress,
		Handler:      http.HandlerFunc(handle),
		ReadTimeout:  time.Minute,
		WriteTimeout: time.Minute,
	}

	runStartupHooks()

	// Load templates
	MainTemplateLoader = NewTemplateLoader(TemplatePaths)
	MainTemplateLoader.Refresh()

	// The "watch" config variable can turn on and off all watching.
	// (As a convenient way to control it all together.)
	if Config.BoolDefault("watch", true) {
		MainWatcher = NewWatcher()
		Filters = append([]Filter{WatchFilter}, Filters...)
	}

	// If desired (or by default), create a watcher for templates and routes.
	// The watcher calls Refresh() on things on the first request.
	if MainWatcher != nil && Config.BoolDefault("watch.templates", true) {
		MainWatcher.Listen(MainTemplateLoader, MainTemplateLoader.paths...)
	}

	go func() {
		time.Sleep(100 * time.Millisecond)
		fmt.Printf("Listening on %s...\n", localAddress)
	}()

	if HttpSsl {
		if network != "tcp" {
			// This limitation is just to reduce complexity, since it is standard
			// to terminate SSL upstream when using unix domain sockets.
			ERROR.Fatalln("SSL is only supported for TCP sockets. Specify a port to listen on.")
		}
		ERROR.Fatalln("Failed to listen:",
			Server.ListenAndServeTLS(HttpSslCert, HttpSslKey))
	} else {
		listener, err := net.Listen(network, localAddress)
		if err != nil {
			ERROR.Fatalln("Failed to listen:", err)
		}
		ERROR.Fatalln("Failed to serve:", Server.Serve(listener))
	}
}

func runStartupHooks() {
	for _, hook := range startupHooks {
		hook()
	}
}

var startupHooks []func()

// Register a function to be run at app startup.
//
// The order you register the functions will be the order they are run.
// You can think of it as a FIFO queue.
// This process will happen after the config file is read
// and before the server is listening for connections.
//
// Ideally, your application should have only one call to init() in the file init.go.
// The reason being that the call order of multiple init() functions in
// the same package is undefined.
// Inside of init() call revel.OnAppStart() for each function you wish to register.
//
// Example:
//
//      // from: yourapp/app/controllers/somefile.go
//      func InitDB() {
//          // do DB connection stuff here
//      }
//
//      func FillCache() {
//          // fill a cache from DB
//          // this depends on InitDB having been run
//      }
//
//      // from: yourapp/app/init.go
//      func init() {
//          // set up filters...
//
//          // register startup functions
//          revel.OnAppStart(InitDB)
//          revel.OnAppStart(FillCache)
//      }
//
// This can be useful when you need to establish connections to databases or third-party services,
// setup app components, compile assets, or any thing you need to do between starting Revel and accepting connections.
//
func OnAppStart(f func()) {
	startupHooks = append(startupHooks, f)
}
<commit_msg>Rename maxRequestSize setting, default to unset<commit_after>package revel

import (
	"fmt"
	"io"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"golang.org/x/net/websocket"
)

var (
	MainRouter         *Router
	MainTemplateLoader *TemplateLoader
	MainWatcher        *Watcher
	Server             *http.Server
)

// This method handles all requests.  It dispatches to handleInternal after
// handling / adapting websocket connections.
func handle(w http.ResponseWriter, r *http.Request) {
	if maxRequestSize := int64(Config.IntDefault("http.maxrequestsize", 0)); maxRequestSize > 0 {
		r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
	}

	upgrade := r.Header.Get("Upgrade")
	if upgrade == "websocket" || upgrade == "Websocket" {
		websocket.Handler(func(ws *websocket.Conn) {
			//Override default Read/Write timeout with sane value for a web socket request
			ws.SetDeadline(time.Now().Add(time.Hour * 24))
			r.Method = "WS"
			handleInternal(w, r, ws)
		}).ServeHTTP(w, r)
	} else {
		handleInternal(w, r, nil)
	}
}

func handleInternal(w http.ResponseWriter, r *http.Request, ws *websocket.Conn) {
	var (
		req  = NewRequest(r)
		resp = NewResponse(w)
		c    = NewController(req, resp)
	)
	req.Websocket = ws

	Filters[0](c, Filters[1:])
	if c.Result != nil {
		c.Result.Apply(req, resp)
	} else if c.Response.Status != 0 {
		c.Response.Out.WriteHeader(c.Response.Status)
	}
	// Close the Writer if we can
	if w, ok := resp.Out.(io.Closer); ok {
		w.Close()
	}
}

// Run the server.
// This is called from the generated main file.
// If port is non-zero, use that.  Else, read the port from app.conf.
func Run(port int) {
	address := HttpAddr
	if port == 0 {
		port = HttpPort
	}

	var network = "tcp"
	var localAddress string

	// If the port is zero, treat the address as a fully qualified local address.
	// This address must be prefixed with the network type followed by a colon,
	// e.g. unix:/tmp/app.socket or tcp6:::1 (equivalent to tcp6:0:0:0:0:0:0:0:1)
	if port == 0 {
		parts := strings.SplitN(address, ":", 2)
		network = parts[0]
		localAddress = parts[1]
	} else {
		localAddress = address + ":" + strconv.Itoa(port)
	}

	Server = &http.Server{
		Addr:         localAddress,
		Handler:      http.HandlerFunc(handle),
		ReadTimeout:  time.Minute,
		WriteTimeout: time.Minute,
	}

	runStartupHooks()

	// Load templates
	MainTemplateLoader = NewTemplateLoader(TemplatePaths)
	MainTemplateLoader.Refresh()

	// The "watch" config variable can turn on and off all watching.
	// (As a convenient way to control it all together.)
	if Config.BoolDefault("watch", true) {
		MainWatcher = NewWatcher()
		Filters = append([]Filter{WatchFilter}, Filters...)
	}

	// If desired (or by default), create a watcher for templates and routes.
	// The watcher calls Refresh() on things on the first request.
	if MainWatcher != nil && Config.BoolDefault("watch.templates", true) {
		MainWatcher.Listen(MainTemplateLoader, MainTemplateLoader.paths...)
	}

	go func() {
		time.Sleep(100 * time.Millisecond)
		fmt.Printf("Listening on %s...\n", localAddress)
	}()

	if HttpSsl {
		if network != "tcp" {
			// This limitation is just to reduce complexity, since it is standard
			// to terminate SSL upstream when using unix domain sockets.
			ERROR.Fatalln("SSL is only supported for TCP sockets. Specify a port to listen on.")
		}
		ERROR.Fatalln("Failed to listen:",
			Server.ListenAndServeTLS(HttpSslCert, HttpSslKey))
	} else {
		listener, err := net.Listen(network, localAddress)
		if err != nil {
			ERROR.Fatalln("Failed to listen:", err)
		}
		ERROR.Fatalln("Failed to serve:", Server.Serve(listener))
	}
}

func runStartupHooks() {
	for _, hook := range startupHooks {
		hook()
	}
}

var startupHooks []func()

// Register a function to be run at app startup.
//
// The order you register the functions will be the order they are run.
// You can think of it as a FIFO queue.
// This process will happen after the config file is read
// and before the server is listening for connections.
//
// Ideally, your application should have only one call to init() in the file init.go.
// The reason being that the call order of multiple init() functions in
// the same package is undefined.
// Inside of init() call revel.OnAppStart() for each function you wish to register.
//
// Example:
//
//      // from: yourapp/app/controllers/somefile.go
//      func InitDB() {
//          // do DB connection stuff here
//      }
//
//      func FillCache() {
//          // fill a cache from DB
//          // this depends on InitDB having been run
//      }
//
//      // from: yourapp/app/init.go
//      func init() {
//          // set up filters...
//
//          // register startup functions
//          revel.OnAppStart(InitDB)
//          revel.OnAppStart(FillCache)
//      }
//
// This can be useful when you need to establish connections to databases or third-party services,
// setup app components, compile assets, or any thing you need to do between starting Revel and accepting connections.
//
func OnAppStart(f func()) {
	startupHooks = append(startupHooks, f)
}
<|endoftext|>


<commit_before>package caspercloud

import (
	"encoding/json"
	"fmt"
	"github.com/BigTong/gocounter"
	"github.com/xlvector/dlog"
	"net/http"
	"net/url"
	"runtime/debug"
)

const (
	kInternalErrorResut = "server get internal result"
)

type CasperServer struct {
	cmdCache   *CommandCache
	ct         *gocounter.Counter
	cmdFactory CommandFactory
}

func NewCasperServer(cf CommandFactory) *CasperServer {
	return &CasperServer{
		cmdCache:   NewCommandCache(),
		ct:         gocounter.NewCounter(),
		cmdFactory: cf,
	}
}

func (self *CasperServer) setArgs(cmd Command, params url.Values) *Output {
	args := self.getArgs(params)
	dlog.Println("setArgs:", args)
	cmd.SetInputArgs(args)

	if message := cmd.GetMessage(); message != nil {
		return message
	}
	return nil
}

func (self *CasperServer) getArgs(params url.Values) map[string]string {
	args := make(map[string]string)
	for k, v := range params {
		args[k] = v[0]
	}
	return args
}

func (self *CasperServer) Process(params url.Values) *Output {
	dlog.Info("%s", params.Encode())
	id := params.Get("id")
	if len(id) == 0 {
		c := self.cmdFactory.CreateCommand(params)
		if c == nil {
			return &Output{Status: FAIL, Data: "no create command"}
		}
		self.cmdCache.SetCommand(c)
		params.Set("id", c.GetId())
		return self.setArgs(c, params)
	}

	dlog.Info("get id:%s", id)
	c := self.cmdCache.GetCommand(id)
	if c == nil {
		dlog.Warn("get nil command id:%s", id)
		return &Output{Status: FAIL, Data: "not get command"}
	}

	dlog.Info("get cmd:%s", id)
	ret := self.setArgs(c, params)

	if c.Finished() {
		c.Successed()
		self.cmdCache.Delete(id)
		return &Output{Status: FINISH_FETCH_DATA}
	}

	if ret.Status == FAIL {
		c.Successed()
		return &Output{Status: FAIL, Data: ret.Data}
	}

	return ret
}

func (self *CasperServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	defer func() {
		if r := recover(); r != nil {
			dlog.Println("ERROR: http submit", r)
			debug.PrintStack()
		}
	}()
	self.ct.Incr("request", 1)
	params := req.URL.Query()
	ret := self.Process(params)
	output, _ := json.Marshal(ret)
	fmt.Fprint(w, string(output))
	return
}
<commit_msg>delete id<commit_after>package caspercloud

import (
	"encoding/json"
	"fmt"
	"github.com/BigTong/gocounter"
	"github.com/xlvector/dlog"
	"net/http"
	"net/url"
	"runtime/debug"
)

const (
	kInternalErrorResut = "server get internal result"
)

type CasperServer struct {
	cmdCache   *CommandCache
	ct         *gocounter.Counter
	cmdFactory CommandFactory
}

func NewCasperServer(cf CommandFactory) *CasperServer {
	return &CasperServer{
		cmdCache:   NewCommandCache(),
		ct:         gocounter.NewCounter(),
		cmdFactory: cf,
	}
}

func (self *CasperServer) setArgs(cmd Command, params url.Values) *Output {
	args := self.getArgs(params)
	dlog.Println("setArgs:", args)
	cmd.SetInputArgs(args)

	if message := cmd.GetMessage(); message != nil {
		return message
	}
	return nil
}

func (self *CasperServer) getArgs(params url.Values) map[string]string {
	args := make(map[string]string)
	for k, v := range params {
		args[k] = v[0]
	}
	return args
}

func (self *CasperServer) Process(params url.Values) *Output {
	dlog.Info("%s", params.Encode())
	id := params.Get("id")
	if len(id) == 0 {
		c := self.cmdFactory.CreateCommand(params)
		if c == nil {
			return &Output{Status: FAIL, Data: "no create command"}
		}
		self.cmdCache.SetCommand(c)
		params.Set("id", c.GetId())
		return self.setArgs(c, params)
	}

	dlog.Info("get id:%s", id)
	c := self.cmdCache.GetCommand(id)
	if c == nil {
		dlog.Warn("get nil command id:%s", id)
		return &Output{Status: FAIL, Data: "not get command"}
	}

	dlog.Info("get cmd:%s", id)
	ret := self.setArgs(c, params)

	if c.Finished() || ret.Status == FAIL || ret.Status == FINISH_FETCH_DATA || ret.Status == FINISH_ALL {
		c.Successed()
		self.cmdCache.Delete(id)
	}

	return ret
}

func (self *CasperServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	defer func() {
		if r := recover(); r != nil {
			dlog.Println("ERROR: http submit", r)
			debug.PrintStack()
		}
	}()
	self.ct.Incr("request", 1)
	params := req.URL.Query()
	ret := self.Process(params)
	output, _ := json.Marshal(ret)
	fmt.Fprint(w, string(output))
	return
}
<|endoftext|>


<commit_before>package pixel

import (
	"encoding/json"
	"log"
	"log/syslog"
	"net/http"
	"time"
)

type Server struct {
	listenAddress  string
	httpServer     *http.Server
	syslogAddress  string
	syslogPriority syslog.Priority
	logger         *log.Logger
	now            func() time.Time
}

type Event struct {
	Time      string            `json:"t"`
	Params    map[string]string `json:"params"`
	UserAgent string            `json:"ua,omitempty"`
	IP        string            `json:"ip,omitempty"`
	Proto     string            `json:"proto,omitempty"`
}

const ISO8601_FORMAT = "2006-01-02T15:04:05Z"

const TRANSPARENT_1_PX_GIF = "\x47\x49\x46\x38\x39\x61\x01\x00" +
	"\x01\x00\x80\x00\x00\xff\xff\xff\x00\x00\x00\x2c\x00\x00\x00\x00" +
	"\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3b"

var BAD_REQUEST string
var TRANSPARENT_1_PX_GIF_BYTES []byte

func init() {
	TRANSPARENT_1_PX_GIF_BYTES = []byte(TRANSPARENT_1_PX_GIF)
	BAD_REQUEST = http.StatusText(http.StatusBadRequest)
}

func NewSyslogPriority(level string, facility string) (p syslog.Priority) {
	switch level {
	case "LOG_EMERG":
		p = syslog.LOG_EMERG
	case "LOG_ALERT":
		p = syslog.LOG_ALERT
	case "LOG_CRIT":
		p = syslog.LOG_CRIT
	case "LOG_ERR":
		p = syslog.LOG_ERR
	case "LOG_WARNING":
		p = syslog.LOG_WARNING
	case "LOG_NOTICE":
		p = syslog.LOG_NOTICE
	case "LOG_INFO":
		p = syslog.LOG_INFO
	case "LOG_DEBUG":
		p = syslog.LOG_DEBUG
	default:
		p = syslog.LOG_INFO
	}

	switch facility {
	case "LOG_KERN":
		p |= syslog.LOG_KERN
	case "LOG_USER":
		p |= syslog.LOG_USER
	case "LOG_MAIL":
		p |= syslog.LOG_MAIL
	case "LOG_DAEMON":
		p |= syslog.LOG_DAEMON
	case "LOG_AUTH":
		p |= syslog.LOG_AUTH
	case "LOG_SYSLOG":
		p |= syslog.LOG_SYSLOG
	case "LOG_LPR":
		p |= syslog.LOG_LPR
	case "LOG_NEWS":
		p |= syslog.LOG_NEWS
	case "LOG_UUCP":
		p |= syslog.LOG_UUCP
	case "LOG_CRON":
		p |= syslog.LOG_CRON
	case "LOG_AUTHPRIV":
		p |= syslog.LOG_AUTHPRIV
	case "LOG_FTP":
		p |= syslog.LOG_FTP
	case "LOG_LOCAL0":
		p |= syslog.LOG_LOCAL0
	case "LOG_LOCAL1":
		p |= syslog.LOG_LOCAL1
	case "LOG_LOCAL2":
		p |= syslog.LOG_LOCAL2
	case "LOG_LOCAL3":
		p |= syslog.LOG_LOCAL3
	case "LOG_LOCAL4":
		p |= syslog.LOG_LOCAL4
	case "LOG_LOCAL5":
		p |= syslog.LOG_LOCAL5
	case "LOG_LOCAL6":
		p |= syslog.LOG_LOCAL6
	case "LOG_LOCAL7":
		p |= syslog.LOG_LOCAL7
	default:
		p |= syslog.LOG_LOCAL7
	}
	return p
}

func NewServer(syslogAddress string, syslogPriority syslog.Priority) (*Server, error) {
	var err error
	var writer *syslog.Writer
	s := new(Server)
	s.syslogAddress = syslogAddress
	s.syslogPriority = syslogPriority

	writer, err = syslog.Dial("udp", s.syslogAddress, s.syslogPriority,
		"pixel")
	// log.Printf("dial: %s %d", s.syslogAddress, s.syslogPriority)

	if err != nil {
		return nil, err
	}

	s.logger = log.New(writer, "", 0)
	s.now = time.Now
	return s, err
}

func NewEvent(t time.Time, r *http.Request) (event *Event, err error) {
	err = r.ParseForm()
	if err != nil {
		log.Printf("Malformed query string: %s", err)
		return
	}

	event = &Event{
		Time:   t.UTC().Format(ISO8601_FORMAT),
		Params: make(map[string]string),
	}

	for key, values := range r.Form {
		event.Params[key] = values[0]
	}

	event.UserAgent = r.Header.Get("User-Agent")
	event.IP = r.Header.Get("X-Forwarded-For")
	event.Proto = r.Header.Get("X-Forwarded-Proto")
	return event, err
}

func (s *Server) trackPixel(w http.ResponseWriter, r *http.Request) {
	var event *Event
	var err error
	var jsondata []byte

	event, err = NewEvent(s.now(), r)
	if err != nil {
		log.Printf("%s", err)
		http.Error(w, BAD_REQUEST, http.StatusBadRequest)
		return
	}

	w.Header().Set("Content-Type", "image/gif")
	w.Write(TRANSPARENT_1_PX_GIF_BYTES)

	jsondata, err = json.Marshal(event)
	if err != nil {
		log.Printf("json encode error: %s", err)
	} else {
		s.logger.Printf("%s", jsondata)
	}
}

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		s.trackPixel(w, r)
		return

	default:
		http.Error(w, BAD_REQUEST, http.StatusBadRequest)
	}
}

func (s *Server) ListenAndServe(address string) {
	s.httpServer = &http.Server{
		Addr:           address,
		Handler:        s,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	log.Fatal(s.httpServer.ListenAndServe())
}
<commit_msg>remove logging comment; standardize return args<commit_after>package pixel

import (
	"encoding/json"
	"log"
	"log/syslog"
	"net/http"
	"time"
)

type Server struct {
	listenAddress  string
	httpServer     *http.Server
	syslogAddress  string
	syslogPriority syslog.Priority
	logger         *log.Logger
	now            func() time.Time
}

type Event struct {
	Time      string            `json:"t"`
	Params    map[string]string `json:"params"`
	UserAgent string            `json:"ua,omitempty"`
	IP        string            `json:"ip,omitempty"`
	Proto     string            `json:"proto,omitempty"`
}

const ISO8601_FORMAT = "2006-01-02T15:04:05Z"

const TRANSPARENT_1_PX_GIF = "\x47\x49\x46\x38\x39\x61\x01\x00" +
	"\x01\x00\x80\x00\x00\xff\xff\xff\x00\x00\x00\x2c\x00\x00\x00\x00" +
	"\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3b"

var BAD_REQUEST string
var TRANSPARENT_1_PX_GIF_BYTES []byte

func init() {
	TRANSPARENT_1_PX_GIF_BYTES = []byte(TRANSPARENT_1_PX_GIF)
	BAD_REQUEST = http.StatusText(http.StatusBadRequest)
}

func NewSyslogPriority(level string, facility string) (p syslog.Priority) {
	switch level {
	case "LOG_EMERG":
		p = syslog.LOG_EMERG
	case "LOG_ALERT":
		p = syslog.LOG_ALERT
	case "LOG_CRIT":
		p = syslog.LOG_CRIT
	case "LOG_ERR":
		p = syslog.LOG_ERR
	case "LOG_WARNING":
		p = syslog.LOG_WARNING
	case "LOG_NOTICE":
		p = syslog.LOG_NOTICE
	case "LOG_INFO":
		p = syslog.LOG_INFO
	case "LOG_DEBUG":
		p = syslog.LOG_DEBUG
	default:
		p = syslog.LOG_INFO
	}

	switch facility {
	case "LOG_KERN":
		p |= syslog.LOG_KERN
	case "LOG_USER":
		p |= syslog.LOG_USER
	case "LOG_MAIL":
		p |= syslog.LOG_MAIL
	case "LOG_DAEMON":
		p |= syslog.LOG_DAEMON
	case "LOG_AUTH":
		p |= syslog.LOG_AUTH
	case "LOG_SYSLOG":
		p |= syslog.LOG_SYSLOG
	case "LOG_LPR":
		p |= syslog.LOG_LPR
	case "LOG_NEWS":
		p |= syslog.LOG_NEWS
	case "LOG_UUCP":
		p |= syslog.LOG_UUCP
	case "LOG_CRON":
		p |= syslog.LOG_CRON
	case "LOG_AUTHPRIV":
		p |= syslog.LOG_AUTHPRIV
	case "LOG_FTP":
		p |= syslog.LOG_FTP
	case "LOG_LOCAL0":
		p |= syslog.LOG_LOCAL0
	case "LOG_LOCAL1":
		p |= syslog.LOG_LOCAL1
	case "LOG_LOCAL2":
		p |= syslog.LOG_LOCAL2
	case "LOG_LOCAL3":
		p |= syslog.LOG_LOCAL3
	case "LOG_LOCAL4":
		p |= syslog.LOG_LOCAL4
	case "LOG_LOCAL5":
		p |= syslog.LOG_LOCAL5
	case "LOG_LOCAL6":
		p |= syslog.LOG_LOCAL6
	case "LOG_LOCAL7":
		p |= syslog.LOG_LOCAL7
	default:
		p |= syslog.LOG_LOCAL7
	}
	return p
}

func NewServer(syslogAddress string, syslogPriority syslog.Priority) (*Server, error) {
	var err error
	var writer *syslog.Writer
	s := new(Server)
	s.syslogAddress = syslogAddress
	s.syslogPriority = syslogPriority

	writer, err = syslog.Dial("udp", s.syslogAddress, s.syslogPriority,
		"pixel")

	if err != nil {
		return nil, err
	}

	s.logger = log.New(writer, "", 0)
	s.now = time.Now
	return s, err
}

func NewEvent(t time.Time, r *http.Request) (event *Event, err error) {
	err = r.ParseForm()
	if err != nil {
		log.Printf("Malformed query string: %s", err)
		return nil, err
	}

	event = &Event{
		Time:   t.UTC().Format(ISO8601_FORMAT),
		Params: make(map[string]string),
	}

	for key, values := range r.Form {
		event.Params[key] = values[0]
	}

	event.UserAgent = r.Header.Get("User-Agent")
	event.IP = r.Header.Get("X-Forwarded-For")
	event.Proto = r.Header.Get("X-Forwarded-Proto")
	return event, err
}

func (s *Server) trackPixel(w http.ResponseWriter, r *http.Request) {
	var event *Event
	var err error
	var jsondata []byte

	event, err = NewEvent(s.now(), r)
	if err != nil {
		log.Printf("%s", err)
		http.Error(w, BAD_REQUEST, http.StatusBadRequest)
		return
	}

	w.Header().Set("Content-Type", "image/gif")
	w.Write(TRANSPARENT_1_PX_GIF_BYTES)

	jsondata, err = json.Marshal(event)
	if err != nil {
		log.Printf("json encode error: %s", err)
	} else {
		s.logger.Printf("%s", jsondata)
	}
}

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		s.trackPixel(w, r)
		return

	default:
		http.Error(w, BAD_REQUEST, http.StatusBadRequest)
	}
}

func (s *Server) ListenAndServe(address string) {
	s.httpServer = &http.Server{
		Addr:           address,
		Handler:        s,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	log.Fatal(s.httpServer.ListenAndServe())
}
<|endoftext|>


<commit_before>package hookah

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"sync"
	"time"
)

var errsNotDir = errors.New("Given path is not a dir")
var validGhEvent = regexp.MustCompile(`^[a-z_]{1,30}$`)

// HookServer implements net/http.Handler
type HookServer struct {
	RootDir string
	Timeout time.Duration
	secret  string
	sync.Mutex
}

// NewHookServer instantiates a new HookServer with some basic validation
// on the root directory
func NewHookServer(rootdir, secret string, timeout time.Duration) (*HookServer, error) {
	f, err := os.Open(rootdir)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return nil, err
	}

	if !fi.IsDir() {
		return nil, errsNotDir
	}

	return &HookServer{
		RootDir: rootdir,
		Timeout: timeout,
		secret:  secret,
	}, nil
}

func (h *HookServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ghEvent := r.Header.Get("X-Github-Event")

	if !validGhEvent.MatchString(ghEvent) {
		http.Error(w, "Request requires valid X-Github-Event", http.StatusBadRequest)
		return
	}

	if ghEvent == "ping" {
		fmt.Fprintln(w, "pong")
		return
	}

	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		log.Println(err)
		return
	}
	buff := bytes.NewReader(b)

	if h.secret != "" {
		xSig := r.Header.Get("X-Hub-Signature")

		if xSig == "" {
			http.Error(w, "Missing required X-Hub-Signature for HMAC verification", http.StatusForbidden)
			log.Println("missing X-Hub-Signature")
			return
		}

		hash := hmac.New(sha1.New, []byte(h.secret))
		hash.Write(b)

		ehash := hash.Sum(nil)
		esig := "sha1=" + hex.EncodeToString(ehash)

		if !hmac.Equal([]byte(esig), []byte(xSig)) {
			http.Error(w, "HMAC verification failed", http.StatusForbidden)
			log.Println("HMAC verification failed")
			return
		}
	}

	basicHook := &HookJSON{}

	decoder := json.NewDecoder(buff)
	err = decoder.Decode(basicHook)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		log.Println(err)
		return
	}

	login := basicHook.Repository.Owner.GetLogin()
	repo := basicHook.Repository.Name

	fmt.Fprintf(w, "%s/%s", login, repo)

	if repo == "" || login == "" {
		http.Error(w, "Failed parsing JSON HTTP Body", http.StatusBadRequest)
		log.Println(err)
		return
	}

	hook := HookExec{
		RootDir: h.RootDir,

		Owner: login,
		Repo:  repo,

		Event: ghEvent,
		Data:  buff,

		HookServer: h,
	}

	go hook.Exec(h.Timeout)
}

// HookUserJSON exists because some hooks use Login, some use Name
// - it's horribly inconsistant
type HookUserJSON struct {
	Login string `json:"login"`
	Name  string `json:"name"`
}

// GetLogin is used to get the login from the data github decided to pass today
func (h *HookUserJSON) GetLogin() string {
	if h.Login != "" {
		return h.Login
	}

	return h.Name
}

// HookJSON represents the minimum body we need to parse
type HookJSON struct {
	Repository struct {
		Name  string       `json:"name"`
		Owner HookUserJSON `json:"owner"`
	} `json:"repository"`
	Sender HookUserJSON `json:"sender"`
}
<commit_msg>Corrects spelling<commit_after>package hookah

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"sync"
	"time"
)

var errsNotDir = errors.New("Given path is not a dir")
var validGhEvent = regexp.MustCompile(`^[a-z_]{1,30}$`)

// HookServer implements net/http.Handler
type HookServer struct {
	RootDir string
	Timeout time.Duration
	secret  string
	sync.Mutex
}

// NewHookServer instantiates a new HookServer with some basic validation
// on the root directory
func NewHookServer(rootdir, secret string, timeout time.Duration) (*HookServer, error) {
	f, err := os.Open(rootdir)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		return nil, err
	}

	if !fi.IsDir() {
		return nil, errsNotDir
	}

	return &HookServer{
		RootDir: rootdir,
		Timeout: timeout,
		secret:  secret,
	}, nil
}

func (h *HookServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ghEvent := r.Header.Get("X-Github-Event")

	if !validGhEvent.MatchString(ghEvent) {
		http.Error(w, "Request requires valid X-Github-Event", http.StatusBadRequest)
		return
	}

	if ghEvent == "ping" {
		fmt.Fprintln(w, "pong")
		return
	}

	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		log.Println(err)
		return
	}
	buff := bytes.NewReader(b)

	if h.secret != "" {
		xSig := r.Header.Get("X-Hub-Signature")

		if xSig == "" {
			http.Error(w, "Missing required X-Hub-Signature for HMAC verification", http.StatusForbidden)
			log.Println("missing X-Hub-Signature")
			return
		}

		hash := hmac.New(sha1.New, []byte(h.secret))
		hash.Write(b)

		ehash := hash.Sum(nil)
		esig := "sha1=" + hex.EncodeToString(ehash)

		if !hmac.Equal([]byte(esig), []byte(xSig)) {
			http.Error(w, "HMAC verification failed", http.StatusForbidden)
			log.Println("HMAC verification failed")
			return
		}
	}

	basicHook := &HookJSON{}

	decoder := json.NewDecoder(buff)
	err = decoder.Decode(basicHook)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		log.Println(err)
		return
	}

	login := basicHook.Repository.Owner.GetLogin()
	repo := basicHook.Repository.Name

	fmt.Fprintf(w, "%s/%s", login, repo)

	if repo == "" || login == "" {
		http.Error(w, "Failed parsing JSON HTTP Body", http.StatusBadRequest)
		log.Println(err)
		return
	}

	hook := HookExec{
		RootDir: h.RootDir,

		Owner: login,
		Repo:  repo,

		Event: ghEvent,
		Data:  buff,

		HookServer: h,
	}

	go hook.Exec(h.Timeout)
}

// HookUserJSON exists because some hooks use Login, some use Name
// - it's horribly inconsistent
type HookUserJSON struct {
	Login string `json:"login"`
	Name  string `json:"name"`
}

// GetLogin is used to get the login from the data github decided to pass today
func (h *HookUserJSON) GetLogin() string {
	if h.Login != "" {
		return h.Login
	}

	return h.Name
}

// HookJSON represents the minimum body we need to parse
type HookJSON struct {
	Repository struct {
		Name  string       `json:"name"`
		Owner HookUserJSON `json:"owner"`
	} `json:"repository"`
	Sender HookUserJSON `json:"sender"`
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"log"
	"net/http"
	"os"
)

var (
	// cfg is the global configuration for the server. It's read in at startup from
	// the config.json file and enviornment variables, see config.go for more info.
	cfg *config
	// log output
	logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
	// application database connection
	appDB *sql.DB
)

func main() {
	var err error
	cfg, err = initConfig(os.Getenv("GOLANG_ENV"))
	if err != nil {
		// panic if the server is missing a vital configuration detail
		panic(fmt.Errorf("server configuration error: %s", err.Error()))
	}

	connectToAppDb()

	s := &http.Server{}
	m := http.NewServeMux()

	m.HandleFunc("/", NotFoundHandler)
	m.Handle("/status", middleware(HealthCheckHandler))
	m.HandleFunc("/.well-known/acme-challenge/", CertbotHandler)

	// m.Handle("/v0/users", middleware(UserHandler))
	// m.Handle("/v0/users/", middleware(UsersHandler))
	m.Handle("/v0/primers", middleware(PrimersHandler))
	m.Handle("/v0/primers/", middleware(PrimerHandler))
	m.Handle("/v0/sources", middleware(SourcesHandler))
	m.Handle("/v0/sources/", middleware(SourceHandler))
	m.Handle("/v0/urls", middleware(UrlsHandler))
	m.Handle("/v0/urls/", middleware(UrlHandler))
	// m.Handle("/v0/links", middleware(UrlHandler))
	// m.Handle("/v0/links/", middleware(UrlsHandler))
	// m.Handle("/v0/snapshots", middleware())
	// m.Handle("/v0/snapshots/", middleware())
	// m.Handle("/v0/content", middleware())
	// m.Handle("/v0/content/", middleware())
	// m.Handle("/v0/metadata", middleware())
	// m.Handle("/v0/metadata/", middleware())
	// m.Handle("/v0/consensus", middleware())
	// m.Handle("/v0/consensus/", middleware())
	// m.Handle("/v0/collections", middleware())
	// m.Handle("/v0/collections/", middleware())

	// connect mux to server
	s.Handler = m

	// print notable config settings
	printConfigInfo()

	// fire it up!
	fmt.Println("starting server on port", cfg.Port)

	// start server wrapped in a log.Fatal b/c http.ListenAndServe will not
	// return unless there's an error
	logger.Fatal(StartServer(cfg, s))
}
<commit_msg>safety commit<commit_after>package main

import (
	"database/sql"
	"fmt"
	"log"
	"net/http"
	"os"
)

var (
	// cfg is the global configuration for the server. It's read in at startup from
	// the config.json file and enviornment variables, see config.go for more info.
	cfg *config
	// log output
	logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
	// application database connection
	appDB *sql.DB
)

func main() {
	var err error
	cfg, err = initConfig(os.Getenv("GOLANG_ENV"))
	if err != nil {
		// panic if the server is missing a vital configuration detail
		panic(fmt.Errorf("server configuration error: %s", err.Error()))
	}

	connectToAppDb()

	s := &http.Server{}
	m := http.NewServeMux()

	m.HandleFunc("/", NotFoundHandler)
	m.Handle("/status", middleware(HealthCheckHandler))
	m.HandleFunc("/.well-known/acme-challenge/", CertbotHandler)

	// m.Handle("/v0/users", middleware(UserHandler))
	// m.Handle("/v0/users/", middleware(UsersHandler))
	m.Handle("/v0/primers", middleware(PrimersHandler))
	m.Handle("/v0/primers/", middleware(PrimerHandler))
	m.Handle("/v0/sources", middleware(SourcesHandler))
	m.Handle("/v0/sources/", middleware(SourceHandler))
	m.Handle("/v0/urls", middleware(UrlsHandler))
	m.Handle("/v0/urls/", middleware(UrlHandler))

	// m.Handle("/v0/links", middleware(UrlHandler))
	// m.Handle("/v0/links/", middleware(UrlsHandler))
	// m.Handle("/v0/snapshots", middleware())
	// m.Handle("/v0/snapshots/", middleware())
	// m.Handle("/v0/content", middleware())
	// m.Handle("/v0/content/", middleware())
	// m.Handle("/v0/metadata", middleware())
	// m.Handle("/v0/metadata/", middleware())
	// m.Handle("/v0/consensus", middleware())
	// m.Handle("/v0/consensus/", middleware())
	// m.Handle("/v0/collections", middleware())
	// m.Handle("/v0/collections/", middleware())

	// connect mux to server
	s.Handler = m

	// print notable config settings
	printConfigInfo()

	// fire it up!
	fmt.Println("starting server on port", cfg.Port)

	// start server wrapped in a log.Fatal b/c http.ListenAndServe will not
	// return unless there's an error
	logger.Fatal(StartServer(cfg, s))
}
<|endoftext|>


<commit_before>// Package mannersagain combines manners and goagain to provide graceful hot
// restarting of net/http servers.
package mannersagain

import (
	"errors"
	"log"
	"net"
	"net/http"
	"os"
	"time"

	"github.com/braintree/manners"
	"github.com/titanous/goagain"
)

func newListener(l net.Listener) net.Listener {
	return listener{Listener: l, closed: make(chan struct{})}
}

type listener struct {
	net.Listener
	closed chan struct{}
}

var ErrClosed = errors.New("mannersagain: listener has been gracefully closed")

func (l listener) Accept() (net.Conn, error) {
	for {
		select {
		case <-l.closed:
			return nil, ErrClosed
		default:
		}

		// Set a deadline so Accept doesn't block forever, which gives
		// us an opportunity to stop gracefully.
		l.Listener.(*net.TCPListener).SetDeadline(time.Now().Add(100 * time.Millisecond))
		c, err := l.Listener.Accept()
		if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
			continue
		}
		return c, err
	}
}

func (l listener) Close() error {
	close(l.closed)
	return nil
}

func ListenAndServe(addr string, handler http.Handler) error {
	var gl *manners.GracefulListener
	srv := manners.NewServer()

	done := make(chan struct{})
	serve := func(l net.Listener) {
		srv.Serve(l, handler)
		close(done)
	}

	// Attempt to inherit a listener from our parent
	l, err := goagain.Listener()
	if err != nil {
		// We don't have an inherited listener, create a new one
		l, err = net.Listen("tcp", addr)
		if err != nil {
			return err
		}
		log.Println("Listening on", l.Addr())
		gl = manners.NewListener(newListener(l), srv)
		go serve(gl)
	} else {
		log.Println("Resuming listening on", l.Addr())
		gl = manners.NewListener(newListener(l), srv)
		go serve(gl)

		if err := goagain.Kill(); nil != err {
			return err
		}
	}

	// Block the main goroutine awaiting signals.
	sig, err := goagain.Wait(l)
	if err != nil {
		return err
	}

	// Wait returns one of SIGINT, SIGTERM, SIGQUIT, SIGUSR2
	// We should stop gracefully if we receive one of the second two
	if sig != goagain.SIGINT && sig != goagain.SIGTERM {
		// Stop accepting new connections
		gl.Close()
		// Wait for all existing connections to complete
		<-done
	}

	if goagain.Strategy == goagain.Double && sig == goagain.SIGUSR2 {
		// If we received SIGUSR2, re-exec the parent process.
		if err := goagain.Exec(l); err != nil {
			return err
		}
	}

	// We were told to exit, so do it!
	os.Exit(0)
	return nil
}
<commit_msg>Use fork of manners to fix WaitGroup multiple decrement<commit_after>// Package mannersagain combines manners and goagain to provide graceful hot
// restarting of net/http servers.
package mannersagain

import (
	"errors"
	"log"
	"net"
	"net/http"
	"os"
	"time"

	"github.com/titanous/goagain"
	"github.com/titanous/manners"
)

func newListener(l net.Listener) net.Listener {
	return listener{Listener: l, closed: make(chan struct{})}
}

type listener struct {
	net.Listener
	closed chan struct{}
}

var ErrClosed = errors.New("mannersagain: listener has been gracefully closed")

func (l listener) Accept() (net.Conn, error) {
	for {
		select {
		case <-l.closed:
			return nil, ErrClosed
		default:
		}

		// Set a deadline so Accept doesn't block forever, which gives
		// us an opportunity to stop gracefully.
		l.Listener.(*net.TCPListener).SetDeadline(time.Now().Add(100 * time.Millisecond))
		c, err := l.Listener.Accept()
		if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
			continue
		}
		return c, err
	}
}

func (l listener) Close() error {
	close(l.closed)
	return nil
}

func ListenAndServe(addr string, handler http.Handler) error {
	var gl *manners.GracefulListener
	srv := manners.NewServer()

	done := make(chan struct{})
	serve := func(l net.Listener) {
		srv.Serve(l, handler)
		close(done)
	}

	// Attempt to inherit a listener from our parent
	l, err := goagain.Listener()
	if err != nil {
		// We don't have an inherited listener, create a new one
		l, err = net.Listen("tcp", addr)
		if err != nil {
			return err
		}
		log.Println("Listening on", l.Addr())
		gl = manners.NewListener(newListener(l), srv)
		go serve(gl)
	} else {
		log.Println("Resuming listening on", l.Addr())
		gl = manners.NewListener(newListener(l), srv)
		go serve(gl)

		if err := goagain.Kill(); nil != err {
			return err
		}
	}

	// Block the main goroutine awaiting signals.
	sig, err := goagain.Wait(l)
	if err != nil {
		return err
	}

	// Wait returns one of SIGINT, SIGTERM, SIGQUIT, SIGUSR2
	// We should stop gracefully if we receive one of the second two
	if sig != goagain.SIGINT && sig != goagain.SIGTERM {
		// Stop accepting new connections
		gl.Close()
		// Wait for all existing connections to complete
		<-done
	}

	if goagain.Strategy == goagain.Double && sig == goagain.SIGUSR2 {
		// If we received SIGUSR2, re-exec the parent process.
		if err := goagain.Exec(l); err != nil {
			return err
		}
	}

	// We were told to exit, so do it!
	os.Exit(0)
	return nil
}
<|endoftext|>


<commit_before>package datahub

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strconv"

	"github.com/NeowayLabs/datahub/company"
	"github.com/NeowayLabs/datahub/scientists"
	"github.com/julienschmidt/httprouter"
)

// Server ...
type Server struct {
	router     *httprouter.Router
	datadir    string
	log        *log.Logger
	company    *company.Company
	scientists *scientists.Scientists
}

// NewServer ...
func NewServer() *Server {
	const datadir string = "./.repo"
	log := log.New(os.Stdout, "datahub.server", log.Lshortfile|log.Lmicroseconds)
	err := os.MkdirAll(datadir, 0755)
	if err != nil {
		log.Fatalf("error %q creating data dir %q", err, datadir)
	}

	router := httprouter.New()
	company := company.NewCompany()
	scientists := scientists.NewScientists()

	d := &Server{
		router:     router,
		datadir:    datadir,
		log:        log,
		company:    company,
		scientists: scientists,
	}

	router.GET("/api/companies/jobs", d.companiesGetJobs)

	router.POST("/api/companies/jobs", d.companiesCreateJob)
	router.GET("/api/companies/jobs/:id", d.companiesGetJob)
	router.POST("/api/companies/job/:id/upload", d.companiesUploadJob)
	router.POST("/api/companies/jobs/:id/start", d.companiesStartJob)

	router.GET("/api/scientists", d.scientistsList)

	router.GET("/api/scientists/:id/jobs", d.scientistsGetJobs)
	router.POST("/api/scientists/:id/jobs/:job/apply", d.scientistsApplyJob)
	router.GET("/api/scientists/:id/jobs/:job/workspace", d.scientistsGetWorkspace)
	router.POST("/api/scientists/:id/jobs/:job/upload", d.companiesUploadCode)

	router.POST("/api/execR", d.execR)

	return d
}

func (d *Server) companiesUploadJob(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	uploadFileNames := []string{
		"code.r",
		"trainingset.csv",
		"testset.challenge.csv",
		"testset.result.csv",
	}

	jobID := params.ByName("id")

	success := false
	for _, filename := range uploadFileNames {
		res := d.receiveUpload(req, filename, jobID)
		if res {
			success = res
		}
	}
	if !success {
		d.failrequest(
			w,
			"no dataset received, expected one of these: %q",
			uploadFileNames,
		)
		return
	}
	w.WriteHeader(http.StatusOK)
}

// Jobs ...
type Jobs struct {
	Pending []*company.Job `json:"pending"`
	Doing   []*company.Job `json:"doing"`
	Done    []*company.Job `json:"done"`
}

func (d *Server) companiesGetJobs(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	scientists := d.scientists.GetScientists()

	bytes, err := json.Marshal(scientists)
	if err != nil {
		d.log.Printf("marshal: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	if _, err := w.Write(bytes); err != nil {
		d.log.Printf("write: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
	}
}

func (d *Server) companiesCreateJob(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	decoder := json.NewDecoder(req.Body)

	var job company.Job
	if err := decoder.Decode(&job); err != nil {
		d.log.Printf("unmarshal: error %q", err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	d.company.AddNewJob(&job)

	w.WriteHeader(http.StatusOK)
}

func getID(params httprouter.Params) (int, error) {
	s := params.ByName("id")
	if s == "" {
		return 0, fmt.Errorf("param: id is empty")
	}

	id, err := strconv.Atoi(s)
	if err != nil {
		return 0, fmt.Errorf("param: id is not a number")
	}

	return id, nil
}

func (d *Server) companiesGetJob(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	id, err := getID(params)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	job := d.company.GetJob(id)
	if job == nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	bytes, err := json.Marshal(job)
	if err != nil {
		d.log.Printf("marshal: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	if _, err := w.Write(bytes); err != nil {
		d.log.Printf("write: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
	}
}

func (d *Server) companiesStartJob(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	type Scientists struct {
		Scientists []*company.Scientist `json:"scientists"`
	}

	job, err := getID(params)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	decoder := json.NewDecoder(req.Body)

	var scientists Scientists
	if err := decoder.Decode(&scientists); err != nil {
		d.log.Printf("unmarshal: error %q", err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	if err := d.company.StartJob(job, scientists.Scientists); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
}

func (d *Server) scientistsList(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	w.WriteHeader(http.StatusNotImplemented)
}

func (d *Server) scientistsGetJobs(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
	//TODO
	w.WriteHeader(http.StatusNotImplemented)
}

func (d *Server) scientistsApplyJob(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
	//TODO
	w.WriteHeader(http.StatusNotImplemented)
}

func (d *Server) scientistsGetWorkspace(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
	//TODO
	w.WriteHeader(http.StatusNotImplemented)
}

func (d *Server) companiesUploadCode(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
	//TODO
	w.WriteHeader(http.StatusNotImplemented)
}

func (d *Server) execR(
	w http.ResponseWriter,
	req *http.Request,
	_ httprouter.Params,
) {
	// TODO: Still not getting stderr
	cwd, err := os.Getwd()
	if err != nil {
		d.failrequest(w, "getwd: unexpected error %q", err)
		return
	}
	err = os.Chdir(cwd + "/" + d.datadir)
	if err != nil {
		d.failrequest(w, "chdir: unexpected error %q", err)
		return
	}
	defer func() {
		if err := os.Chdir(cwd); err != nil {
			d.log.Printf("chdir: unexpected error %q", err)
		}
	}()

	cmd := exec.Command("R", "-f", "./code.r")
	d.log.Printf("executing R code")
	res, err := cmd.CombinedOutput()

	if err != nil {
		d.failrequest(w, "exec R: unexpected error %q", err)
		return
	}
	d.log.Printf("executed R code with success")

	w.WriteHeader(http.StatusOK)
	_, err = w.Write(res)
	if err != nil {
		d.log.Printf("unexpected error %q sending response", err)
		return
	}
}

func (d *Server) receiveUpload(
	req *http.Request,
	filename string,
	jobID string,
) bool {
	uploadedfile, _, err := req.FormFile(filename)
	if err != nil {
		d.log.Printf("%q parsing form", err)
		return false
	}

	defer func() {
		if err := uploadedfile.Close(); err != nil {
			d.log.Printf("close: unexpected error %q", err)
		}
	}()

	filepath := d.datadir + "/" + filename
	d.log.Printf("creating file %q", filepath)
	file, err := os.Create(filepath)
	if err != nil {
		d.log.Printf("error: %q opening file %q", err, filepath)
		return false
	}
	d.log.Printf("created file with success, copying contents")
	_, err = io.Copy(file, uploadedfile)
	if err != nil {
		d.log.Printf("error: %q copying file", err)
		return false
	}
	d.log.Printf("finished copying from form %q with success", filename)
	return true
}

func (d *Server) failrequest(
	w http.ResponseWriter,
	fmt string,
	args ...interface{},
) {
	d.log.Printf(fmt, args...)
	w.WriteHeader(http.StatusInternalServerError)
}

// Handler ...
func (d *Server) Handler() http.Handler {
	return d.router
}

// ListenAndServe ...
func (d *Server) ListenAndServe(addr string) error {
	d.log.Printf("WebServer running at %q", addr)
	return http.ListenAndServe(addr, d.router)
}
<commit_msg>Fixed GetCompanyJobs<commit_after>package datahub

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strconv"

	"github.com/NeowayLabs/datahub/company"
	"github.com/NeowayLabs/datahub/scientists"
	"github.com/julienschmidt/httprouter"
)

// Server ...
type Server struct {
	router     *httprouter.Router
	datadir    string
	log        *log.Logger
	company    *company.Company
	scientists *scientists.Scientists
}

// NewServer ...
func NewServer() *Server {
	const datadir string = "./.repo"
	log := log.New(os.Stdout, "datahub.server", log.Lshortfile|log.Lmicroseconds)
	err := os.MkdirAll(datadir, 0755)
	if err != nil {
		log.Fatalf("error %q creating data dir %q", err, datadir)
	}

	router := httprouter.New()
	company := company.NewCompany()
	scientists := scientists.NewScientists()

	d := &Server{
		router:     router,
		datadir:    datadir,
		log:        log,
		company:    company,
		scientists: scientists,
	}

	router.GET("/api/companies/jobs", d.companiesGetJobs)

	router.POST("/api/companies/jobs", d.companiesCreateJob)
	router.GET("/api/companies/jobs/:id", d.companiesGetJob)
	router.POST("/api/companies/job/:id/upload", d.companiesUploadJob)
	router.POST("/api/companies/jobs/:id/start", d.companiesStartJob)

	router.GET("/api/scientists", d.scientistsList)

	router.GET("/api/scientists/:id/jobs", d.scientistsGetJobs)
	router.POST("/api/scientists/:id/jobs/:job/apply", d.scientistsApplyJob)
	router.GET("/api/scientists/:id/jobs/:job/workspace", d.scientistsGetWorkspace)
	router.POST("/api/scientists/:id/jobs/:job/upload", d.companiesUploadCode)

	router.POST("/api/execR", d.execR)

	return d
}

func (d *Server) companiesUploadJob(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	uploadFileNames := []string{
		"code.r",
		"trainingset.csv",
		"testset.challenge.csv",
		"testset.result.csv",
	}

	jobID := params.ByName("id")

	success := false
	for _, filename := range uploadFileNames {
		res := d.receiveUpload(req, filename, jobID)
		if res {
			success = res
		}
	}
	if !success {
		d.failrequest(
			w,
			"no dataset received, expected one of these: %q",
			uploadFileNames,
		)
		return
	}
	w.WriteHeader(http.StatusOK)
}

// Jobs ...
type Jobs struct {
	Pending []*company.Job `json:"pending"`
	Doing   []*company.Job `json:"doing"`
	Done    []*company.Job `json:"done"`
}

func (d *Server) companiesGetJobs(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	pending := d.company.GetJobsByStatus("pending")
	doing := d.company.GetJobsByStatus("doing")
	done := d.company.GetJobsByStatus("done")

	jobs := &Jobs{
		Pending: pending,
		Doing:   doing,
		Done:    done,
	}

	bytes, err := json.Marshal(jobs)
	if err != nil {
		d.log.Printf("marshal: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	if _, err := w.Write(bytes); err != nil {
		d.log.Printf("write: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
	}
}

func (d *Server) companiesCreateJob(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	decoder := json.NewDecoder(req.Body)

	var job company.Job
	if err := decoder.Decode(&job); err != nil {
		d.log.Printf("unmarshal: error %q", err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	d.company.AddNewJob(&job)

	w.WriteHeader(http.StatusOK)
}

func getID(params httprouter.Params) (int, error) {
	s := params.ByName("id")
	if s == "" {
		return 0, fmt.Errorf("param: id is empty")
	}

	id, err := strconv.Atoi(s)
	if err != nil {
		return 0, fmt.Errorf("param: id is not a number")
	}

	return id, nil
}

func (d *Server) companiesGetJob(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	id, err := getID(params)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	job := d.company.GetJob(id)
	if job == nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	bytes, err := json.Marshal(job)
	if err != nil {
		d.log.Printf("marshal: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	if _, err := w.Write(bytes); err != nil {
		d.log.Printf("write: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
	}
}

func (d *Server) companiesStartJob(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	type Scientists struct {
		Scientists []*company.Scientist `json:"scientists"`
	}

	job, err := getID(params)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	decoder := json.NewDecoder(req.Body)

	var scientists Scientists
	if err := decoder.Decode(&scientists); err != nil {
		d.log.Printf("unmarshal: error %q", err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	if err := d.company.StartJob(job, scientists.Scientists); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
}

func (d *Server) scientistsList(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	defer func() {
		if err := req.Body.Close(); err != nil {
			d.log.Printf("body close: error %q", err)
		}
	}()

	scientists := d.scientists.GetScientists()

	bytes, err := json.Marshal(scientists)
	if err != nil {
		d.log.Printf("marshal: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	if _, err := w.Write(bytes); err != nil {
		d.log.Printf("write: error %q", err)
		w.WriteHeader(http.StatusInternalServerError)
	}
}

func (d *Server) scientistsGetJobs(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
	//TODO
	w.WriteHeader(http.StatusNotImplemented)
}

func (d *Server) scientistsApplyJob(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
	//TODO
	w.WriteHeader(http.StatusNotImplemented)
}

func (d *Server) scientistsGetWorkspace(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
	//TODO
	w.WriteHeader(http.StatusNotImplemented)
}

func (d *Server) companiesUploadCode(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
	//TODO
	w.WriteHeader(http.StatusNotImplemented)
}

func (d *Server) execR(
	w http.ResponseWriter,
	req *http.Request,
	_ httprouter.Params,
) {
	// TODO: Still not getting stderr
	cwd, err := os.Getwd()
	if err != nil {
		d.failrequest(w, "getwd: unexpected error %q", err)
		return
	}
	err = os.Chdir(cwd + "/" + d.datadir)
	if err != nil {
		d.failrequest(w, "chdir: unexpected error %q", err)
		return
	}
	defer func() {
		if err := os.Chdir(cwd); err != nil {
			d.log.Printf("chdir: unexpected error %q", err)
		}
	}()

	cmd := exec.Command("R", "-f", "./code.r")
	d.log.Printf("executing R code")
	res, err := cmd.CombinedOutput()

	if err != nil {
		d.failrequest(w, "exec R: unexpected error %q", err)
		return
	}
	d.log.Printf("executed R code with success")

	w.WriteHeader(http.StatusOK)
	_, err = w.Write(res)
	if err != nil {
		d.log.Printf("unexpected error %q sending response", err)
		return
	}
}

func (d *Server) receiveUpload(
	req *http.Request,
	filename string,
	jobID string,
) bool {
	uploadedfile, _, err := req.FormFile(filename)
	if err != nil {
		d.log.Printf("%q parsing form", err)
		return false
	}

	defer func() {
		if err := uploadedfile.Close(); err != nil {
			d.log.Printf("close: unexpected error %q", err)
		}
	}()

	filepath := d.datadir + "/" + filename
	d.log.Printf("creating file %q", filepath)
	file, err := os.Create(filepath)
	if err != nil {
		d.log.Printf("error: %q opening file %q", err, filepath)
		return false
	}
	d.log.Printf("created file with success, copying contents")
	_, err = io.Copy(file, uploadedfile)
	if err != nil {
		d.log.Printf("error: %q copying file", err)
		return false
	}
	d.log.Printf("finished copying from form %q with success", filename)
	return true
}

func (d *Server) failrequest(
	w http.ResponseWriter,
	fmt string,
	args ...interface{},
) {
	d.log.Printf(fmt, args...)
	w.WriteHeader(http.StatusInternalServerError)
}

// Handler ...
func (d *Server) Handler() http.Handler {
	return d.router
}

// ListenAndServe ...
func (d *Server) ListenAndServe(addr string) error {
	d.log.Printf("WebServer running at %q", addr)
	return http.ListenAndServe(addr, d.router)
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "regexp"
    "net/http"
)

// Define HTTP route structure for the server
type Route struct {
    pattern *regexp.Regexp
    method  string
    handler http.Handler
}

<commit_msg>Very small gorilla mux based router + server<commit_after>package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"net/http"
)

// Main entry point
func main() {
	router := mux.NewRouter()

	// Define error'd route handler
	router.NotFoundHandler = http.HandlerFunc(Render404)

	// Define various application routes here
	router.HandleFunc("/", RenderIndex).Methods("GET")

	// Use the above router for all routes
	http.Handle("/", router)

	fmt.Printf("Server up and listening...")
	http.ListenAndServe("0.0.0.0:3000", nil)
}

// Render 4040 page
func Render404(response http.ResponseWriter, request *http.Request) {
	response.Write([]byte("Hmm looks like we 404'd trying to find: " + request.URL.Path))
}

// Render Home page
func RenderIndex(response http.ResponseWriter, request *http.Request) {
	response.Write([]byte("Hello world!"))
}
<|endoftext|>


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

package httputils

import (
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
)

// Provide a HTTP server implementation which can listen on TPC
// and Unix Domain sockets.
type Server struct {
	http.Server
	*log.Logger
}

// ListenAndServe binds sockets according to the configuration of srv and blocks
// until the socket closes or an exit signal is received.
func (srv *Server) ListenAndServe() error {

	addr := srv.Addr
	if addr == "" {
		addr = ":http"
	}

	var closing = false
	var err error
	var l net.Listener
	if l, err = srv.socketListen(addr); err != nil {
		return err
	}

	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-sig
		msg := "Received exit signal %d - Closing ..."
		if srv.Logger != nil {
			srv.Logger.Printf(msg, s)
		} else {
			log.Printf(msg, s)
		}
		closing = true
		l.Close()
	}()

	err = srv.Serve(l)
	if err != nil {
		if closing {
			return nil
		}
	}
	return err

}

// ListenAndServeTLS binds sockets according to the configuration of srv and blocks
// until the socket closes or an exit signal is received.
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {

	addr := srv.Addr
	if addr == "" {
		addr = ":https"
	}

	config := &tls.Config{}
	if srv.TLSConfig != nil {
		*config = *srv.TLSConfig
	}
	if config.NextProtos == nil {
		config.NextProtos = []string{"http/1.1"}
	}

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

	var closing = false
	var l net.Listener
	if l, err = srv.socketListen(addr); err != nil {
		return err
	}

	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-sig
		msg := "Received exit signal %d - Closing ..."
		if srv.Logger != nil {
			srv.Logger.Printf(msg, s)
		} else {
			log.Printf(msg, s)
		}
		closing = true
		l.Close()
	}()

	tlsListener := tls.NewListener(l, config)

	err = srv.Serve(tlsListener)
	if err != nil {
		if closing {
			return nil
		}
	}
	return err

}

// ListenAndServeTLSAdvanced binds sockets according to the configuration
// of srv and blocks until the socket closes or an exit signal is received. A
// TLSConfig needs to be available at the server.
func (srv *Server) ListenAndServeTLSAdvanced() error {

	addr := srv.Addr
	if addr == "" {
		addr = ":https"
	}

	config := srv.TLSConfig

	if config == nil {
		return errors.New("TLSConfig required")
	}
	if config.NextProtos == nil {
		config.NextProtos = []string{"http/1.1"}
	}

	if len(config.Certificates) == 0 {
		return errors.New("TLSConfig has no certificate")
	}

	var err error
	var closing = false
	var l net.Listener
	if l, err = srv.socketListen(addr); err != nil {
		return err
	}

	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-sig
		msg := "Received exit signal %d - Closing ..."
		if srv.Logger != nil {
			srv.Logger.Printf(msg, s)
		} else {
			log.Printf(msg, s)
		}
		closing = true
		l.Close()
	}()

	tlsListener := tls.NewListener(l, config)

	err = srv.Serve(tlsListener)
	if err != nil {
		if closing {
			return nil
		}
	}
	return err

}

func (srv *Server) socketListen(addr string) (net.Listener, error) {

	var err error
	var l net.Listener

	if strings.HasPrefix(addr, "/") {
		var laddr *net.UnixAddr
		if laddr, err = net.ResolveUnixAddr("unix", addr); err != nil {
			return nil, err
		}
		if l, err = createUnixSocket(laddr); err != nil {
			// Unix-domain-socket already exists, try to connect to it to
			// see if it still is usedb by another process
			if _, err = net.Dial("unix", addr); err != nil {
				if err = os.Remove(addr); err != nil {
					return nil, err
				}
				if l, err = createUnixSocket(laddr); err != nil {
					return nil, err
				}
			} else {
				return nil, fmt.Errorf("another process seems to be listening on %s already", addr)
			}
		}
	} else {
		var laddr *net.TCPAddr
		if laddr, err = net.ResolveTCPAddr("tcp", addr); err != nil {
			return nil, err
		}
		if l, err = net.ListenTCP("tcp", laddr); err != nil {
			return nil, err
		}
	}

	return l, nil

}

func createUnixSocket(addr *net.UnixAddr) (l net.Listener, err error) {
	l, err = net.ListenUnix("unix", addr)

	if err != nil {
		return
	}

	// TODO(lcooper): Not sure if this sequence is completely safe.
	// It would be better if we could get the underlying FD of the socket
	// and stat() + chmod() that instead.
	fi, err := os.Stat(addr.String())
	if err != nil {
		return
	}

	// NOTE(lcooper): This only ensures g+w other then on Linux,
	// BSD systems only use parent directory permissions.
	// See http://stackoverflow.com/questions/5977556 .
	err = os.Chmod(addr.String(), fi.Mode()|0060)
	return
}
<commit_msg>Removed duplicated code.<commit_after>// Copyright 2014 struktur AG. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package httputils

import (
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
)

// Provide a HTTP server implementation which can listen on TPC
// and Unix Domain sockets.
type Server struct {
	http.Server
	*log.Logger
}

// ListenAndServe binds sockets according to the configuration of srv and blocks
// until the socket closes or an exit signal is received.
func (srv *Server) ListenAndServe() error {

	addr := srv.Addr
	if addr == "" {
		addr = ":http"
	}

	var closing = false
	var err error
	var l net.Listener
	if l, err = srv.socketListen(addr); err != nil {
		return err
	}

	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-sig
		msg := "Received exit signal %d - Closing ..."
		if srv.Logger != nil {
			srv.Logger.Printf(msg, s)
		} else {
			log.Printf(msg, s)
		}
		closing = true
		l.Close()
	}()

	err = srv.Serve(l)
	if err != nil {
		if closing {
			return nil
		}
	}
	return err

}

// ListenAndServeTLS binds sockets according to the configuration of srv and blocks
// until the socket closes or an exit signal is received.
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {

	config := &tls.Config{}
	if srv.TLSConfig != nil {
		*config = *srv.TLSConfig
	}

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

    return srv.ListenAndServeTLSWithConfig(config)

}

// ListenAndServeTLSAdvanced binds sockets according to the configuration
// of srv and blocks until the socket closes or an exit signal is received. A
// TLSConfig needs to be available at the server.
func (srv *Server) ListenAndServeTLSWithConfig(config *tls.Config) error {

	addr := srv.Addr
	if addr == "" {
		addr = ":https"
	}

	if config == nil {
		return errors.New("TLSConfig required")
	}
	if config.NextProtos == nil {
		config.NextProtos = []string{"http/1.1"}
	}

	if len(config.Certificates) == 0 {
		return errors.New("TLSConfig has no certificate")
	}

	var err error
	var closing = false
	var l net.Listener
	if l, err = srv.socketListen(addr); err != nil {
		return err
	}

	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-sig
		msg := "Received exit signal %d - Closing ..."
		if srv.Logger != nil {
			srv.Logger.Printf(msg, s)
		} else {
			log.Printf(msg, s)
		}
		closing = true
		l.Close()
	}()

	tlsListener := tls.NewListener(l, config)

	err = srv.Serve(tlsListener)
	if err != nil {
		if closing {
			return nil
		}
	}
	return err

}

func (srv *Server) socketListen(addr string) (net.Listener, error) {

	var err error
	var l net.Listener

	if strings.HasPrefix(addr, "/") {
		var laddr *net.UnixAddr
		if laddr, err = net.ResolveUnixAddr("unix", addr); err != nil {
			return nil, err
		}
		if l, err = createUnixSocket(laddr); err != nil {
			// Unix-domain-socket already exists, try to connect to it to
			// see if it still is usedb by another process
			if _, err = net.Dial("unix", addr); err != nil {
				if err = os.Remove(addr); err != nil {
					return nil, err
				}
				if l, err = createUnixSocket(laddr); err != nil {
					return nil, err
				}
			} else {
				return nil, fmt.Errorf("another process seems to be listening on %s already", addr)
			}
		}
	} else {
		var laddr *net.TCPAddr
		if laddr, err = net.ResolveTCPAddr("tcp", addr); err != nil {
			return nil, err
		}
		if l, err = net.ListenTCP("tcp", laddr); err != nil {
			return nil, err
		}
	}

	return l, nil

}

func createUnixSocket(addr *net.UnixAddr) (l net.Listener, err error) {
	l, err = net.ListenUnix("unix", addr)

	if err != nil {
		return
	}

	// TODO(lcooper): Not sure if this sequence is completely safe.
	// It would be better if we could get the underlying FD of the socket
	// and stat() + chmod() that instead.
	fi, err := os.Stat(addr.String())
	if err != nil {
		return
	}

	// NOTE(lcooper): This only ensures g+w other then on Linux,
	// BSD systems only use parent directory permissions.
	// See http://stackoverflow.com/questions/5977556 .
	err = os.Chmod(addr.String(), fi.Mode()|0060)
	return
}
<|endoftext|>


<commit_before>// get show and movie source download links
package main

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"regexp"
	"strings"
	"sync"
)

type Media struct {
	Name string
	Size string
	Link string
}

//zmz.tv needs to login before downloading
var zmzClient http.Client

func getMovieFromLBL(movie string, results chan string, wg *sync.WaitGroup) {
	defer wg.Done()
	var id string
	resp, _ := http.Get("http://www.lbldy.com/search/" + movie)
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	re, _ := regexp.Compile("
")
	//find first match case
	firstId := re.FindSubmatch(body)
	if len(firstId) == 0 {
		results <- fmt.Sprintf("No results for *%s* from LBL", movie)
		return
	} else {
		id = string(firstId[1])
		resp, _ = http.Get("http://www.lbldy.com/movie/" + id + ".html")
		defer resp.Body.Close()
		re, _ = regexp.Compile(`<p><a href="(.*?)"( target="_blank">|>)(.*?)</a></p>`)
		body, _ := ioutil.ReadAll(resp.Body)
		//go does not support (?!) regex
		body = []byte(strings.Replace(string(body), `<a href="/xunlei/"`, "", -1))
		downloads := re.FindAllSubmatch(body, -1)
		if len(downloads) == 0 {
			results <- fmt.Sprintf("No results for *%s* from LBL", movie)
			return
		} else {
			ret := "Results from LBL:\n\n"
			for i := range downloads {
				ret += fmt.Sprintf("*%s*\n```%s```\n\n", string(downloads[i][3]), string(downloads[i][1]))
				//when results are too large, we split it.
				if i%5 == 0 && i > 0 {
					results <- ret
					ret = fmt.Sprintf("*LBL Part %d*\n\n", i/5+1)
				}
			}
			results <- ret
		}
	}
}

func getMovieFromZMZ(movie string, results chan string, wg *sync.WaitGroup) {
	defer wg.Done()
	loginZMZ()
	if ms := getZMZResource(movie, "0", "0"); ms == nil {
		results <- fmt.Sprintf("No results for *%s* from ZMZ", movie)
		return
	} else {
		ret := "Results from ZMZ:\n\n"
		for i, m := range ms {
			name := m.Name
			size := m.Size
			link := m.Link
			ret += fmt.Sprintf("*%s*(%s)\n```%s```\n\n", name, size, link)
			if i%3 == 0 && i > 0 {
				results <- ret
				ret = fmt.Sprintf("*ZMZ Part %d*\n\n", i/3+1)
			}
		}
		results <- ret
	}
	return
}

func getShowFromZMZ(show, s, e string, results chan string) (found bool) {
	loginZMZ()
	ms := getZMZResource(show, s, e)
	if ms == nil {
		results <- fmt.Sprintf("No results found for *S%sE%s*", s, e)
		return false
	}
	for _, m := range ms {
		name := m.Name
		size := m.Size
		link := m.Link
		results <- fmt.Sprintf("*ZMZ %s*(%s)\n```%s```\n\n", name, size, link)
	}
	return true
}

//get show and get movie from zmz both uses this function
func getZMZResource(name, season, episode string) []Media {
	id := getZMZResourceId(name)
	if id == "" {
		return nil
	}
	resourceURL := "http://www.zimuzu.tv/resource/list/" + id
	resp, _ := zmzClient.Get(resourceURL)
	defer resp.Body.Close()
	//1.name 2.size 3.link
	var ms []Media
	doc, err := goquery.NewDocumentFromReader(io.Reader(resp.Body))
	if err != nil {
		return nil
	}
	doc.Find("li.clearfix").Each(func(i int, selection *goquery.Selection) {
		s, _ := selection.Attr("season")
		e, _ := selection.Attr("episode")
		if e != episode || s != season {
			return
		}
		name := selection.Find(".fl a").Text()
		link, _ := selection.Find(".fr a").Attr("href")
		var size string
		if strings.HasPrefix(link, "ed2k") || strings.HasPrefix(link, "magnet") {
			size = selection.Find(".fl font.f3").Text()
			if size == "" || size == "0" {
				size = "unknown_size"
			}
			m := Media{
				Name: name,
				Link: link,
				Size: size,
			}
			ms = append(ms, m)
		}
	})
	return ms
}

func getZMZResourceId(name string) (id string) {
	queryURL := fmt.Sprintf("http://www.zimuzu.tv/search?keyword=%s&type=resource", name)
	re, _ := regexp.Compile(`<div class="t f14"><a href="/resource/(.*?)"><strong class="list_title">`)
	resp, _ := zmzClient.Get(queryURL)
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	//find first match case
	firstId := re.FindSubmatch(body)
	if len(firstId) == 0 {
		return
	} else {
		log.Println(id)
		id = string(firstId[1])
		return
	}
}

//login zmz first because zmz don't allow login at different browsers, but I have two robots...
func loginZMZ() {
	gCookieJar, _ := cookiejar.New(nil)
	zmzURL := "http://www.zimuzu.tv/User/Login/ajaxLogin"
	zmzClient = http.Client{
		Jar: gCookieJar,
	}
	//post with my public account, you can use it also
	zmzClient.PostForm(zmzURL, url.Values{"account": {"evol4snow"}, "password": {"104545"}, "remember": {"0"}})
}
<commit_msg>echo each one<commit_after>// get show and movie source download links
package main

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"regexp"
	"strings"
	"sync"
)

type Media struct {
	Name string
	Size string
	Link string
}

//zmz.tv needs to login before downloading
var zmzClient http.Client

func getMovieFromLBL(movie string, results chan string, wg *sync.WaitGroup) {
	defer wg.Done()
	var id string
	resp, _ := http.Get("http://www.lbldy.com/search/" + movie)
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	re, _ := regexp.Compile("
")
	//find first match case
	firstId := re.FindSubmatch(body)
	if len(firstId) == 0 {
		results <- fmt.Sprintf("No results for *%s* from LBL", movie)
		return
	} else {
		id = string(firstId[1])
		resp, _ = http.Get("http://www.lbldy.com/movie/" + id + ".html")
		defer resp.Body.Close()
		re, _ = regexp.Compile(`<p><a href="(.*?)"( target="_blank">|>)(.*?)</a></p>`)
		body, _ := ioutil.ReadAll(resp.Body)
		//go does not support (?!) regex
		body = []byte(strings.Replace(string(body), `<a href="/xunlei/"`, "", -1))
		downloads := re.FindAllSubmatch(body, -1)
		if len(downloads) == 0 {
			results <- fmt.Sprintf("No results for *%s* from LBL", movie)
			return
		} else {
			ret := "Results from LBL:\n\n"
			for i := range downloads {
				ret += fmt.Sprintf("*%s*\n```%s```\n\n", string(downloads[i][3]), string(downloads[i][1]))
				//when results are too large, we split it.
				if i%5 == 0 && i > 0 {
					results <- ret
					ret = fmt.Sprintf("*LBL Part %d*\n\n", i/5+1)
				}
			}
			results <- ret
		}
	}
}

func getMovieFromZMZ(movie string, results chan string, wg *sync.WaitGroup) {
	defer wg.Done()
	loginZMZ()
	if ms := getZMZResource(movie, "0", "0"); ms == nil {
		results <- fmt.Sprintf("No results for *%s* from ZMZ", movie)
		return
	} else {
		results <- "Results from ZMZ:\n\n"
		for _, m := range ms {
			name := m.Name
			size := m.Size
			link := m.Link
			results <- fmt.Sprintf("*%s*(%s)\n```%s```\n\n", name, size, link)
		}
	}
	return
}

func getShowFromZMZ(show, s, e string, results chan string) (found bool) {
	loginZMZ()
	ms := getZMZResource(show, s, e)
	if ms == nil {
		results <- fmt.Sprintf("No results found for *S%sE%s*", s, e)
		return false
	}
	for _, m := range ms {
		name := m.Name
		size := m.Size
		link := m.Link
		results <- fmt.Sprintf("*ZMZ %s*(%s)\n```%s```\n\n", name, size, link)
	}
	return true
}

//get show and get movie from zmz both uses this function
func getZMZResource(name, season, episode string) []Media {
	id := getZMZResourceId(name)
	if id == "" {
		return nil
	}
	resourceURL := "http://www.zimuzu.tv/resource/list/" + id
	resp, _ := zmzClient.Get(resourceURL)
	defer resp.Body.Close()
	//1.name 2.size 3.link
	var ms []Media
	doc, err := goquery.NewDocumentFromReader(io.Reader(resp.Body))
	if err != nil {
		return nil
	}
	doc.Find("li.clearfix").Each(func(i int, selection *goquery.Selection) {
		s, _ := selection.Attr("season")
		e, _ := selection.Attr("episode")
		if e != episode || s != season {
			return
		}
		name := selection.Find(".fl a").Text()
		link, _ := selection.Find(".fr a").Attr("href")
		var size string
		if strings.HasPrefix(link, "ed2k") || strings.HasPrefix(link, "magnet") {
			size = selection.Find(".fl font.f3").Text()
			if size == "" || size == "0" {
				size = "unknown_size"
			}
			m := Media{
				Name: name,
				Link: link,
				Size: size,
			}
			ms = append(ms, m)
		}
	})
	return ms
}

func getZMZResourceId(name string) (id string) {
	queryURL := fmt.Sprintf("http://www.zimuzu.tv/search?keyword=%s&type=resource", name)
	re, _ := regexp.Compile(`<div class="t f14"><a href="/resource/(.*?)"><strong class="list_title">`)
	resp, _ := zmzClient.Get(queryURL)
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	//find first match case
	firstId := re.FindSubmatch(body)
	if len(firstId) == 0 {
		return
	} else {
		log.Println(id)
		id = string(firstId[1])
		return
	}
}

//login zmz first because zmz don't allow login at different browsers, but I have two robots...
func loginZMZ() {
	gCookieJar, _ := cookiejar.New(nil)
	zmzURL := "http://www.zimuzu.tv/User/Login/ajaxLogin"
	zmzClient = http.Client{
		Jar: gCookieJar,
	}
	//post with my public account, you can use it also
	zmzClient.PostForm(zmzURL, url.Values{"account": {"evol4snow"}, "password": {"104545"}, "remember": {"0"}})
}
<|endoftext|>