commit 9ae20db92e378c2ecd797350655a9bc2c946b1cd Author: Björn Busse Date: Mon Oct 2 10:43:44 2017 +0000 Initial commit diff --git a/main.go b/main.go new file mode 100644 index 0000000..4f432e3 --- /dev/null +++ b/main.go @@ -0,0 +1,107 @@ +package main + +import ( + "container/ring" + "fmt" + "github.com/hpcloud/tail" + "encoding/json" + "net/http" + "os" + "regexp" + "strconv" + "strings" + "time" +) + +func fileHandler(w http.ResponseWriter, r *http.Request, s string) { + fn := r.URL.Path[5:len(r.URL.Path)] + + for _, v := range whitelist { + if !strings.Contains(v, fn) { + sendFile(w, fn, "", "Permission denied") + return + } + } + + if _, err := os.Stat(fn); err != nil { + sendFile(w, fn, "", "No such file or directory") + return + } + + if (watch == false) { + t, err := tail.TailFile(fn, tail.Config{Follow: false}) + watch = true + } + + if (err == nil) { + fmt.Println(err) + } + + var m = "" + + w.WriteHeader(http.StatusOK) + for line := range t.Lines { + m += fmt.Sprintf("%s\n", line.Text) + logring.Value = line.Text + logring = logring.Next() + } + if m != m_prev { + sendFile(w, fn, m, "") + m_prev = m + } +} + +func sendFile(w http.ResponseWriter, fn string, m string, err string) { + json.NewEncoder(w).Encode(map[string]string{"time": strconv.FormatInt(t_ms(), 16), "Filename": fn, "Text": m, "error": err}) +} + +func t_ms() (int64) { + now := time.Now() + ns := now.UnixNano() + ms := ns / 1000000 + return ms +} + +func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + m := validPath.FindStringSubmatch(r.URL.Path) + if m == nil { + http.NotFound(w, r) + return + } + fmt.Println("makeHandler::request::" + r.RequestURI) + fn(w, r, m[2]) + } +} + +var prj = "httptail" +var version = "0.1.0" +var server_inet6 = "[fdef:c181:4234:7978:6::1]:8080" +var whitelist = map[int]string{ + 0: "/var/log", +} + +var logring = ring.New(1000) +var validPath = regexp.MustCompile("^/(tail*|auth)/(.*)$") +var watch bool = false +var m_prev = "" + +func main() { + uid := os.Getuid() + t.Filename = "" + + if (uid == -1) { + fmt.Println("Windows is unsupported") + } + + if (uid == 0) { + fmt.Println("Refusing to run as root") + return + } + + http.HandleFunc("/tail/", makeHandler(fileHandler)) + + fmt.Println("Serving " + prj + " " + version + " on " + server_inet6) + http.ListenAndServe(server_inet6, nil) + t.Cleanup() +}