httptail/main.go

108 lines
2.3 KiB
Go
Raw Normal View History

2017-10-02 10:43:44 +00:00
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()
}