Committed

This commit is contained in:
Brian Buller 2016-06-04 16:55:10 -05:00
parent 0a0abf5698
commit fdc6c763da
4 changed files with 90 additions and 27 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# binary
hostsplitter

View File

@ -2,8 +2,8 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"path" "path"
"reflect" "reflect"
@ -13,6 +13,7 @@ var (
config map[string]interface{} config map[string]interface{}
) )
// LoadConfig loads the config
func LoadConfig() { func LoadConfig() {
stagedRoutedHostnames := make(map[string]int) stagedRoutedHostnames := make(map[string]int)
stagedSites := []Site{} stagedSites := []Site{}
@ -21,11 +22,11 @@ func LoadConfig() {
var files []os.FileInfo var files []os.FileInfo
if err = os.MkdirAll(*sitesLoc, 0600); err != nil { if err = os.MkdirAll(*sitesLoc, 0600); err != nil {
log.Print(err) fmt.Println(err)
} }
if files, err = ioutil.ReadDir(*sitesLoc); err != nil { if files, err = ioutil.ReadDir(*sitesLoc); err != nil {
log.Print(err) fmt.Println(err)
return return
} }
@ -53,11 +54,11 @@ func LoadConfig() {
stagedSites = append(stagedSites, Site{}) stagedSites = append(stagedSites, Site{})
if dat, err = ioutil.ReadFile(*sitesLoc + "/" + f.Name()); err != nil { if dat, err = ioutil.ReadFile(*sitesLoc + "/" + f.Name()); err != nil {
log.Print(err) fmt.Println(err)
} }
if err = json.Unmarshal(dat, &siteConf); err != nil { if err = json.Unmarshal(dat, &siteConf); err != nil {
log.Print(err) fmt.Println(err)
} }
switch siteConf["hostnames"].(type) { switch siteConf["hostnames"].(type) {
@ -65,14 +66,14 @@ func LoadConfig() {
for _, hostname := range siteConf["hostnames"].([]interface{}) { for _, hostname := range siteConf["hostnames"].([]interface{}) {
switch hostname.(type) { switch hostname.(type) {
case string: case string:
log.Print("Adding hostname -> ", hostname) fmt.Println("Adding hostname -> ", hostname)
stagedRoutedHostnames[hostname.(string)] = siteIndex stagedRoutedHostnames[hostname.(string)] = siteIndex
default: 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: 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) { switch siteConf["backends"].(type) {
@ -80,21 +81,21 @@ func LoadConfig() {
for _, backend := range siteConf["backends"].([]interface{}) { for _, backend := range siteConf["backends"].([]interface{}) {
switch backend.(type) { switch backend.(type) {
case string: case string:
log.Print("Adding backend -> ", backend) fmt.Println("Adding backend -> ", backend)
stagedSites[siteIndex].Backends = append(stagedSites[siteIndex].Backends, backend.(string)) stagedSites[siteIndex].Backends = append(stagedSites[siteIndex].Backends, backend.(string))
default: 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: 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) { switch siteConf["secret"].(type) {
case string: case string:
stagedSites[siteIndex].Secret = siteConf["secret"].(string) stagedSites[siteIndex].Secret = siteConf["secret"].(string)
default: 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 routedHostnames = stagedRoutedHostnames

View File

@ -2,10 +2,11 @@ package main
import ( import (
"fmt" "fmt"
"log"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"os" "os"
"strings"
"time"
"github.com/VividCortex/godaemon" "github.com/VividCortex/godaemon"
"gopkg.in/alecthomas/kingpin.v2" "gopkg.in/alecthomas/kingpin.v2"
@ -13,7 +14,9 @@ import (
var ( var (
routedHostnames map[string]int routedHostnames map[string]int
// Sites are the enabled sites
Sites []Site Sites []Site
// HTTPClient is the http client
HTTPClient http.Client HTTPClient http.Client
) )
@ -29,20 +32,20 @@ func main() {
kingpin.Parse() kingpin.Parse()
log.Print("Starting hostsplitter") fmt.Println("Starting hostsplitter")
if *logFileLoc != "stdout" { if *logFileLoc != "stdout" {
logFile, err := os.OpenFile(*logFileLoc, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0640) logFile, err := os.OpenFile(*logFileLoc, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0640)
defer logFile.Close() defer logFile.Close()
if err != nil { if err != nil {
log.Fatalf("error opening file: %v", err) fmt.Println("error opening file: %v", err)
} }
log.Print("Using ", *logFileLoc, " for logging") fmt.Println("Using ", *logFileLoc, " for logging")
log.SetOutput(logFile) //log.SetOutput(logFile)
} }
if *daemonize { if *daemonize {
log.Print("Daemonizing... Bye Bye") fmt.Println("Daemonizing... Bye Bye")
godaemon.MakeDaemon(&godaemon.DaemonAttr{}) godaemon.MakeDaemon(&godaemon.DaemonAttr{})
} }
@ -50,22 +53,78 @@ func main() {
go SignalHandler() go SignalHandler()
log.Fatal(http.ListenAndServe(*bindAddr, &httputil.ReverseProxy{ fmt.Println(http.ListenAndServe(*bindAddr, &httputil.ReverseProxy{
Director: func(r *http.Request) { Director: func(r *http.Request) {
HTTPLogger(r)
if i, ok := routedHostnames[string(r.Host)]; ok { if i, ok := routedHostnames[string(r.Host)]; ok {
r.Header.Set("X-Hostsplitter-Secret", Sites[i].Secret) r.Header.Set("X-Hostsplitter-Secret", Sites[i].Secret)
r.Header.Set("Host", r.Host) r.Header.Set("Host", r.Host)
r.URL.Scheme = "http" r.URL.Scheme = "http"
r.URL.Host = Sites[i].GetBackend() r.URL.Host = Sites[i].GetBackend()
r.RequestURI = "" r.RequestURI = ""
HTTPLogger(r, http.StatusOK)
} else { } else {
log.Print("%q is not routed", r.Host) r.URL.Host = ""
r.URL.Scheme = ""
HTTPLogger(r, http.StatusBadRequest)
} }
}, },
})) }))
} }
func HTTPLogger(r *http.Request) { const apacheFormatPattern = "%s - - [%s] \"%s %s %s\" %d %d \"%s\" \"%s\" %.4f\n"
log.Print(fmt.Sprintf("httplog> %v %v (%v) (conlen %v)", r.Host, r.Method, r.RequestURI, r.RemoteAddr))
// 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),
}
*/

View File

@ -1,18 +1,19 @@
package main package main
import ( import (
"log" "fmt"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
) )
// SignalHandler handles a config reload on a pkill 10
func SignalHandler() { func SignalHandler() {
sigs := make(chan os.Signal, 1) sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.Signal(0xa)) signal.Notify(sigs, syscall.Signal(0xa))
for { for {
if <-sigs == syscall.Signal(0xa) { if <-sigs == syscall.Signal(0xa) {
log.Print("Recieved 0xa, reloading config") fmt.Println("Recieved 0xa, reloading config")
LoadConfig() LoadConfig()
} }
} }