diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d68c120 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# binary +hostsplitter \ No newline at end of file diff --git a/config.go b/config.go index 3621793..1a6e128 100644 --- a/config.go +++ b/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 diff --git a/hostsplitter.go b/hostsplitter.go index 6e213e2..6ba9d76 100644 --- a/hostsplitter.go +++ b/hostsplitter.go @@ -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), + } +*/ diff --git a/signal_handler.go b/signal_handler.go index bd57e02..3241a1c 100644 --- a/signal_handler.go +++ b/signal_handler.go @@ -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() } }