<commit_before>package openzwave

//
// Provides a facade for the C++ API that exposes just enough of the underlying C++
// API to be useful to implementing the Ninja Zwave driver
//
// The functions in this module are responsible for marshalling to and from the C functions
// declared in api.hpp and api.cpp.
//

//
// The following #cgo directives assumed that 'go' is a symbolic link that references the gopath that contains the current directory, e.g. ../../../..
//
// All 'go' packages that have this package as a dependency should include such a go link and will then inherit the library built in this package.
//

// #cgo LDFLAGS: -lopenzwave -Lgo/src/github.com/ninjasphere/go-openzwave/openzwave
// #cgo CPPFLAGS: -Iopenzwave/cpp/src/platform -Iopenzwave/cpp/src -Iopenzwave/cpp/src/value_classes
//
// #include "api.h"
import "C"

import (
	"fmt"
	"os"
	"os/signal"
	"time"
	"unsafe"

	"github.com/ninjasphere/go-openzwave/CODE"
	"github.com/ninjasphere/go-openzwave/NT"
	"github.com/ninjasphere/go-openzwave/VT"
)

type api struct {
	options       C.Options // an opaque reference to C++ Options object
	notifications chan Notification
	device        string
	quit          chan bool
	manager       C.Manager
}

//
// The API interface is available to implementors of the EventLoop type.
//
type API interface {
	// notifications are received on this channel
	Notifications() chan Notification

	// free a notification after use.
	FreeNotification(Notification)

	// The EventLoop should return from the function when a signal is received on this channel
	QuitSignal() chan bool
}

// Begin the construction of the API by returning a Configurator
func BuildAPI(configPath string, userPath string, overrides string) Configurator {
	var (
		cConfigPath *C.char = C.CString(configPath)
		cUserPath   *C.char = C.CString(userPath)
		cOverrides  *C.char = C.CString(overrides)
	)
	//defer C.free(unsafe.Pointer(cConfigPath))
	//defer C.free(unsafe.Pointer(cUserPath))
	//defer C.free(unsafe.Pointer(cOverrides))
	return api{
		C.startOptions(cConfigPath, cUserPath, cOverrides),
		make(chan Notification),
		defaultDriverName,
		make(chan bool, 0),
		C.Manager{nil}}
}

// An interface that can be used to configure the API by setting various options,
// and the controller device name. When configuration is finished, call the Run method
// with an EventLoop function. The result of the Run function
// can be passed as a parameter to Os.Exit().
type Configurator interface {
	// Add an integer option.
	AddIntOption(option string, value int) Configurator
	// Add a boolean option.
	AddBoolOption(option string, value bool) Configurator
	// Set the device name used by the driver.
	SetDriver(device string) Configurator
	// Conclude the configuration and start running the supplied event loop. The
	// body of the EventLoop has access to an API reference.
	Run(loop EventLoop) int
}

// Clients of the API should provide an implementation of this type to handle the notifications
// generated by the API.
type EventLoop func(API)

// The type of notifications received via the API's Notifications() channel.
type Notification struct {
	notification *C.Notification
}

// Converts the notification into a string representation.
func (self Notification) String() string {
	return fmt.Sprintf(
		"Notification[\n"+
			"notificationType=%s,\n"+
			"notificationCode=%s,\n"+
			"homeId=0x%08x,\n"+
			"nodeId=0x%02x,\n"+
			"valueType=%s,\n"+
			"valueId=0x%08x]\n",
		NT.ToEnum(int(self.notification.notificationType)),
		CODE.ToEnum(int(self.notification.notificationCode)),
		self.notification.nodeId.homeId,
		self.notification.nodeId.nodeId,
		VT.ToEnum(int(self.notification.valueId.valueType)),
		self.notification.valueId.valueId)
}

// configure the C++ Options object with an integer value
func (self api) AddIntOption(option string, value int) Configurator {
	var cOption *C.char = C.CString(option)
	//defer C.free(unsafe.Pointer(cOption))

	C.addIntOption(self.options, cOption, C.int(value))
	return self
}

// configure the C++ Options object with a boolean value
func (self api) AddBoolOption(option string, value bool) Configurator {
	var cOption *C.char = C.CString(option)

	//defer C.free(unsafe.Pointer(cOption))
	C.addBoolOption(self.options, cOption, C._Bool(value))
	return self
}

// add a driver.
func (self api) SetDriver(device string) Configurator {
	if device != "" {
		self.device = device
	}
	return self
}

//
// Run the supplied event loop
//
// The intent of the complexity is to gracefully handle device insertion and removal events and to
// deal with unexpected (but observed) lockups during the driver removal processing.
//
// The function will only return if a signal is received. It may also call os.Exit(1) in case
// of unexpected lock ups during signal handling, device or driver removal processing.
//
func (self api) Run(loop EventLoop) int {

	// lock the options object, now we are done configuring it

	C.endOptions(self.options)

	// allocate various channels we need

	signals := make(chan os.Signal, 1) // used to receive OS signals
	startQuit := make(chan bool, 2)    // used to indicate we need to quit the event loop
	signalRaised := make(chan bool, 1) // used to indicate to outer loop that it should exit
	exit := make(chan int, 1)          // used to indicate we are ready to exit

	// indicate that we want to wait for these signals

	signal.Notify(signals, os.Interrupt, os.Kill)

	//
	// This goroutine does the following
	//    starts the manager
	//    starts a device monitoroing loop which
	//       waits for the device to be available
	// 	 starts a device removal goroutine which raises a startQuit signal when removal of the device is detected
	//   	 starts the driver
	//	 starts a go routine that that waits until a startQuit is signaled, then initiates the removal of the driver and quit of the event loop
	//	 runs the event loop
	//
	// It does not exit until either an OS Interrupt or Kill signal is received or driver removal or event loop blocks for some reason.
	//
	// If the device is removed, the monitoring go routine will send a signal via the startQuit channel. The intent is to allow the
	// event loop to exit and have the driver removed.
	//
	// The driver removal goroutine waits for the startQuit signal, then attempts to remove the driver. If this completes successfully
	// it propagates a quit signal to the event loop. It also sets up an abort timer which will exit the process if either
	// the driver removal or quit signal propagation blocks for some reason.
	//
	// If an OS signal is received, the main go routine will send signals to the startQuit and to the signalRaised channels.
	// It then waits for another signal, for the outer loop to exit or for a 5 second timeout. When one of these occurs, the
	// process will exit.
	//

	go func() {
		cSelf := unsafe.Pointer(&self) // a reference to self

		self.manager = C.startManager(cSelf) // start the manager
		defer C.stopManager(self.manager, cSelf)

		cDevice := C.CString(self.device) // allocate a C string for device
		defer C.free(unsafe.Pointer(cDevice))

		// a function which returns true if the device exists
		deviceExists := func() bool {
			if _, err := os.Stat(self.device); err == nil {
				return true
			} else {
				if os.IsNotExist(err) {
					return false
				} else {
					return true
				}
			}
		}

		// waits until the state matches the desired state.
		pollUntilDeviceExistsStateEquals := func(comparand bool) {
			for deviceExists() != comparand {
				time.Sleep(time.Second)
			}
		}

		// there is one iteration of this loop for each device insertion/removal cycle
		done := false
		for !done {
			select {
			case done = <-signalRaised: // we received a signal, allow us to quit
				break
			default:
				// one iteration of a device insert/removal cycle

				// wait until device present
				fmt.Printf("waiting until %s is available\n", self.device)
				pollUntilDeviceExistsStateEquals(true)

				go func() {

					// wait until device absent
					pollUntilDeviceExistsStateEquals(false)
					fmt.Printf("device %s removed\n", self.device)

					// start the removal of the driver
					startQuit <- true
				}()

				C.addDriver(self.manager, cDevice)

				go func() {
					// wait until something (OS signal handler or device existence monitor) decides we need to terminate
					<-startQuit

					// we start an abort timer, because if the driver blocks, we need to start the driver process
					abortTimer := time.AfterFunc(5*time.Second, func() {
						fmt.Printf("failed to remove driver - exiting driver process\n")
						os.Exit(1)
					})

					// try to remove the driver
					if C.removeDriver(self.manager, cDevice) {
						self.quit <- true
						abortTimer.Stop() // if we get to here in a timely fashion we can stop the abort timer
					} else {
						// this is unexpected, if we get to here, let the abort timer do its thing
						fmt.Printf("removeDriver call failed - waiting for abort\n")
					}
				}()

				loop(self) // run the event loop
			}
		}

		exit <- 1
	}()

	// Block until a signal is received.

	signal := <-signals
	fmt.Printf("received %v signal - commencing shutdown\n", signal)

	startQuit <- true    // try a graceful shutdown of the event loop
	signalRaised <- true // ensure the device existence loop will exit

	// but, just in case this doesn't happen, set up an abort timer.
	time.AfterFunc(time.Second*5, func() {
		fmt.Printf("timed out while waiting for event loop to quit - aborting now\n")
		exit <- 1
	})

	for {
		select {
		// the device existence loop has exited
		case rc := <-exit:
			return rc
		// the user is impatient - just die now
		case signal := <-signals:
			fmt.Printf("received 2nd %v signal - aborting now\n", signal)
			return 1
		}
	}
}

func (self api) Notifications() chan Notification {
	return self.notifications
}

func (self api) QuitSignal() chan bool {
	return self.quit
}

func (self api) FreeNotification(apiNotification Notification) {
	C.freeNotification(apiNotification.notification)
}

//export onNotificationWrapper
func onNotificationWrapper(notification *C.Notification, context unsafe.Pointer) {
	self := (*api)(context)
	self.notifications <- Notification{notification}
}
<commit_msg>Factor out signal handling into separate goroutine.<commit_after>package openzwave

//
// Provides a facade for the C++ API that exposes just enough of the underlying C++
// API to be useful to implementing the Ninja Zwave driver
//
// The functions in this module are responsible for marshalling to and from the C functions
// declared in api.hpp and api.cpp.
//

//
// The following #cgo directives assumed that 'go' is a symbolic link that references the gopath that contains the current directory, e.g. ../../../..
//
// All 'go' packages that have this package as a dependency should include such a go link and will then inherit the library built in this package.
//

// #cgo LDFLAGS: -lopenzwave -Lgo/src/github.com/ninjasphere/go-openzwave/openzwave
// #cgo CPPFLAGS: -Iopenzwave/cpp/src/platform -Iopenzwave/cpp/src -Iopenzwave/cpp/src/value_classes
//
// #include "api.h"
import "C"

import (
	"fmt"
	"os"
	"os/signal"
	"time"
	"unsafe"

	"github.com/ninjasphere/go-openzwave/CODE"
	"github.com/ninjasphere/go-openzwave/NT"
	"github.com/ninjasphere/go-openzwave/VT"
)

type api struct {
	options       C.Options // an opaque reference to C++ Options object
	notifications chan Notification
	device        string
	quit          chan bool
	manager       C.Manager
}

//
// The API interface is available to implementors of the EventLoop type.
//
type API interface {
	// notifications are received on this channel
	Notifications() chan Notification

	// free a notification after use.
	FreeNotification(Notification)

	// The EventLoop should return from the function when a signal is received on this channel
	QuitSignal() chan bool
}

// Begin the construction of the API by returning a Configurator
func BuildAPI(configPath string, userPath string, overrides string) Configurator {
	var (
		cConfigPath *C.char = C.CString(configPath)
		cUserPath   *C.char = C.CString(userPath)
		cOverrides  *C.char = C.CString(overrides)
	)
	//defer C.free(unsafe.Pointer(cConfigPath))
	//defer C.free(unsafe.Pointer(cUserPath))
	//defer C.free(unsafe.Pointer(cOverrides))
	return api{
		C.startOptions(cConfigPath, cUserPath, cOverrides),
		make(chan Notification),
		defaultDriverName,
		make(chan bool, 0),
		C.Manager{nil}}
}

// An interface that can be used to configure the API by setting various options,
// and the controller device name. When configuration is finished, call the Run method
// with an EventLoop function. The result of the Run function
// can be passed as a parameter to Os.Exit().
type Configurator interface {
	// Add an integer option.
	AddIntOption(option string, value int) Configurator
	// Add a boolean option.
	AddBoolOption(option string, value bool) Configurator
	// Set the device name used by the driver.
	SetDriver(device string) Configurator
	// Conclude the configuration and start running the supplied event loop. The
	// body of the EventLoop has access to an API reference.
	Run(loop EventLoop) int
}

// Clients of the API should provide an implementation of this type to handle the notifications
// generated by the API.
type EventLoop func(API)

// The type of notifications received via the API's Notifications() channel.
type Notification struct {
	notification *C.Notification
}

// Converts the notification into a string representation.
func (self Notification) String() string {
	return fmt.Sprintf(
		"Notification[\n"+
			"notificationType=%s,\n"+
			"notificationCode=%s,\n"+
			"homeId=0x%08x,\n"+
			"nodeId=0x%02x,\n"+
			"valueType=%s,\n"+
			"valueId=0x%08x]\n",
		NT.ToEnum(int(self.notification.notificationType)),
		CODE.ToEnum(int(self.notification.notificationCode)),
		self.notification.nodeId.homeId,
		self.notification.nodeId.nodeId,
		VT.ToEnum(int(self.notification.valueId.valueType)),
		self.notification.valueId.valueId)
}

// configure the C++ Options object with an integer value
func (self api) AddIntOption(option string, value int) Configurator {
	var cOption *C.char = C.CString(option)
	//defer C.free(unsafe.Pointer(cOption))

	C.addIntOption(self.options, cOption, C.int(value))
	return self
}

// configure the C++ Options object with a boolean value
func (self api) AddBoolOption(option string, value bool) Configurator {
	var cOption *C.char = C.CString(option)

	//defer C.free(unsafe.Pointer(cOption))
	C.addBoolOption(self.options, cOption, C._Bool(value))
	return self
}

// add a driver.
func (self api) SetDriver(device string) Configurator {
	if device != "" {
		self.device = device
	}
	return self
}

//
// Run the supplied event loop
//
// The intent of the complexity is to gracefully handle device insertion and removal events and to
// deal with unexpected (but observed) lockups during the driver removal processing.
//
// The function will only return if a signal is received. It may also call os.Exit(1) in case
// of unexpected lock ups during signal handling, device or driver removal processing.
//
func (self api) Run(loop EventLoop) int {

	// lock the options object, now we are done configuring it

	C.endOptions(self.options)

	// allocate various channels we need

	signals := make(chan os.Signal, 1) // used to receive OS signals
	startQuit := make(chan bool, 2)    // used to indicate we need to quit the event loop
	signalRaised := make(chan bool, 1) // used to indicate to outer loop that it should exit
	exit := make(chan int, 1)          // used to indicate we are ready to exit

	// indicate that we want to wait for these signals

	signal.Notify(signals, os.Interrupt, os.Kill)
	go func() {
		// Block until a signal is received.

		signal := <-signals
		// once we receive a signal, exit of the process is inevitable
		fmt.Printf("received %v signal - commencing shutdown\n", signal)

		startQuit <- true    // try a graceful shutdown of the event loop
		signalRaised <- true // ensure the device existence loop will exit

		// but, just in case this doesn't happen, set up an abort timer.
		time.AfterFunc(time.Second*5, func() {
			fmt.Printf("timed out while waiting for event loop to quit - aborting now\n")
			exit <- 1
		})

		// the user is impatient - just die now
		signal = <-signals
		fmt.Printf("received 2nd %v signal - aborting now\n", signal)
		exit <- 2
	}()

	//
	// This goroutine does the following
	//    starts the manager
	//    starts a device monitoroing loop which
	//       waits for the device to be available
	// 	 starts a device removal goroutine which raises a startQuit signal when removal of the device is detected
	//   	 starts the driver
	//	 starts a go routine that that waits until a startQuit is signaled, then initiates the removal of the driver and quit of the event loop
	//	 runs the event loop
	//
	// It does not exit until either an OS Interrupt or Kill signal is received or driver removal or event loop blocks for some reason.
	//
	// If the device is removed, the monitoring go routine will send a signal via the startQuit channel. The intent is to allow the
	// event loop to exit and have the driver removed.
	//
	// The driver removal goroutine waits for the startQuit signal, then attempts to remove the driver. If this completes successfully
	// it propagates a quit signal to the event loop. It also sets up an abort timer which will exit the process if either
	// the driver removal or quit signal propagation blocks for some reason.
	//
	// If an OS signal is received, the main go routine will send signals to the startQuit and to the signalRaised channels.
	// It then waits for another signal, for the outer loop to exit or for a 5 second timeout. When one of these occurs, the
	// process will exit.
	//

	go func() {
		cSelf := unsafe.Pointer(&self) // a reference to self

		self.manager = C.startManager(cSelf) // start the manager
		defer C.stopManager(self.manager, cSelf)

		cDevice := C.CString(self.device) // allocate a C string for device
		defer C.free(unsafe.Pointer(cDevice))

		// a function which returns true if the device exists
		deviceExists := func() bool {
			if _, err := os.Stat(self.device); err == nil {
				return true
			} else {
				if os.IsNotExist(err) {
					return false
				} else {
					return true
				}
			}
		}

		// waits until the state matches the desired state.
		pollUntilDeviceExistsStateEquals := func(comparand bool) {
			for deviceExists() != comparand {
				time.Sleep(time.Second)
			}
		}

		// there is one iteration of this loop for each device insertion/removal cycle
		done := false
		for !done {
			select {
			case done = <-signalRaised: // we received a signal, allow us to quit
				break
			default:
				// one iteration of a device insert/removal cycle

				// wait until device present
				fmt.Printf("waiting until %s is available\n", self.device)
				pollUntilDeviceExistsStateEquals(true)

				go func() {

					// wait until device absent
					pollUntilDeviceExistsStateEquals(false)
					fmt.Printf("device %s removed\n", self.device)

					// start the removal of the driver
					startQuit <- true
				}()

				C.addDriver(self.manager, cDevice)

				go func() {
					// wait until something (OS signal handler or device existence monitor) decides we need to terminate
					<-startQuit

					// we start an abort timer, because if the driver blocks, we need to start the driver process
					abortTimer := time.AfterFunc(5*time.Second, func() {
						fmt.Printf("failed to remove driver - exiting driver process\n")
						exit <- 3
					})

					// try to remove the driver
					if C.removeDriver(self.manager, cDevice) {
						self.quit <- true
						abortTimer.Stop() // if we get to here in a timely fashion we can stop the abort timer
					} else {
						// this is unexpected, if we get to here, let the abort timer do its thing
						fmt.Printf("removeDriver call failed - waiting for abort\n")
					}
				}()

				loop(self) // run the event loop
			}
		}

		exit <- 4
	}()

	return <-exit
}

func (self api) Notifications() chan Notification {
	return self.notifications
}

func (self api) QuitSignal() chan bool {
	return self.quit
}

func (self api) FreeNotification(apiNotification Notification) {
	C.freeNotification(apiNotification.notification)
}

//export onNotificationWrapper
func onNotificationWrapper(notification *C.Notification, context unsafe.Pointer) {
	self := (*api)(context)
	self.notifications <- Notification{notification}
}
<|endoftext|>


<commit_before>package theforeman

import (
	"fmt"
	"net/http"

	"github.com/dghubble/sling"
)

type Config struct {
	// Base URL for TheForeman API
	BaseURL string

	HttpClient *http.Client

	Username string

	Password string
}

type Client struct {
	EnvironmentsService *EnvironmentsService
	HostsService        *HostsService
}

// NewClient returns a new Client
func NewClient(conf *Config, httpClient *http.Client) *Client {
	s := sling.New().Client(conf.HttpClient).Base(conf.BaseURL).SetBasicAuth(conf.Username, conf.Password)
	fmt.Println(conf.Username)
	fmt.Println(conf.Password)
	return &Client{
		EnvironmentsService: NewEnvironmentsService(s),
		HostsService:        NewHostsService(s),
	}
}
<commit_msg>Removing some debugging code.<commit_after>package theforeman

import (
	"fmt"
	"net/http"

	"github.com/dghubble/sling"
)

type Config struct {
	// Base URL for TheForeman API
	BaseURL string

	HttpClient *http.Client

	Username string

	Password string
}

type Client struct {
	EnvironmentsService *EnvironmentsService
	HostsService        *HostsService
}

// NewClient returns a new Client
func NewClient(conf *Config, httpClient *http.Client) *Client {
	s := sling.New().Client(conf.HttpClient).Base(conf.BaseURL).SetBasicAuth(conf.Username, conf.Password)
	return &Client{
		EnvironmentsService: NewEnvironmentsService(s),
		HostsService:        NewHostsService(s),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
)

func tinyUrlAPI(port string) {
	router := gin.Default()
	router.Use(cors.New(cors.Config{
		AllowOrigins: []string{"http://tinyurl.api.adolphlwq.xyz"},
		AllowMethods: []string{"GET", "POST"},
		AllowHeaders: []string{"Content-Type"},
		ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin",
			"Access-Control-Allow-Headers", "Access-Control-Allow-Methods"},
		//AllowCredentials: true,
		AllowOriginFunc: func(origin string) bool {
			logrus.Info("origin is ", origin)
			return true
		},
		MaxAge: 12 * time.Hour,
	}))

	baseAPI := router.Group("/api/v1")
	{
		baseAPI.POST("/shorten", ShortenUrl)
		baseAPI.PUT("/health", HealthCheck)
	}

	//router.GET("/", ParseUrl)
	router.GET("/n/:shortpath", ParseUrl)

	router.Run(port)
}

func ShortenUrl(c *gin.Context) {
	longurl := c.PostForm("longurl")

	if len(longurl) == 0 {
		c.JSON(http.StatusOK, gin.H{"shortpath": "This is OPITIONS preflight request, please try again."})
	}
	// check longurl
	logrus.Info("check if longurl:", longurl, " has existed in db.")
	shortpath, exists := usi.dbs.CheckLongurl(longurl)
	if exists {
		logrus.Info(longurl, " has been existed, return shortpath directly.")
		c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "shortpath": shortpath})
	} else {
		shortpath := usi.Shorten(longurl, 4)
		logrus.Info("generate shortpath: ", shortpath, " for longurl: ", longurl)
		c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "shortpath": shortpath})
	}
}

// ParseUrl parse shorten path and return source url
func ParseUrl(c *gin.Context) {
	shortpath := c.Param("shortpath")
	logrus.Info("parse shortpath: ", shortpath, " for longurl")
	if len(shortpath) == 0 {
		logrus.Warn("shortpath is nil, return default home path.")
		c.Redirect(http.StatusMovedPermanently, "http://tinyurl.adolphlwq.xyz")
	}

	longurl := usi.dbs.QueryUrlRecord(shortpath)
	if len(longurl) == 0 {
		logrus.Warn("longurl of shortpath is nil, return default home page.")
		c.Redirect(http.StatusMovedPermanently, "http://tinyurl.adolphlwq.xyz")
	}

	c.Redirect(http.StatusMovedPermanently, longurl)
}

func HealthCheck(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "health"})
}
<commit_msg>remove origin in cors config<commit_after>package main

import (
	"net/http"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
)

func tinyUrlAPI(port string) {
	router := gin.Default()
	router.Use(cors.New(cors.Config{
		AllowMethods: []string{"GET", "POST"},
		AllowHeaders: []string{"Content-Type"},
		ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin",
			"Access-Control-Allow-Headers", "Access-Control-Allow-Methods"},
		//AllowCredentials: true,
		AllowOriginFunc: func(origin string) bool {
			logrus.Info("origin is ", origin)
			return true
		},
		MaxAge: 12 * time.Hour,
	}))

	baseAPI := router.Group("/api/v1")
	{
		baseAPI.POST("/shorten", ShortenUrl)
		baseAPI.PUT("/health", HealthCheck)
	}

	//router.GET("/", ParseUrl)
	router.GET("/n/:shortpath", ParseUrl)

	router.Run(port)
}

func ShortenUrl(c *gin.Context) {
	longurl := c.PostForm("longurl")

	if len(longurl) == 0 {
		c.JSON(http.StatusOK, gin.H{"shortpath": "This is OPITIONS preflight request, please try again."})
	}
	// check longurl
	logrus.Info("check if longurl:", longurl, " has existed in db.")
	shortpath, exists := usi.dbs.CheckLongurl(longurl)
	if exists {
		logrus.Info(longurl, " has been existed, return shortpath directly.")
		c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "shortpath": shortpath})
	} else {
		shortpath := usi.Shorten(longurl, 4)
		logrus.Info("generate shortpath: ", shortpath, " for longurl: ", longurl)
		c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "shortpath": shortpath})
	}
}

// ParseUrl parse shorten path and return source url
func ParseUrl(c *gin.Context) {
	shortpath := c.Param("shortpath")
	logrus.Info("parse shortpath: ", shortpath, " for longurl")
	if len(shortpath) == 0 {
		logrus.Warn("shortpath is nil, return default home path.")
		c.Redirect(http.StatusMovedPermanently, "http://tinyurl.adolphlwq.xyz")
	}

	longurl := usi.dbs.QueryUrlRecord(shortpath)
	if len(longurl) == 0 {
		logrus.Warn("longurl of shortpath is nil, return default home page.")
		c.Redirect(http.StatusMovedPermanently, "http://tinyurl.adolphlwq.xyz")
	}

	c.Redirect(http.StatusMovedPermanently, longurl)
}

func HealthCheck(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": "health"})
}
<|endoftext|>


<commit_before>package termbox

import "os"
import "os/signal"
import "syscall"

// public API

type (
	InputMode int
	EventType uint8
	Modifier  uint8
	Key       uint16
	Attribute uint16
)

// This type represents a termbox event. 'Mod', 'Key' and 'Ch' fields are valid
// if 'Type' is EventKey. 'W' and 'H' are valid if 'Type' is EventResize.
type Event struct {
	Type   EventType // one of Event* constants
	Mod    Modifier  // one of Mod* constants or 0
	Key    Key       // one of Key* constants, invalid if 'Ch' is not 0
	Ch     rune      // a unicode character
	Width  int       // width of the screen
	Height int       // height of the screen
}

// A cell, single conceptual entity on the screen. The screen is basically a 2d
// array of cells. 'Ch' is a unicode character, 'Fg' and 'Bg' are foreground
// and background attributes respectively.
type Cell struct {
	Ch rune
	Fg Attribute
	Bg Attribute
}

// Key constants, see Event.Key field.
const (
	KeyF1 Key = 0xFFFF - iota
	KeyF2
	KeyF3
	KeyF4
	KeyF5
	KeyF6
	KeyF7
	KeyF8
	KeyF9
	KeyF10
	KeyF11
	KeyF12
	KeyInsert
	KeyDelete
	KeyHome
	KeyEnd
	KeyPgup
	KeyPgdn
	KeyArrowUp
	KeyArrowDown
	KeyArrowLeft
	KeyArrowRight
)

const (
	KeyCtrlTilde      Key = 0x00
	KeyCtrl2          Key = 0x00
	KeyCtrlA          Key = 0x01
	KeyCtrlB          Key = 0x02
	KeyCtrlC          Key = 0x03
	KeyCtrlD          Key = 0x04
	KeyCtrlE          Key = 0x05
	KeyCtrlF          Key = 0x06
	KeyCtrlG          Key = 0x07
	KeyBackspace      Key = 0x08
	KeyCtrlH          Key = 0x08
	KeyTab            Key = 0x09
	KeyCtrlI          Key = 0x09
	KeyCtrlJ          Key = 0x0A
	KeyCtrlK          Key = 0x0B
	KeyCtrlL          Key = 0x0C
	KeyEnter          Key = 0x0D
	KeyCtrlM          Key = 0x0D
	KeyCtrlN          Key = 0x0E
	KeyCtrlO          Key = 0x0F
	KeyCtrlP          Key = 0x10
	KeyCtrlQ          Key = 0x11
	KeyCtrlR          Key = 0x12
	KeyCtrlS          Key = 0x13
	KeyCtrlT          Key = 0x14
	KeyCtrlU          Key = 0x15
	KeyCtrlV          Key = 0x16
	KeyCtrlW          Key = 0x17
	KeyCtrlX          Key = 0x18
	KeyCtrlY          Key = 0x19
	KeyCtrlZ          Key = 0x1A
	KeyEsc            Key = 0x1B
	KeyCtrlLsqBracket Key = 0x1B
	KeyCtrl3          Key = 0x1B
	KeyCtrl4          Key = 0x1C
	KeyCtrlBackslash  Key = 0x1C
	KeyCtrl5          Key = 0x1D
	KeyCtrlRsqBracket Key = 0x1D
	KeyCtrl6          Key = 0x1E
	KeyCtrl7          Key = 0x1F
	KeyCtrlSlash      Key = 0x1F
	KeyCtrlUnderscore Key = 0x1F
	KeySpace          Key = 0x20
	KeyBackspace2     Key = 0x7F
	KeyCtrl8          Key = 0x7F
)

// Alt modifier constant, see Event.Mod field and SetInputMode function.
const (
	ModAlt Modifier = 0x01
)

// Cell attributes, it is possible to use multiple attributes by combining them
// using bitwise OR ('|'). Although, colors cannot be combined. But you can
// combine attributes and a single color.
const (
	ColorBlack Attribute = iota
	ColorRed
	ColorGreen
	ColorYellow
	ColorBlue
	ColorMagenta
	ColorCyan
	ColorWhite
	ColorDefault
)

const (
	AttrBold      Attribute = 0x10
	AttrUnderline Attribute = 0x20
)

// Input mode. See SelectInputMode function.
const (
	InputCurrent InputMode = iota
	InputEsc
	InputAlt
)

// Event type. See Event.Type field.
const (
	EventKey EventType = iota
	EventResize
)

// Initializes termbox library. This function should be called before any other functions.
// After successful initialization, the library must be finalized using 'Shutdown' function.
//
// Example usage:
//      err := termbox.Init()
//      if err != nil {
//              panic(err.String())
//      }
//      defer termbox.Shutdown()
func Init() error {
	// TODO: try os.Stdin and os.Stdout directly
	var err error

	// os.Create is confusing here, but it's just a shortcut for 'open'
	out, err = os.Create("/dev/tty")
	if err != nil {
		return err
	}
	in, err = os.Open("/dev/tty")
	if err != nil {
		return err
	}

	err = setup_term()
	if err != nil {
		return err
	}

	// we set two signal handlers, because input/output are not really
	// connected, but they both need to be aware of window size changes
	signal.Notify(sigwinch_input, syscall.SIGWINCH)
	signal.Notify(sigwinch_draw, syscall.SIGWINCH)

	err = tcgetattr(out.Fd(), &orig_tios)
	if err != nil {
		return err
	}

	tios := orig_tios
	tios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK |
		syscall.ISTRIP | syscall.INLCR | syscall.IGNCR |
		syscall.ICRNL | syscall.IXON
	tios.Oflag &^= syscall.OPOST
	tios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON |
		syscall.ISIG | syscall.IEXTEN
	tios.Cflag &^= syscall.CSIZE | syscall.PARENB
	tios.Cflag |= syscall.CS8
	tios.Cc[syscall.VMIN] = 1
	tios.Cc[syscall.VTIME] = 0

	err = tcsetattr(out.Fd(), &tios)
	if err != nil {
		return err
	}

	out.WriteString(funcs[t_enter_ca])
	out.WriteString(funcs[t_enter_keypad])
	out.WriteString(funcs[t_hide_cursor])
	out.WriteString(funcs[t_clear_screen])

	termw, termh = get_term_size(out.Fd())
	back_buffer.init(termw, termh)
	front_buffer.init(termw, termh)
	back_buffer.clear()
	front_buffer.clear()

	go func() {
		buf := make([]byte, 128)
		for {
			n, _ := in.Read(buf)
			input_comm <- buf[:n]
			buf = (<-input_comm)[:128]
		}
	}()

	return nil
}

// Finalizes termbox library, should be called after successful initialization
// when termbox's functionality isn't required anymore.
func Shutdown() {
	out.WriteString(funcs[t_show_cursor])
	out.WriteString(funcs[t_sgr0])
	out.WriteString(funcs[t_clear_screen])
	out.WriteString(funcs[t_exit_ca])
	out.WriteString(funcs[t_exit_keypad])
	tcsetattr(out.Fd(), &orig_tios)

	out.Close()
	in.Close()
}

// Synchronizes the internal back buffer with the terminal.
func Present() {
	// invalidate cursor position
	lastx = coord_invalid
	lasty = coord_invalid

	select {
	case <-sigwinch_draw:
		update_size()
	default:
	}

	for y := 0; y < front_buffer.height; y++ {
		line_offset := y * front_buffer.width
		for x := 0; x < front_buffer.width; x++ {
			cell_offset := line_offset + x
			back := &back_buffer.cells[cell_offset]
			front := &front_buffer.cells[cell_offset]
			if *back == *front {
				continue
			}
			send_attr(back.Fg, back.Bg)
			send_char(x, y, back.Ch)
			*front = *back
		}
	}
	if !is_cursor_hidden(cursor_x, cursor_y) {
		write_cursor(cursor_x, cursor_y)
	}
	flush()
}

// Sets the position of the cursor. See also HideCursor().
func SetCursor(x, y int) {
	if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) {
		outbuf.WriteString(funcs[t_show_cursor])
	}

	if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) {
		outbuf.WriteString(funcs[t_hide_cursor])
	}

	cursor_x, cursor_y = x, y
	if !is_cursor_hidden(cursor_x, cursor_y) {
		write_cursor(cursor_x, cursor_y)
	}
}

// The shortcut for SetCursor(-1, -1).
func HideCursor() {
	SetCursor(cursor_hidden, cursor_hidden)
}

// Puts the 'cell' into the internal back buffer at the specified position.
func PutCell(x, y int, cell *Cell) {
	if x < 0 || x >= back_buffer.width {
		return
	}
	if y < 0 || y >= back_buffer.height {
		return
	}

	back_buffer.cells[y*back_buffer.width+x] = *cell
}

// Changes cell's parameters in the internal back buffer at the specified
// position.
func ChangeCell(x, y int, ch rune, fg, bg Attribute) {
	var c = Cell{ch, fg, bg}
	PutCell(x, y, &c)
}

// 'Blit' function copies the 'cells' buffer to the internal back buffer at the
// position specified by 'x' and 'y'. Blit doesn't perform any kind of cuts and
// if contents of the cells buffer cannot be placed without crossing back
// buffer's boundaries, the operation is discarded. Parameter 'w' must be > 0,
// otherwise it will cause "division by zero" panic.
//
// The width and the height of the 'cells' buffer are calculated that way:
//      w := w
//      h := len(cells) / w
func Blit(x, y, w int, cells []Cell) {
	h := len(cells) / w
	if x+w > back_buffer.width || x < 0 {
		return
	}
	if y+h > back_buffer.height || y < 0 {
		return
	}

	dsti := y * back_buffer.width + x
	srci := 0

	src := cells
	dst := back_buffer.cells

	for i := 0; i < h; i++ {
		copy(dst[dsti:dsti+w], src[srci:srci+w])
		dsti += back_buffer.width
		srci += w
	}
}

// Wait for an event and return it. This is a blocking function call.
func PollEvent() Event {
	var event Event

	// try to extract event from input buffer, return on success
	event.Type = EventKey
	if extract_event(&event) {
		return event
	}

	for {
		select {
		case data := <-input_comm:
			inbuf = append(inbuf, data...)
			input_comm <- data
			if extract_event(&event) {
				return event
			}
		case <-sigwinch_input:
			event.Type = EventResize
			event.Width, event.Height = get_term_size(out.Fd())
			return event
		}
	}
	panic("unreachable")
}

// Returns the size of the internal back buffer (which is the same as
// terminal's window size in characters).
func Size() (int, int) {
	return termw, termh
}

// Clears the internal back buffer.
func Clear() {
	select {
	case <-sigwinch_draw:
		update_size()
	default:
	}
	back_buffer.clear()
}

// Sets termbox input mode. Termbox has two input modes:
//
// 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC means KeyEsc.
//
// 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC enables ModAlt modifier for the next keyboard event.
//
// If 'mode' is InputCurrent, returns the current input mode. See also Input*
// constants.
func SetInputMode(mode InputMode) InputMode {
	if mode != InputCurrent {
		input_mode = mode
	}
	return input_mode
}

// Set attributes which are used for clearing the internal back buffer.
func SetClearAttributes(fg, bg Attribute) {
	foreground, background = fg, bg
}
<commit_msg>Remove the 'Blit' function, provide direct access to the back buffer instead.<commit_after>package termbox

import "os"
import "os/signal"
import "syscall"

// public API

type (
	InputMode int
	EventType uint8
	Modifier  uint8
	Key       uint16
	Attribute uint16
)

// This type represents a termbox event. 'Mod', 'Key' and 'Ch' fields are valid
// if 'Type' is EventKey. 'W' and 'H' are valid if 'Type' is EventResize.
type Event struct {
	Type   EventType // one of Event* constants
	Mod    Modifier  // one of Mod* constants or 0
	Key    Key       // one of Key* constants, invalid if 'Ch' is not 0
	Ch     rune      // a unicode character
	Width  int       // width of the screen
	Height int       // height of the screen
}

// A cell, single conceptual entity on the screen. The screen is basically a 2d
// array of cells. 'Ch' is a unicode character, 'Fg' and 'Bg' are foreground
// and background attributes respectively.
type Cell struct {
	Ch rune
	Fg Attribute
	Bg Attribute
}

// Key constants, see Event.Key field.
const (
	KeyF1 Key = 0xFFFF - iota
	KeyF2
	KeyF3
	KeyF4
	KeyF5
	KeyF6
	KeyF7
	KeyF8
	KeyF9
	KeyF10
	KeyF11
	KeyF12
	KeyInsert
	KeyDelete
	KeyHome
	KeyEnd
	KeyPgup
	KeyPgdn
	KeyArrowUp
	KeyArrowDown
	KeyArrowLeft
	KeyArrowRight
)

const (
	KeyCtrlTilde      Key = 0x00
	KeyCtrl2          Key = 0x00
	KeyCtrlA          Key = 0x01
	KeyCtrlB          Key = 0x02
	KeyCtrlC          Key = 0x03
	KeyCtrlD          Key = 0x04
	KeyCtrlE          Key = 0x05
	KeyCtrlF          Key = 0x06
	KeyCtrlG          Key = 0x07
	KeyBackspace      Key = 0x08
	KeyCtrlH          Key = 0x08
	KeyTab            Key = 0x09
	KeyCtrlI          Key = 0x09
	KeyCtrlJ          Key = 0x0A
	KeyCtrlK          Key = 0x0B
	KeyCtrlL          Key = 0x0C
	KeyEnter          Key = 0x0D
	KeyCtrlM          Key = 0x0D
	KeyCtrlN          Key = 0x0E
	KeyCtrlO          Key = 0x0F
	KeyCtrlP          Key = 0x10
	KeyCtrlQ          Key = 0x11
	KeyCtrlR          Key = 0x12
	KeyCtrlS          Key = 0x13
	KeyCtrlT          Key = 0x14
	KeyCtrlU          Key = 0x15
	KeyCtrlV          Key = 0x16
	KeyCtrlW          Key = 0x17
	KeyCtrlX          Key = 0x18
	KeyCtrlY          Key = 0x19
	KeyCtrlZ          Key = 0x1A
	KeyEsc            Key = 0x1B
	KeyCtrlLsqBracket Key = 0x1B
	KeyCtrl3          Key = 0x1B
	KeyCtrl4          Key = 0x1C
	KeyCtrlBackslash  Key = 0x1C
	KeyCtrl5          Key = 0x1D
	KeyCtrlRsqBracket Key = 0x1D
	KeyCtrl6          Key = 0x1E
	KeyCtrl7          Key = 0x1F
	KeyCtrlSlash      Key = 0x1F
	KeyCtrlUnderscore Key = 0x1F
	KeySpace          Key = 0x20
	KeyBackspace2     Key = 0x7F
	KeyCtrl8          Key = 0x7F
)

// Alt modifier constant, see Event.Mod field and SetInputMode function.
const (
	ModAlt Modifier = 0x01
)

// Cell attributes, it is possible to use multiple attributes by combining them
// using bitwise OR ('|'). Although, colors cannot be combined. But you can
// combine attributes and a single color.
const (
	ColorBlack Attribute = iota
	ColorRed
	ColorGreen
	ColorYellow
	ColorBlue
	ColorMagenta
	ColorCyan
	ColorWhite
	ColorDefault
)

const (
	AttrBold      Attribute = 0x10
	AttrUnderline Attribute = 0x20
)

// Input mode. See SetInputMode function.
const (
	InputCurrent InputMode = iota
	InputEsc
	InputAlt
)

// Event type. See Event.Type field.
const (
	EventKey EventType = iota
	EventResize
)

// Initializes termbox library. This function should be called before any other functions.
// After successful initialization, the library must be finalized using 'Shutdown' function.
//
// Example usage:
//      err := termbox.Init()
//      if err != nil {
//              panic(err.String())
//      }
//      defer termbox.Shutdown()
func Init() error {
	// TODO: try os.Stdin and os.Stdout directly
	var err error

	// os.Create is confusing here, but it's just a shortcut for 'open'
	out, err = os.Create("/dev/tty")
	if err != nil {
		return err
	}
	in, err = os.Open("/dev/tty")
	if err != nil {
		return err
	}

	err = setup_term()
	if err != nil {
		return err
	}

	// we set two signal handlers, because input/output are not really
	// connected, but they both need to be aware of window size changes
	signal.Notify(sigwinch_input, syscall.SIGWINCH)
	signal.Notify(sigwinch_draw, syscall.SIGWINCH)

	err = tcgetattr(out.Fd(), &orig_tios)
	if err != nil {
		return err
	}

	tios := orig_tios
	tios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK |
		syscall.ISTRIP | syscall.INLCR | syscall.IGNCR |
		syscall.ICRNL | syscall.IXON
	tios.Oflag &^= syscall.OPOST
	tios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON |
		syscall.ISIG | syscall.IEXTEN
	tios.Cflag &^= syscall.CSIZE | syscall.PARENB
	tios.Cflag |= syscall.CS8
	tios.Cc[syscall.VMIN] = 1
	tios.Cc[syscall.VTIME] = 0

	err = tcsetattr(out.Fd(), &tios)
	if err != nil {
		return err
	}

	out.WriteString(funcs[t_enter_ca])
	out.WriteString(funcs[t_enter_keypad])
	out.WriteString(funcs[t_hide_cursor])
	out.WriteString(funcs[t_clear_screen])

	termw, termh = get_term_size(out.Fd())
	back_buffer.init(termw, termh)
	front_buffer.init(termw, termh)
	back_buffer.clear()
	front_buffer.clear()

	go func() {
		buf := make([]byte, 128)
		for {
			n, _ := in.Read(buf)
			input_comm <- buf[:n]
			buf = (<-input_comm)[:128]
		}
	}()

	return nil
}

// Finalizes termbox library, should be called after successful initialization
// when termbox's functionality isn't required anymore.
func Shutdown() {
	out.WriteString(funcs[t_show_cursor])
	out.WriteString(funcs[t_sgr0])
	out.WriteString(funcs[t_clear_screen])
	out.WriteString(funcs[t_exit_ca])
	out.WriteString(funcs[t_exit_keypad])
	tcsetattr(out.Fd(), &orig_tios)

	out.Close()
	in.Close()
}

// Synchronizes the internal back buffer with the terminal.
func Present() {
	// invalidate cursor position
	lastx = coord_invalid
	lasty = coord_invalid

	select {
	case <-sigwinch_draw:
		update_size()
	default:
	}

	for y := 0; y < front_buffer.height; y++ {
		line_offset := y * front_buffer.width
		for x := 0; x < front_buffer.width; x++ {
			cell_offset := line_offset + x
			back := &back_buffer.cells[cell_offset]
			front := &front_buffer.cells[cell_offset]
			if *back == *front {
				continue
			}
			send_attr(back.Fg, back.Bg)
			send_char(x, y, back.Ch)
			*front = *back
		}
	}
	if !is_cursor_hidden(cursor_x, cursor_y) {
		write_cursor(cursor_x, cursor_y)
	}
	flush()
}

// Sets the position of the cursor. See also HideCursor().
func SetCursor(x, y int) {
	if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) {
		outbuf.WriteString(funcs[t_show_cursor])
	}

	if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) {
		outbuf.WriteString(funcs[t_hide_cursor])
	}

	cursor_x, cursor_y = x, y
	if !is_cursor_hidden(cursor_x, cursor_y) {
		write_cursor(cursor_x, cursor_y)
	}
}

// The shortcut for SetCursor(-1, -1).
func HideCursor() {
	SetCursor(cursor_hidden, cursor_hidden)
}

// Puts the 'cell' into the internal back buffer at the specified position.
func PutCell(x, y int, cell *Cell) {
	if x < 0 || x >= back_buffer.width {
		return
	}
	if y < 0 || y >= back_buffer.height {
		return
	}

	back_buffer.cells[y*back_buffer.width+x] = *cell
}

// Changes cell's parameters in the internal back buffer at the specified
// position.
func ChangeCell(x, y int, ch rune, fg, bg Attribute) {
	var c = Cell{ch, fg, bg}
	PutCell(x, y, &c)
}

// Returns a slice of the termbox back buffer. You can get its dimensions using
// 'Size' function. The slice remains valid as long as no 'Clear' or 'Present'
// function calls were made after call to this function.
//
// The function is provided for performance reasons, normally it is suggested to
// use 'ChangeCell' or 'PutCell'.
func CellBuffer() []Cell {
	return back_buffer.cells
}

// Wait for an event and return it. This is a blocking function call.
func PollEvent() Event {
	var event Event

	// try to extract event from input buffer, return on success
	event.Type = EventKey
	if extract_event(&event) {
		return event
	}

	for {
		select {
		case data := <-input_comm:
			inbuf = append(inbuf, data...)
			input_comm <- data
			if extract_event(&event) {
				return event
			}
		case <-sigwinch_input:
			event.Type = EventResize
			event.Width, event.Height = get_term_size(out.Fd())
			return event
		}
	}
	panic("unreachable")
}

// Returns the size of the internal back buffer (which is the same as
// terminal's window size in characters).
func Size() (int, int) {
	return termw, termh
}

// Clears the internal back buffer.
func Clear() {
	select {
	case <-sigwinch_draw:
		update_size()
	default:
	}
	back_buffer.clear()
}

// Sets termbox input mode. Termbox has two input modes:
//
// 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC means KeyEsc.
//
// 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match
// any known sequence. ESC enables ModAlt modifier for the next keyboard event.
//
// If 'mode' is InputCurrent, returns the current input mode. See also Input*
// constants.
func SetInputMode(mode InputMode) InputMode {
	if mode != InputCurrent {
		input_mode = mode
	}
	return input_mode
}

// Set attributes which are used for clearing the internal back buffer.
func SetClearAttributes(fg, bg Attribute) {
	foreground, background = fg, bg
}
<|endoftext|>


<commit_before>package openzwave

//
// #cgo LDFLAGS: -lopenzwave
// #cgo CPPFLAGS: -Iopenzwave/cpp/src/platform -Iopenzwave/cpp/src -Iopenzwave/cpp/src/value_classes
//
// #include <stdlib.h>
// #include "wrapper.hpp"
import "C"

import "unsafe"

type API struct {
	available bool // true if a zwave device is available.
}

func NewAPI(device string) *API {
	var cDevice *C.char = C.CString(device);
	defer C.free(unsafe.Pointer(cDevice));
	var rc C.int = C.init(cDevice);
	return &API{rc != 0}
}
<commit_msg>fix missing -L directive<commit_after>package openzwave

//
// #cgo LDFLAGS: -lopenzwave -Lopenzwave
// #cgo CPPFLAGS: -Iopenzwave/cpp/src/platform -Iopenzwave/cpp/src -Iopenzwave/cpp/src/value_classes
//
// #include <stdlib.h>
// #include "wrapper.hpp"
import "C"

import "unsafe"

type API struct {
	available bool // true if a zwave device is available.
}

func NewAPI(device string) *API {
	var cDevice *C.char = C.CString(device);
	defer C.free(unsafe.Pointer(cDevice));
	var rc C.int = C.init(cDevice);
	return &API{rc != 0}
}
<|endoftext|>


<commit_before>package main

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

func main() {

	// request:  http://localhost:8080/bar
	// response: Thanks for the GET!
	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Thanks for the %s!", r.Method)
	})

	log.Fatal(http.ListenAndServe(":8080", nil))
}
<commit_msg>json.MarshalIndent<commit_after>package main

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

func main() {

	http.HandleFunc("/request", func(w http.ResponseWriter, r *http.Request) {
		resp, _ := json.MarshalIndent(r, "", "\t")
		fmt.Fprintf(w, "%v", string(resp))
	})

	log.Fatal(http.ListenAndServe(":8080", nil))

	/*
	   	// request:  http://localhost:8080/request
	   	// response:

	   {
	   	"Method": "GET",
	   	"URL": {
	   		"Scheme": "",
	   		"Opaque": "",
	   		"User": null,
	   		"Host": "",
	   		"Path": "/request",
	   		"RawQuery": "",
	   		"Fragment": ""
	   	},
	   	"Proto": "HTTP/1.1",
	   	"ProtoMajor": 1,
	   	"ProtoMinor": 1,
	   	"Header": {
	   		"Accept": [
	   			"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,* /*;q=0.8"
	   		],
	   		"Accept-Encoding": [
	   			"gzip,deflate,sdch"
	   		],
	   		"Accept-Language": [
	   			"de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4"
	   		],
	   		"Cache-Control": [
	   			"max-age=0"
	   		],
	   		"Connection": [
	   			"keep-alive"
	   		],
	   		"Dnt": [
	   			"1"
	   		],
	   		"User-Agent": [
	   			"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36"
	   		]
	   	},
	   	"Body": {
	   		"Closer": {
	   			"Reader": null
	   		}
	   	},
	   	"ContentLength": 0,
	   	"TransferEncoding": null,
	   	"Close": false,
	   	"Host": "localhost:8080",
	   	"Form": null,
	   	"PostForm": null,
	   	"MultipartForm": null,
	   	"Trailer": null,
	   	"RemoteAddr": "[::1]:61199",
	   	"RequestURI": "/request",
	   	"TLS": null
	   }
	*/

}
<|endoftext|>


<commit_before>package app

import (
	"bytes"
	"image"
	"io"
	"io/ioutil"
	"math/rand"
	"mime/multipart"
	"net/http"
	"os"
	"strings"
	"time"

	_ "image/jpeg"
	_ "image/png"

	fb "github.com/huandu/facebook"

	"appengine"
	"appengine/datastore"
	"appengine/urlfetch"
)

var clientID = "526791527487217"
var FbApp = fb.New(clientID, APPSECRET)

var aboutParams = fb.Params{
	"method":       fb.GET,
	"relative_url": "me?fields=name,email,gender,age_range,address,location",
}

var photoParams = fb.Params{
	"method":       fb.GET,
	"relative_url": "me/picture?width=320&height=320&redirect=false",
}

func init() {
	http.HandleFunc("/static/", StaticHandler)
	http.HandleFunc("/", MainHandler)
	http.HandleFunc("/web/", WebHandler)

	fb.Debug = fb.DEBUG_ALL
	FbApp.EnableAppsecretProof = true
	rand.Seed(time.Now().UTC().UnixNano())
}

func WebHandler(w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	code := query.Get("code")

	if code == "" {
		http.Error(w, "Cannot get code from facebook.", 505)
		return
	}

	context := appengine.NewContext(r)
	client := urlfetch.Client(context)
	fb.SetHttpClient(client)

	redirectURL := "http://" + r.Host + r.URL.Path
	accessResp, err := fb.Get("/v2.4/oauth/access_token", fb.Params{
		"code":          code,
		"redirect_uri":  redirectURL,
		"client_id":     clientID,
		"client_secret": APPSECRET,
	})
	check(err, context)

	var accessToken string
	accessResp.DecodeField("access_token", &accessToken)

	paths := strings.Split(r.URL.Path, "/")
	party := paths[len(paths)-1]
	photoID := UploadPhoto(accessToken, party, context)
	redirectUrl := "https://facebook.com/photo.php?fbid=" + photoID + "&makeprofile=1&prof"
	http.Redirect(w, r, redirectUrl, 303)
}

func UploadPhoto(accessToken string, party string, context appengine.Context) string {
	session := FbApp.Session(accessToken)
	session.HttpClient = urlfetch.Client(context)
	err := session.Validate()
	check(err, context)

	results, err := session.BatchApi(aboutParams, photoParams)
	check(err, context)

	aboutBatch, err := results[0].Batch()
	check(err, context)
	photoBatch, err := results[1].Batch()
	check(err, context)

	aboutResp := aboutBatch.Result
	photoResp := photoBatch.Result

	SaveAboutUser(&aboutResp, party, context)

	profilePicture := GetUserPhoto(&photoResp, context)

	imagebytes := addLogo(profilePicture, party, context)
	form, mime := CreateImageForm(&imagebytes, context)

	url := "https://graph.facebook.com/v2.4/me/photos" +
		"?access_token=" + accessToken +
		"&appsecret_proof=" + session.AppsecretProof()

	uploadResquest, _ := http.NewRequest("POST", url, form)
	uploadResquest.Header.Set("Content-Type", mime)
	uploadResp, _ := session.Request(uploadResquest)
	check(err, context)

	var photoID string
	uploadResp.DecodeField("id", &photoID)

	return photoID
}

func StaticHandler(w http.ResponseWriter, r *http.Request) {
	path := "." + r.URL.Path

	if f, err := os.Stat(path); err == nil && !f.IsDir() {
		http.ServeFile(w, r, path)
		return
	}

	http.NotFound(w, r)
}

func MainHandler(w http.ResponseWriter, r *http.Request) {
	switch {

	case r.URL.Path == "/privacy":
		context := appengine.NewContext(r)
		data, err := ioutil.ReadFile("privacy.html")
		check(err, context)
		w.Write(data)

	case r.URL.Path != "/":
		http.NotFound(w, r)

	default:
		handleMain(w, r)
	}

	return
}

func handleMain(w http.ResponseWriter, r *http.Request) {
	context := appengine.NewContext(r)
	data, err := ioutil.ReadFile("index.html")
	check(err, context)
	w.Write(data)
}

type Log struct {
	Name     string
	Gender   string
	Party    string
	Email    string
	AgeRange int
	Location string
}

func SaveAboutUser(aboutResp *fb.Result, party string, context appengine.Context) {
	var log Log
	aboutResp.Decode(&log)

	var ageRange map[string]int
	var location map[string]string
	aboutResp.DecodeField("location", &location)
	aboutResp.DecodeField("age_range", &ageRange)

	log.AgeRange = ageRange["min"]
	log.Location = location["name"]
	log.Party = party

	_, err := datastore.Put(context,
		datastore.NewIncompleteKey(context, "log", nil),
		&log)
	check(err, context)
}

func GetUserPhoto(photoResp *fb.Result, context appengine.Context) *image.Image {
	var dataField fb.Result
	photoResp.DecodeField("data", &dataField)

	var url string
	dataField.DecodeField("url", &url)

	client := urlfetch.Client(context)
	resp, err := client.Get(url)
	data, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	check(err, context)

	reader := bytes.NewReader(data)
	profilePicture, _, err := image.Decode(reader)
	check(err, context)

	return &profilePicture
}

func CreateImageForm(imageBytes *[]byte, context appengine.Context) (*bytes.Buffer, string) {
	var formBuffer bytes.Buffer
	multiWriter := multipart.NewWriter(&formBuffer)

	imageField, err := multiWriter.CreateFormFile("source", "election.png")
	check(err, context)

	imageBuffer := bytes.NewBuffer(*imageBytes)
	_, err = io.Copy(imageField, imageBuffer)
	check(err, context)

	multiWriter.Close()
	return &formBuffer, multiWriter.FormDataContentType()
}
<commit_msg>set no story<commit_after>package app

import (
	"bytes"
	"image"
	"io"
	"io/ioutil"
	"math/rand"
	"mime/multipart"
	"net/http"
	"os"
	"strings"
	"time"

	_ "image/jpeg"
	_ "image/png"

	fb "github.com/huandu/facebook"

	"appengine"
	"appengine/datastore"
	"appengine/urlfetch"
)

var clientID = "526791527487217"
var FbApp = fb.New(clientID, APPSECRET)

var aboutParams = fb.Params{
	"method":       fb.GET,
	"relative_url": "me?fields=name,email,gender,age_range,address,location",
}

var photoParams = fb.Params{
	"method":       fb.GET,
	"relative_url": "me/picture?width=320&height=320&redirect=false",
}

func init() {
	http.HandleFunc("/static/", StaticHandler)
	http.HandleFunc("/", MainHandler)
	http.HandleFunc("/web/", WebHandler)

	fb.Debug = fb.DEBUG_ALL
	FbApp.EnableAppsecretProof = true
	rand.Seed(time.Now().UTC().UnixNano())
}

func WebHandler(w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	code := query.Get("code")

	if code == "" {
		http.Error(w, "Cannot get code from facebook.", 505)
		return
	}

	context := appengine.NewContext(r)
	client := urlfetch.Client(context)
	fb.SetHttpClient(client)

	redirectURL := "http://" + r.Host + r.URL.Path
	accessResp, err := fb.Get("/v2.4/oauth/access_token", fb.Params{
		"code":          code,
		"redirect_uri":  redirectURL,
		"client_id":     clientID,
		"client_secret": APPSECRET,
	})
	check(err, context)

	var accessToken string
	accessResp.DecodeField("access_token", &accessToken)

	paths := strings.Split(r.URL.Path, "/")
	party := paths[len(paths)-1]
	photoID := UploadPhoto(accessToken, party, context)
	redirectUrl := "https://facebook.com/photo.php?fbid=" + photoID + "&makeprofile=1&prof"
	http.Redirect(w, r, redirectUrl, 303)
}

func UploadPhoto(accessToken string, party string, context appengine.Context) string {
	session := FbApp.Session(accessToken)
	session.HttpClient = urlfetch.Client(context)
	err := session.Validate()
	check(err, context)

	results, err := session.BatchApi(aboutParams, photoParams)
	check(err, context)

	aboutBatch, err := results[0].Batch()
	check(err, context)
	photoBatch, err := results[1].Batch()
	check(err, context)

	aboutResp := aboutBatch.Result
	photoResp := photoBatch.Result

	SaveAboutUser(&aboutResp, party, context)

	profilePicture := GetUserPhoto(&photoResp, context)

	imagebytes := addLogo(profilePicture, party, context)
	form, mime := CreateImageForm(&imagebytes, context)

	url := "https://graph.facebook.com/v2.4/me/photos" +
		"?access_token=" + accessToken +
		"&no_story=true" +
		"&appsecret_proof=" + session.AppsecretProof()

	uploadResquest, _ := http.NewRequest("POST", url, form)
	uploadResquest.Header.Set("Content-Type", mime)
	uploadResp, _ := session.Request(uploadResquest)
	check(err, context)

	var photoID string
	uploadResp.DecodeField("id", &photoID)

	return photoID
}

func StaticHandler(w http.ResponseWriter, r *http.Request) {
	path := "." + r.URL.Path

	if f, err := os.Stat(path); err == nil && !f.IsDir() {
		http.ServeFile(w, r, path)
		return
	}

	http.NotFound(w, r)
}

func MainHandler(w http.ResponseWriter, r *http.Request) {
	switch {

	case r.URL.Path == "/privacy":
		context := appengine.NewContext(r)
		data, err := ioutil.ReadFile("privacy.html")
		check(err, context)
		w.Write(data)

	case r.URL.Path != "/":
		http.NotFound(w, r)

	default:
		handleMain(w, r)
	}

	return
}

func handleMain(w http.ResponseWriter, r *http.Request) {
	context := appengine.NewContext(r)
	data, err := ioutil.ReadFile("index.html")
	check(err, context)
	w.Write(data)
}

type Log struct {
	Name     string
	Gender   string
	Party    string
	Email    string
	AgeRange int
	Location string
}

func SaveAboutUser(aboutResp *fb.Result, party string, context appengine.Context) {
	var log Log
	aboutResp.Decode(&log)

	var ageRange map[string]int
	var location map[string]string
	aboutResp.DecodeField("location", &location)
	aboutResp.DecodeField("age_range", &ageRange)

	log.AgeRange = ageRange["min"]
	log.Location = location["name"]
	log.Party = party

	_, err := datastore.Put(context,
		datastore.NewIncompleteKey(context, "log", nil),
		&log)
	check(err, context)
}

func GetUserPhoto(photoResp *fb.Result, context appengine.Context) *image.Image {
	var dataField fb.Result
	photoResp.DecodeField("data", &dataField)

	var url string
	dataField.DecodeField("url", &url)

	client := urlfetch.Client(context)
	resp, err := client.Get(url)
	data, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	check(err, context)

	reader := bytes.NewReader(data)
	profilePicture, _, err := image.Decode(reader)
	check(err, context)

	return &profilePicture
}

func CreateImageForm(imageBytes *[]byte, context appengine.Context) (*bytes.Buffer, string) {
	var formBuffer bytes.Buffer
	multiWriter := multipart.NewWriter(&formBuffer)

	imageField, err := multiWriter.CreateFormFile("source", "election.png")
	check(err, context)

	imageBuffer := bytes.NewBuffer(*imageBytes)
	_, err = io.Copy(imageField, imageBuffer)
	check(err, context)

	multiWriter.Close()
	return &formBuffer, multiWriter.FormDataContentType()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"
)

//App struct describing autoscaling app
type App struct {
	AppID    string `json:"app_id"`
	MaxCPU   int    `json:"max_cpu"`
	MinMem   int    `json:"min_mem"`
	Method   string `json:"method"`
	Interval int    `json:"interval"`
}

//Apps - all monitored apps
type Apps []App

//StartMonitor starts a ticker goroutine
func (a *App) StartMonitor() {
	tickers[a.AppID] = time.NewTicker(time.Second * time.Duration(a.Interval))
	go doMonitoring(a)
}

func doMonitoring(a *App) {
	internal := 0
	for t := range tickers[a.AppID].C {
		fmt.Printf("ticker:\t%s,%s\n", a.AppID, t)
		internal++
		monitor(a)
		fmt.Printf("app.Monitor:%s, internal:%d\n", a.AppID, internal)
	}
}

//StopMonitor stops the ticker associated with the given app
func (a *App) StopMonitor() {
	tickers[a.AppID].Stop()
}

func monitor(a *App) {
	//get all apps in marathon
	fmt.Println("GET /service/marathon/v2/apps")
	//check if a.appid is in marathon apps, wait if not
	fmt.Printf("GET /service/marathon/v2/apps/%s\n", a.AppID)
	fmt.Println("app:instances")
	//get all tasks for appid
	fmt.Println("app:tasks")
	fmt.Printf("\tid, slaveId\n")
	//for each task X on agent Y get performance stats
	fmt.Println("GET /slave/<slaveId>/monitor/statistics.json")
	fmt.Println("<tid>==executorId, executorId:statistics")
	//  get cpu usage
	fmt.Println("statistics:cpus_system_time_secs,cpus_user_time_secs,timestamp")
	//  get mem usage
	fmt.Println("statistics:mem_rss_bytes,mem_limit_bytes")
	//calculate average mem and cpu
	fmt.Println("calculate average mem and cpu")
	//based on criteria + method, generate (scale[up|down] by factor) signal
	fmt.Printf("generate_autoscale_signal(avg_cpu, avg_mem, %s) vs (%d, %d)\n",
		a.Method, a.MaxCPU, a.MinMem)
	//put signal in a channel for sequential operation
	fmt.Println("channel <- signal")
}
<commit_msg>Minor cosmetic changes<commit_after>package main

import (
	"fmt"
	"time"
)

//App struct describing autoscaling app
type App struct {
	AppID    string `json:"app_id"`
	MaxCPU   int    `json:"max_cpu"`
	MinMem   int    `json:"min_mem"`
	Method   string `json:"method"`
	Interval int    `json:"interval"`
}

//Apps - all monitored apps
type Apps []App

//StartMonitor starts a ticker goroutine
func (a *App) StartMonitor() {
	tickers[a.AppID] = time.NewTicker(time.Second * time.Duration(a.Interval))
	go doMonitor(a)
}

func doMonitor(a *App) {
	internal := 0
	for t := range tickers[a.AppID].C {
		fmt.Printf("ticker:\t%s,%s\n", a.AppID, t)
		internal++
		monitor(a)
		fmt.Printf("app.Monitor:%s, internal:%d\n", a.AppID, internal)
	}
}

//StopMonitor stops the ticker associated with the given app
func (a *App) StopMonitor() {
	tickers[a.AppID].Stop()
}

func monitor(a *App) {
	//get all apps in marathon
	fmt.Println("GET /service/marathon/v2/apps")
	//check if a.appid is in marathon apps, wait if not
	fmt.Printf("GET /service/marathon/v2/apps/%s\n", a.AppID)
	fmt.Println("app:instances")
	//get all tasks for appid
	fmt.Println("app:tasks")
	fmt.Printf("\tid, slaveId\n")
	//for each task X on agent Y get performance stats
	fmt.Println("GET /slave/<slaveId>/monitor/statistics.json")
	fmt.Println("<tid>==executorId, executorId:statistics")
	//  get cpu usage
	fmt.Println("statistics:cpus_system_time_secs,cpus_user_time_secs,timestamp")
	//  get mem usage
	fmt.Println("statistics:mem_rss_bytes,mem_limit_bytes")
	//calculate average mem and cpu
	fmt.Println("calculate average mem and cpu")
	//based on criteria + method, generate (scale[up|down] by factor) signal
	fmt.Printf("generate_autoscale_signal(avg_cpu, avg_mem, %s) vs (%d, %d)\n",
		a.Method, a.MaxCPU, a.MinMem)
	//put signal in a channel for sequential operation
	fmt.Println("channel <- signal")
}
<|endoftext|>


<commit_before>// Copyright 2014 The Azul3D 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 (
	"errors"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"strings"
)

var tmpl = template.Must(template.New("").Parse(`
<html>
 <head>
  <meta name="go-import" content="{{.PkgPath}} git {{.Repo}}">
 </head>
</html>
`))

const (
	githubOrg       = "azul3d"
	repoAliasHost   = "azul3d.org"
	repoAliasScheme = "http"
	fileHost        = "azul3d.github.io"
)

// isTip is short-hand for:
//  return version == "v0" || version == "dev"
func isTip(version string) bool {
	return version == "v0" || version == "dev"
}

// Pulls version tag from the URL. It would be at the last part of the URL
// like so:
//  foobar.org/something/something/maybe/here.v0
//  foobar.org/something/something/maybe/here.dev
//  foobar.org/something/something/maybe/here.v1.2
//
// NOT like:
//  foobar.org/something/something/maybe/here.v1.2/info/refs
//
// Always returns "dev" for any .dev or .v0 string.
func versionFromEnd(p string) string {
	if strings.HasSuffix(p, "dev") || strings.HasSuffix(p, "v0") {
		return "dev"
	}
	// he.re.v1.2
	split := strings.Split(path.Base(p), ".v")
	if len(split) > 1 {
		return "v" + split[len(split)-1]
	}
	return ""
}

// Takes a string like:
//  cmd/foo/bar.dev
//  cmd/foo/bar.v1
// and returns:
//  cmd-foo-bar
func gitRepoName(path string) string {
	// Change cmd/foo to cmd-foo
	path = strings.Replace(path, "/", "-", -1)
	// Strip version from end.
	return strings.Split(path, ".")[0]
}

func handleGoTool(w http.ResponseWriter, r *http.Request) bool {
	// Clean the URL.
	u := path.Clean(r.URL.Path)

	// Parse the query.
	query, _ := url.ParseQuery(r.URL.RawQuery)

	// If the client is the 'go get' tool, then we serve them a small page that
	// just contains the go-import meta tag -- that's all.
	if r.Method == "GET" && len(query.Get("go-get")) > 0 {
		repo := *r.URL
		repo.Host = repoAliasHost
		repo.Scheme = repoAliasScheme
		repo.Path = path.Join(u, "repo")
		repo.RawQuery = ""
		tmpl.Execute(w, map[string]interface{}{
			"Repo":    repo.String(),
			"PkgPath": path.Join(repoAliasHost, u),
		})
		return true
	}

	// If the client asks for /info/refs then we fetch them from the git repo
	// and serve them to the client.
	if r.Method == "GET" && strings.HasSuffix(u, "/info/refs") && query.Get("service") == "git-upload-pack" {
		// Strip /repo/info/refs from URL.
		fp := strings.Split(u, "/")
		fp = fp[1 : len(fp)-3]
		fps := path.Join(fp...)
		version := versionFromEnd(fps)
		repoName := gitRepoName(strings.TrimSuffix(fps, version))
		//log.Printf("u=%q version=%q repoName=%q\n", u, version, repoName)

		if len(version) == 0 {
			// The path doesn't have a version in it, we can't serve this
			// request.
			log.Printf("Request without version in URL.\n")
			w.WriteHeader(http.StatusNotFound)
			return true
		}

		// Create URL to target repo's /info/refs
		target := &url.URL{
			Scheme:   "http",
			Host:     "github.com",
			Path:     path.Join(githubOrg, repoName+".git", "/info/refs"),
			RawQuery: "service=git-upload-pack",
		}

		// Fetch info/refs from target repository.
		//log.Printf("fetchRefs from %s\n", target.String())
		refs, err := fetchRefs(target.String())
		if err != nil {
			log.Printf("Failed to fetch remote refs: %v\n", err)
			w.WriteHeader(http.StatusInternalServerError)
			return true
		}

		if !isTip(version) {
			//log.Printf("\n\nHack git refs:\n\n%s\n", string(refs.data))
			// Hack the git refs to the given version.
			err = refs.hack(version)
			if err != nil {
				log.Printf("%v\n", err)
				w.WriteHeader(http.StatusNotFound)
				return true
			}
			//log.Printf("\n\nAFTER HACK:\n\n%s\n", string(refs.data))
		}

		w.Header().Set("Content-Type", "application/x-git-upload-pack-advertisement")
		w.Write(refs.data)
		return true
	}

	// If the client wants to POST to /git-upload-pack we redirect their
	// request to the actual git repo.
	if r.Method == "POST" && strings.HasSuffix(u, "/git-upload-pack") {
		// Strip /repo/git-upload-pack from URL.
		fp := strings.Split(u, "/")
		fp = fp[1 : len(fp)-2]
		fps := path.Join(fp...)
		version := versionFromEnd(fps)
		repoName := gitRepoName(strings.TrimSuffix(fps, version))
		//log.Printf("u=%q version=%q repoName=%q\n", u, version, repoName)

		// Create URL to target repo's /git-upload-pack
		target := &url.URL{
			Scheme: "http",
			Host:   "github.com",
			Path:   path.Join(githubOrg, repoName+".git", "/git-upload-pack"),
		}

		w.Header().Set("Location", target.String())
		w.WriteHeader(http.StatusMovedPermanently)
		return true
	}

	// /info/refs for service=git-receive-pack is just forwarded to the repo
	// directly. This occurs when pushing changes via git.
	if r.Method == "GET" && strings.HasSuffix(u, "/info/refs") && query.Get("service") == "git-receive-pack" {
		// Strip /repo/info/refs from URL.
		fp := strings.Split(u, "/")
		fp = fp[1 : len(fp)-3]
		fps := path.Join(fp...)
		version := versionFromEnd(fps)
		repoName := gitRepoName(strings.TrimSuffix(fps, version))
		//log.Printf("u=%q version=%q repoName=%q\n", u, version, repoName)

		// Create URL to target repo's /info/refs
		target := &url.URL{
			Scheme:   "http",
			Host:     "github.com",
			Path:     path.Join(githubOrg, repoName+".git", "/info/refs"),
			RawQuery: "service=git-receive-pack",
		}

		http.Redirect(w, r, target.String(), http.StatusSeeOther)
		return true
	}

	return false
}

func handler(w http.ResponseWriter, r *http.Request) {
	log.Printf("%v %v\n", r.Method, r.URL)

	// If it's the Go tool (or git HTTP, etc) then we let that function handle
	// it.
	if handleGoTool(w, r) {
		return
	}

	// Just proxy the request to the file host then (it's an actual user -- not
	// the Go tool).
	if r.URL.Scheme == "" {
		r.URL.Scheme = "http"
	}
	r.RequestURI = ""
	delete(r.Header, "Content-Length")

	// Change Host in URL so that the request goes to the file host.
	r.URL.Host = fileHost

	// Force the Host header to be the file host (github.io uses this header).
	r.Host = fileHost

	resp, err := http.DefaultClient.Do(r)
	if err != nil {
		log.Printf("GET error: %v\n", err)
		w.WriteHeader(http.StatusNotFound)
		return
	}
	defer resp.Body.Close()

	// Copy headers over.
	hdr := w.Header()
	for k, v := range resp.Header {
		hdr[k] = v
	}
	w.WriteHeader(resp.StatusCode)

	_, err = io.Copy(w, resp.Body)
	if err != nil {
		log.Printf("Proxy copy error: %v\n", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	return
}

var (
	addr = flag.String("http", ":80", "HTTP address to serve on")
)

func main() {
	flag.Parse()
	http.HandleFunc("/", handler)
	log.Println("Serving on", *addr)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal(err)
	}
}

type gitRefs struct {
	data []byte
}

var (
	ErrRepoNotFound    = errors.New("git repository not found")
	ErrVersionNotFound = errors.New("failed to find version in git refs")
)

func (r *gitRefs) hack(version string) error {
	var mrefi, mrefj, vrefi, vrefj int

	vhead := "refs/heads/" + version
	vtag := "refs/tags/" + version

	data := r.data
	sdata := string(r.data)
	for i, j := 0, 0; i < len(data); i = j {
		size, err := strconv.ParseInt(sdata[i:i+4], 16, 32)
		if err != nil {
			return fmt.Errorf("cannot parse refs line size: %s", string(data[i:i+4]))
		}
		if size == 0 {
			size = 4
		}
		j = i + int(size)
		if j > len(sdata) {
			return fmt.Errorf("incomplete refs data received from repo")
		}
		if sdata[0] == '#' {
			continue
		}

		hashi := i + 4
		hashj := strings.IndexByte(sdata[hashi:j], ' ')
		if hashj < 0 || hashj != 40 {
			continue
		}
		hashj += hashi

		namei := hashj + 1
		namej := strings.IndexAny(sdata[namei:j], "\n\x00")
		if namej < 0 {
			namej = j
		} else {
			namej += namei
		}

		name := sdata[namei:namej]

		if name == "refs/heads/master" {
			mrefi = hashi
			mrefj = hashj
		}

		if strings.HasPrefix(name, "refs/heads/v") || strings.HasPrefix(name, "refs/tags/v") {
			// Annotated tag is peeled off and overrides the same version just parsed.
			name = strings.TrimSuffix(name, "^{}")
			if name == vtag || name == vhead {
				vrefi = hashi
				vrefj = hashj
			}
		}

		//if mrefi > 0 && vrefi > 0 {
		//	break
		//}
	}

	if mrefi == 0 || vrefi == 0 {
		return ErrVersionNotFound
	}

	copy(data[mrefi:mrefj], data[vrefi:vrefj])
	return nil
}

func fetchRefs(refsURL string) (*gitRefs, error) {
	resp, err := http.Get(refsURL)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		if resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusNotFound {
			return nil, ErrRepoNotFound
		} else {
			return nil, fmt.Errorf("error from repo: %v", resp.Status)
		}
	}
	defer resp.Body.Close()

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

	return &gitRefs{
		data: data,
	}, nil
}
<commit_msg>Fix content types.<commit_after>// Copyright 2014 The Azul3D 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 (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"strings"
)

var tmpl = template.Must(template.New("").Parse(`
<html>
 <head>
  <meta name="go-import" content="{{.PkgPath}} git {{.Repo}}">
 </head>
</html>
`))

const (
	githubOrg       = "azul3d"
	repoAliasHost   = "azul3d.org"
	repoAliasScheme = "http"
	fileHost        = "azul3d.github.io"
)

// isTip is short-hand for:
//  return version == "v0" || version == "dev"
func isTip(version string) bool {
	return version == "v0" || version == "dev"
}

// Pulls version tag from the URL. It would be at the last part of the URL
// like so:
//  foobar.org/something/something/maybe/here.v0
//  foobar.org/something/something/maybe/here.dev
//  foobar.org/something/something/maybe/here.v1.2
//
// NOT like:
//  foobar.org/something/something/maybe/here.v1.2/info/refs
//
// Always returns "dev" for any .dev or .v0 string.
func versionFromEnd(p string) string {
	if strings.HasSuffix(p, "dev") || strings.HasSuffix(p, "v0") {
		return "dev"
	}
	// he.re.v1.2
	split := strings.Split(path.Base(p), ".v")
	if len(split) > 1 {
		return "v" + split[len(split)-1]
	}
	return ""
}

// Takes a string like:
//  cmd/foo/bar.dev
//  cmd/foo/bar.v1
// and returns:
//  cmd-foo-bar
func gitRepoName(path string) string {
	// Change cmd/foo to cmd-foo
	path = strings.Replace(path, "/", "-", -1)
	// Strip version from end.
	return strings.Split(path, ".")[0]
}

func handleGoTool(w http.ResponseWriter, r *http.Request) bool {
	// Clean the URL.
	u := path.Clean(r.URL.Path)

	// Parse the query.
	query, _ := url.ParseQuery(r.URL.RawQuery)

	// If the client is the 'go get' tool, then we serve them a small page that
	// just contains the go-import meta tag -- that's all.
	if r.Method == "GET" && len(query.Get("go-get")) > 0 {
		repo := *r.URL
		repo.Host = repoAliasHost
		repo.Scheme = repoAliasScheme
		repo.Path = path.Join(u, "repo")
		repo.RawQuery = ""
		tmpl.Execute(w, map[string]interface{}{
			"Repo":    repo.String(),
			"PkgPath": path.Join(repoAliasHost, u),
		})
		return true
	}

	// If the client asks for /info/refs then we fetch them from the git repo
	// and serve them to the client.
	if r.Method == "GET" && strings.HasSuffix(u, "/info/refs") && query.Get("service") == "git-upload-pack" {
		// Strip /repo/info/refs from URL.
		fp := strings.Split(u, "/")
		fp = fp[1 : len(fp)-3]
		fps := path.Join(fp...)
		version := versionFromEnd(fps)
		repoName := gitRepoName(strings.TrimSuffix(fps, version))
		//log.Printf("u=%q version=%q repoName=%q\n", u, version, repoName)

		if len(version) == 0 {
			// The path doesn't have a version in it, we can't serve this
			// request.
			log.Printf("Request without version in URL.\n")
			w.WriteHeader(http.StatusNotFound)
			return true
		}

		// Create URL to target repo's /info/refs
		target := &url.URL{
			Scheme:   "http",
			Host:     "github.com",
			Path:     path.Join(githubOrg, repoName+".git", "/info/refs"),
			RawQuery: "service=git-upload-pack",
		}

		// Fetch info/refs from target repository.
		//log.Printf("fetchRefs from %s\n", target.String())
		refs, err := fetchRefs(target.String())
		if err != nil {
			log.Printf("Failed to fetch remote refs: %v\n", err)
			w.WriteHeader(http.StatusInternalServerError)
			return true
		}

		if !isTip(version) {
			//log.Printf("\n\nHack git refs:\n\n%s\n", string(refs.data))
			// Hack the git refs to the given version.
			err = refs.hack(version)
			if err != nil {
				log.Printf("%v\n", err)
				w.WriteHeader(http.StatusNotFound)
				return true
			}
			//log.Printf("\n\nAFTER HACK:\n\n%s\n", string(refs.data))
		}

		w.Header().Set("Content-Type", "application/x-git-upload-pack-advertisement")
		w.Write(refs.data)
		return true
	}

	// If the client wants to POST to /git-upload-pack we redirect their
	// request to the actual git repo.
	if r.Method == "POST" && strings.HasSuffix(u, "/git-upload-pack") {
		// Strip /repo/git-upload-pack from URL.
		fp := strings.Split(u, "/")
		fp = fp[1 : len(fp)-2]
		fps := path.Join(fp...)
		version := versionFromEnd(fps)
		repoName := gitRepoName(strings.TrimSuffix(fps, version))
		//log.Printf("u=%q version=%q repoName=%q\n", u, version, repoName)

		// Create URL to target repo's /git-upload-pack
		target := &url.URL{
			Scheme: "http",
			Host:   "github.com",
			Path:   path.Join(githubOrg, repoName+".git", "/git-upload-pack"),
		}

		w.Header().Set("Location", target.String())
		w.WriteHeader(http.StatusMovedPermanently)
		return true
	}

	// /info/refs for service=git-receive-pack is just forwarded to the repo
	// directly. This occurs when pushing changes via git.
	if r.Method == "GET" && strings.HasSuffix(u, "/info/refs") && query.Get("service") == "git-receive-pack" {
		// Strip /repo/info/refs from URL.
		fp := strings.Split(u, "/")
		fp = fp[1 : len(fp)-3]
		fps := path.Join(fp...)
		version := versionFromEnd(fps)
		repoName := gitRepoName(strings.TrimSuffix(fps, version))
		//log.Printf("u=%q version=%q repoName=%q\n", u, version, repoName)

		// Create URL to target repo's /info/refs
		target := &url.URL{
			Scheme:   "http",
			Host:     "github.com",
			Path:     path.Join(githubOrg, repoName+".git", "/info/refs"),
			RawQuery: "service=git-receive-pack",
		}

		http.Redirect(w, r, target.String(), http.StatusSeeOther)
		return true
	}

	return false
}

func handler(w http.ResponseWriter, r *http.Request) {
	log.Printf("%v %v\n", r.Method, r.URL)

	// If it's the Go tool (or git HTTP, etc) then we let that function handle
	// it.
	if handleGoTool(w, r) {
		return
	}

	// Just proxy the request to the file host then (it's an actual user -- not
	// the Go tool).
	if r.URL.Scheme == "" {
		r.URL.Scheme = "http"
	}
	r.RequestURI = ""
	delete(r.Header, "Content-Length")

	// Change Host in URL so that the request goes to the file host.
	r.URL.Host = fileHost

	// Force the Host header to be the file host (github.io uses this header).
	r.Host = fileHost

	resp, err := http.DefaultClient.Do(r)
	if err != nil {
		log.Printf("GET error: %v\n", err)
		w.WriteHeader(http.StatusNotFound)
		return
	}
	defer resp.Body.Close()

	// Copy headers over.
	hdr := w.Header()
	for k, v := range resp.Header {
		hdr[k] = v
	}

	// Peek to detect the content type.
	br := bufio.NewReaderSize(resp.Body, 512)
	ident, err := br.Peek(512)
	if err != nil {
		log.Printf("Proxy peek error: %v\n", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	hdr["Content-Type"] = http.DetectContentType(ident)

	// Write the header / status code.
	w.WriteHeader(resp.StatusCode)

	// Copy the response to the user.
	_, err = io.Copy(w, resp.Body)
	if err != nil {
		log.Printf("Proxy copy error: %v\n", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	return
}

var (
	addr = flag.String("http", ":80", "HTTP address to serve on")
)

func main() {
	flag.Parse()
	http.HandleFunc("/", handler)
	log.Println("Serving on", *addr)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal(err)
	}
}

type gitRefs struct {
	data []byte
}

var (
	ErrRepoNotFound    = errors.New("git repository not found")
	ErrVersionNotFound = errors.New("failed to find version in git refs")
)

func (r *gitRefs) hack(version string) error {
	var mrefi, mrefj, vrefi, vrefj int

	vhead := "refs/heads/" + version
	vtag := "refs/tags/" + version

	data := r.data
	sdata := string(r.data)
	for i, j := 0, 0; i < len(data); i = j {
		size, err := strconv.ParseInt(sdata[i:i+4], 16, 32)
		if err != nil {
			return fmt.Errorf("cannot parse refs line size: %s", string(data[i:i+4]))
		}
		if size == 0 {
			size = 4
		}
		j = i + int(size)
		if j > len(sdata) {
			return fmt.Errorf("incomplete refs data received from repo")
		}
		if sdata[0] == '#' {
			continue
		}

		hashi := i + 4
		hashj := strings.IndexByte(sdata[hashi:j], ' ')
		if hashj < 0 || hashj != 40 {
			continue
		}
		hashj += hashi

		namei := hashj + 1
		namej := strings.IndexAny(sdata[namei:j], "\n\x00")
		if namej < 0 {
			namej = j
		} else {
			namej += namei
		}

		name := sdata[namei:namej]

		if name == "refs/heads/master" {
			mrefi = hashi
			mrefj = hashj
		}

		if strings.HasPrefix(name, "refs/heads/v") || strings.HasPrefix(name, "refs/tags/v") {
			// Annotated tag is peeled off and overrides the same version just parsed.
			name = strings.TrimSuffix(name, "^{}")
			if name == vtag || name == vhead {
				vrefi = hashi
				vrefj = hashj
			}
		}

		//if mrefi > 0 && vrefi > 0 {
		//	break
		//}
	}

	if mrefi == 0 || vrefi == 0 {
		return ErrVersionNotFound
	}

	copy(data[mrefi:mrefj], data[vrefi:vrefj])
	return nil
}

func fetchRefs(refsURL string) (*gitRefs, error) {
	resp, err := http.Get(refsURL)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		if resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusNotFound {
			return nil, ErrRepoNotFound
		} else {
			return nil, fmt.Errorf("error from repo: %v", resp.Status)
		}
	}
	defer resp.Body.Close()

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

	return &gitRefs{
		data: data,
	}, nil
}
<|endoftext|>