Committed
This commit is contained in:
parent
0a0abf5698
commit
fdc6c763da
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# binary
|
||||
hostsplitter
|
25
config.go
25
config.go
@ -2,8 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
@ -13,6 +13,7 @@ var (
|
||||
config map[string]interface{}
|
||||
)
|
||||
|
||||
// LoadConfig loads the config
|
||||
func LoadConfig() {
|
||||
stagedRoutedHostnames := make(map[string]int)
|
||||
stagedSites := []Site{}
|
||||
@ -21,11 +22,11 @@ func LoadConfig() {
|
||||
var files []os.FileInfo
|
||||
|
||||
if err = os.MkdirAll(*sitesLoc, 0600); err != nil {
|
||||
log.Print(err)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if files, err = ioutil.ReadDir(*sitesLoc); err != nil {
|
||||
log.Print(err)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -53,11 +54,11 @@ func LoadConfig() {
|
||||
stagedSites = append(stagedSites, Site{})
|
||||
|
||||
if dat, err = ioutil.ReadFile(*sitesLoc + "/" + f.Name()); err != nil {
|
||||
log.Print(err)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(dat, &siteConf); err != nil {
|
||||
log.Print(err)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
switch siteConf["hostnames"].(type) {
|
||||
@ -65,14 +66,14 @@ func LoadConfig() {
|
||||
for _, hostname := range siteConf["hostnames"].([]interface{}) {
|
||||
switch hostname.(type) {
|
||||
case string:
|
||||
log.Print("Adding hostname -> ", hostname)
|
||||
fmt.Println("Adding hostname -> ", hostname)
|
||||
stagedRoutedHostnames[hostname.(string)] = siteIndex
|
||||
default:
|
||||
log.Print("Expected string but got ", reflect.TypeOf(hostname), " while parsing hostname in ", f.Name())
|
||||
fmt.Println("Expected string but got ", reflect.TypeOf(hostname), " while parsing hostname in ", f.Name())
|
||||
}
|
||||
}
|
||||
default:
|
||||
log.Print("Expected array but got ", reflect.TypeOf(siteConf["hostnames"]), " while parsing hosts in ", f.Name())
|
||||
fmt.Println("Expected array but got ", reflect.TypeOf(siteConf["hostnames"]), " while parsing hosts in ", f.Name())
|
||||
}
|
||||
|
||||
switch siteConf["backends"].(type) {
|
||||
@ -80,21 +81,21 @@ func LoadConfig() {
|
||||
for _, backend := range siteConf["backends"].([]interface{}) {
|
||||
switch backend.(type) {
|
||||
case string:
|
||||
log.Print("Adding backend -> ", backend)
|
||||
fmt.Println("Adding backend -> ", backend)
|
||||
stagedSites[siteIndex].Backends = append(stagedSites[siteIndex].Backends, backend.(string))
|
||||
default:
|
||||
log.Print("Expected string but got ", reflect.TypeOf(backend), " while parsing backend in ", f.Name())
|
||||
fmt.Println("Expected string but got ", reflect.TypeOf(backend), " while parsing backend in ", f.Name())
|
||||
}
|
||||
}
|
||||
default:
|
||||
log.Print("Expected array but got ", reflect.TypeOf(siteConf["backends"]), " while parsing backends in ", f.Name())
|
||||
fmt.Println("Expected array but got ", reflect.TypeOf(siteConf["backends"]), " while parsing backends in ", f.Name())
|
||||
}
|
||||
|
||||
switch siteConf["secret"].(type) {
|
||||
case string:
|
||||
stagedSites[siteIndex].Secret = siteConf["secret"].(string)
|
||||
default:
|
||||
log.Print("Expected string but got ", reflect.TypeOf(siteConf["secret"]), " while parsing secret in ", f.Name())
|
||||
fmt.Println("Expected string but got ", reflect.TypeOf(siteConf["secret"]), " while parsing secret in ", f.Name())
|
||||
}
|
||||
|
||||
routedHostnames = stagedRoutedHostnames
|
||||
|
@ -2,10 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/VividCortex/godaemon"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
@ -13,7 +14,9 @@ import (
|
||||
|
||||
var (
|
||||
routedHostnames map[string]int
|
||||
// Sites are the enabled sites
|
||||
Sites []Site
|
||||
// HTTPClient is the http client
|
||||
HTTPClient http.Client
|
||||
)
|
||||
|
||||
@ -29,20 +32,20 @@ func main() {
|
||||
|
||||
kingpin.Parse()
|
||||
|
||||
log.Print("Starting hostsplitter")
|
||||
fmt.Println("Starting hostsplitter")
|
||||
|
||||
if *logFileLoc != "stdout" {
|
||||
logFile, err := os.OpenFile(*logFileLoc, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0640)
|
||||
defer logFile.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("error opening file: %v", err)
|
||||
fmt.Println("error opening file: %v", err)
|
||||
}
|
||||
log.Print("Using ", *logFileLoc, " for logging")
|
||||
log.SetOutput(logFile)
|
||||
fmt.Println("Using ", *logFileLoc, " for logging")
|
||||
//log.SetOutput(logFile)
|
||||
}
|
||||
|
||||
if *daemonize {
|
||||
log.Print("Daemonizing... Bye Bye")
|
||||
fmt.Println("Daemonizing... Bye Bye")
|
||||
godaemon.MakeDaemon(&godaemon.DaemonAttr{})
|
||||
}
|
||||
|
||||
@ -50,22 +53,78 @@ func main() {
|
||||
|
||||
go SignalHandler()
|
||||
|
||||
log.Fatal(http.ListenAndServe(*bindAddr, &httputil.ReverseProxy{
|
||||
fmt.Println(http.ListenAndServe(*bindAddr, &httputil.ReverseProxy{
|
||||
Director: func(r *http.Request) {
|
||||
HTTPLogger(r)
|
||||
if i, ok := routedHostnames[string(r.Host)]; ok {
|
||||
r.Header.Set("X-Hostsplitter-Secret", Sites[i].Secret)
|
||||
r.Header.Set("Host", r.Host)
|
||||
r.URL.Scheme = "http"
|
||||
r.URL.Host = Sites[i].GetBackend()
|
||||
r.RequestURI = ""
|
||||
HTTPLogger(r, http.StatusOK)
|
||||
} else {
|
||||
log.Print("%q is not routed", r.Host)
|
||||
r.URL.Host = ""
|
||||
r.URL.Scheme = ""
|
||||
HTTPLogger(r, http.StatusBadRequest)
|
||||
}
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
func HTTPLogger(r *http.Request) {
|
||||
log.Print(fmt.Sprintf("httplog> %v %v (%v) (conlen %v)", r.Host, r.Method, r.RequestURI, r.RemoteAddr))
|
||||
const apacheFormatPattern = "%s - - [%s] \"%s %s %s\" %d %d \"%s\" \"%s\" %.4f\n"
|
||||
|
||||
// HTTPLogger logs an http request
|
||||
func HTTPLogger(r *http.Request, status int) {
|
||||
if *logFileLoc != "stdout" {
|
||||
logFile, err := os.OpenFile(*logFileLoc, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0640)
|
||||
defer logFile.Close()
|
||||
if err != nil {
|
||||
fmt.Println("error opening file: %v", err)
|
||||
}
|
||||
|
||||
timeFormatted := time.Now().Format("02/Jan/2006 03:04:05")
|
||||
clientIP := r.RemoteAddr
|
||||
if colon := strings.LastIndex(clientIP, ":"); colon != -1 {
|
||||
clientIP = clientIP[:colon]
|
||||
}
|
||||
|
||||
referer := r.Referer()
|
||||
if referer == "" {
|
||||
referer = "-"
|
||||
}
|
||||
|
||||
userAgent := r.UserAgent()
|
||||
if userAgent == "" {
|
||||
userAgent = "-"
|
||||
}
|
||||
|
||||
fmt.Fprint(logFile, fmt.Sprintf(
|
||||
apacheFormatPattern,
|
||||
clientIP,
|
||||
timeFormatted,
|
||||
r.Method,
|
||||
r.RequestURI,
|
||||
r.Proto,
|
||||
status,
|
||||
0,
|
||||
referer,
|
||||
userAgent,
|
||||
0.00,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
record := &ApacheLogRecord{
|
||||
ResponseWriter: rw,
|
||||
ip: clientIP,
|
||||
time: time.Time{},
|
||||
method: r.Method,
|
||||
uri: r.RequestURI,
|
||||
protocol: r.Proto,
|
||||
status: http.StatusOK,
|
||||
referer: referer,
|
||||
userAgent: userAgent,
|
||||
elapsedTime: time.Duration(0),
|
||||
}
|
||||
*/
|
||||
|
@ -1,18 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// SignalHandler handles a config reload on a pkill 10
|
||||
func SignalHandler() {
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.Signal(0xa))
|
||||
for {
|
||||
if <-sigs == syscall.Signal(0xa) {
|
||||
log.Print("Recieved 0xa, reloading config")
|
||||
fmt.Println("Recieved 0xa, reloading config")
|
||||
LoadConfig()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user