2017-10-02 10:43:44 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2017-10-02 10:54:27 +00:00
|
|
|
"container/ring"
|
|
|
|
"fmt"
|
|
|
|
"github.com/hpcloud/tail"
|
|
|
|
"encoding/json"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"regexp"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
2017-10-02 10:43:44 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
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")
|
2017-10-02 10:54:27 +00:00
|
|
|
return
|
2017-10-02 10:43:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := os.Stat(fn); err != nil {
|
|
|
|
sendFile(w, fn, "", "No such file or directory")
|
|
|
|
return
|
|
|
|
}
|
2017-10-02 13:51:31 +00:00
|
|
|
fmt.Println("watch: %#v", watch)
|
2017-10-02 10:43:44 +00:00
|
|
|
if (watch == false) {
|
2017-10-02 13:51:31 +00:00
|
|
|
t, err := tail.TailFile(fn, tail.Config{Follow: false, MustExist: true})
|
|
|
|
watch = true
|
|
|
|
if (err == nil) {
|
|
|
|
fmt.Println(err)
|
|
|
|
}
|
2017-10-02 10:43:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2017-10-02 13:51:31 +00:00
|
|
|
json.NewEncoder(w).Encode(map[string]string{"time": strconv.FormatInt(getMsTimestamp(), 16), "Filename": fn, "Text": m, "error": err})
|
2017-10-02 10:43:44 +00:00
|
|
|
}
|
|
|
|
|
2017-10-02 13:51:31 +00:00
|
|
|
func getMsTimestamp() (int64) {
|
2017-10-02 10:43:44 +00:00
|
|
|
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{
|
2017-10-02 10:54:27 +00:00
|
|
|
0: "/var/log",
|
2017-10-02 10:43:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var logring = ring.New(1000)
|
|
|
|
var validPath = regexp.MustCompile("^/(tail*|auth)/(.*)$")
|
|
|
|
var watch bool = false
|
|
|
|
var m_prev = ""
|
|
|
|
|
|
|
|
func main() {
|
2017-10-02 10:54:27 +00:00
|
|
|
uid := os.Getuid()
|
2017-10-02 10:43:44 +00:00
|
|
|
|
2017-10-02 10:54:27 +00:00
|
|
|
if (uid == -1) {
|
|
|
|
fmt.Println("Windows is unsupported")
|
2017-10-02 10:43:44 +00:00
|
|
|
}
|
|
|
|
|
2017-10-02 10:54:27 +00:00
|
|
|
if (uid == 0) {
|
2017-10-02 10:43:44 +00:00
|
|
|
fmt.Println("Refusing to run as root")
|
2017-10-02 10:54:27 +00:00
|
|
|
return
|
|
|
|
}
|
2017-10-02 10:43:44 +00:00
|
|
|
|
2017-10-02 10:54:27 +00:00
|
|
|
http.HandleFunc("/tail/", makeHandler(fileHandler))
|
2017-10-02 10:43:44 +00:00
|
|
|
|
2017-10-02 13:51:31 +00:00
|
|
|
fmt.Println("Serving " + prj + " " + version + " on " + server_inet6)
|
|
|
|
http.ListenAndServe(server_inet6, nil)
|
|
|
|
//t.Cleanup()
|
2017-10-02 10:43:44 +00:00
|
|
|
}
|