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 (
"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

View File

@ -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,8 +14,10 @@ import (
var (
routedHostnames map[string]int
Sites []Site
HTTPClient http.Client
// Sites are the enabled sites
Sites []Site
// HTTPClient is the http client
HTTPClient http.Client
)
var (
@ -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),
}
*/

View File

@ -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()
}
}