parent
1dbb80d326
commit
1d7b8f5868
26
api.go
26
api.go
|
@ -11,7 +11,7 @@ import (
|
||||||
func ListFiles(w http.ResponseWriter, r *http.Request) {
|
func ListFiles(w http.ResponseWriter, r *http.Request) {
|
||||||
data, err := json.Marshal(files)
|
data, err := json.Marshal(files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
|
@ -21,12 +21,12 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
|
||||||
name := r.URL.Query().Get("name")
|
name := r.URL.Query().Get("name")
|
||||||
file, ok := files[name]
|
file, ok := files[name]
|
||||||
if name == "" || !ok {
|
if name == "" || !ok {
|
||||||
HttpWriter(w, 404, "file not found")
|
MakeResponse(w, 404, []byte("file not found"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, err := file.Read()
|
data, err := file.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
response, err := json.Marshal(map[string]string{
|
response, err := json.Marshal(map[string]string{
|
||||||
|
@ -36,7 +36,7 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
|
||||||
"data": string(data),
|
"data": string(data),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
@ -47,21 +47,21 @@ func PostFile(w http.ResponseWriter, r *http.Request) {
|
||||||
data, err := ioutil.ReadAll(r.Body)
|
data, err := ioutil.ReadAll(r.Body)
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f := configui.File{}
|
f := configui.File{}
|
||||||
if err := json.Unmarshal(data, &f); err != nil {
|
if err := json.Unmarshal(data, &f); err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file, ok := files[f.Alias]
|
file, ok := files[f.Alias]
|
||||||
if !ok {
|
if !ok {
|
||||||
HttpWriter(w, 404, "file not found")
|
MakeResponse(w, 404, []byte("file not found"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := file.Write([]byte(f.Data)); err != nil {
|
if err := file.Write([]byte(f.Data)); err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Write([]byte("ok"))
|
w.Write([]byte("ok"))
|
||||||
|
@ -71,12 +71,12 @@ func Apply(w http.ResponseWriter, r *http.Request) {
|
||||||
name := r.URL.Query().Get("name")
|
name := r.URL.Query().Get("name")
|
||||||
file, ok := files[name]
|
file, ok := files[name]
|
||||||
if name == "" || !ok {
|
if name == "" || !ok {
|
||||||
HttpWriter(w, 404, "file not found")
|
MakeResponse(w, 404, []byte("file not found"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result, err := file.Do()
|
result, err := file.Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Write([]byte(result))
|
w.Write([]byte(result))
|
||||||
|
@ -95,12 +95,12 @@ func LoadConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
data, err := ioutil.ReadAll(r.Body)
|
data, err := ioutil.ReadAll(r.Body)
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ftmp, err := configui.ReadConfig(string(data))
|
ftmp, err := configui.ReadConfig(string(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
files = configui.GetFileMap(ftmp)
|
files = configui.GetFileMap(ftmp)
|
||||||
|
@ -110,7 +110,7 @@ func LoadConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
func getConfigHandler(w http.ResponseWriter, r *http.Request) {
|
func getConfigHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
data, err := GetConfig()
|
data, err := GetConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HttpWriter(w, 500, err.Error())
|
AbortError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResponseWriter struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
StatueCode int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ResponseWriter) WriteHeader(statusCode int) {
|
||||||
|
if w.StatueCode != 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.StatueCode = statusCode
|
||||||
|
w.ResponseWriter.WriteHeader(statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ResponseWriter) Write(body []byte) (int, error) {
|
||||||
|
if w.StatueCode == 0 {
|
||||||
|
w.WriteHeader(200)
|
||||||
|
}
|
||||||
|
return w.ResponseWriter.Write(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeResponse(w http.ResponseWriter, status int, body []byte) (int, error) {
|
||||||
|
w.WriteHeader(status)
|
||||||
|
return w.Write(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func AbortError(w http.ResponseWriter, err interface{}) (int, error) {
|
||||||
|
switch v := err.(type) {
|
||||||
|
case int:
|
||||||
|
w.WriteHeader(v)
|
||||||
|
return w.Write([]byte(strconv.Itoa(v)))
|
||||||
|
case string:
|
||||||
|
w.WriteHeader(500)
|
||||||
|
return w.Write([]byte(v))
|
||||||
|
case error:
|
||||||
|
w.WriteHeader(500)
|
||||||
|
return w.Write([]byte(v.Error()))
|
||||||
|
default:
|
||||||
|
w.WriteHeader(500)
|
||||||
|
return w.Write([]byte(strconv.Itoa(500)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Catch(rw *ResponseWriter, r *http.Request) {
|
||||||
|
ex := recover()
|
||||||
|
if ex != nil {
|
||||||
|
AbortError(rw, r)
|
||||||
|
log.Printf("%s %s %d %s %s\n", GetIP(r), r.Method, rw.StatueCode, r.URL, r.Header.Get("User-Agent"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Middleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(
|
||||||
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
rw := &ResponseWriter{w, 0}
|
||||||
|
defer Catch(rw, r)
|
||||||
|
abort := false
|
||||||
|
if flagAllow != "" {
|
||||||
|
if !matchIPGlob(GetIP(r), flagAllow) {
|
||||||
|
MakeResponse(rw, 403, []byte("permission denyed"))
|
||||||
|
abort = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !abort {
|
||||||
|
next.ServeHTTP(rw, r)
|
||||||
|
}
|
||||||
|
log.Printf("%s %s %d %s %s\n", GetIP(r), r.Method, rw.StatueCode, r.URL, r.Header.Get("User-Agent"))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIP(r *http.Request) string {
|
||||||
|
ip := r.Header.Get("X-Real-Ip")
|
||||||
|
if ip == "" {
|
||||||
|
ips := r.Header.Get("X-Forwarded-For")
|
||||||
|
ipArr := strings.Split(ips, ",")
|
||||||
|
ip = strings.Trim(ipArr[len(ipArr)-1], " ")
|
||||||
|
}
|
||||||
|
if ip == "" {
|
||||||
|
var err error
|
||||||
|
ip, _, err = net.SplitHostPort(r.RemoteAddr)
|
||||||
|
if err != nil {
|
||||||
|
ip = r.RemoteAddr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(w http.ResponseWriter, name string, data interface{}) error {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := tmpl.ExecuteTemplate(buf, "home", data)
|
||||||
|
if err != nil {
|
||||||
|
AbortError(w, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = w.Write(buf.Bytes())
|
||||||
|
return err
|
||||||
|
}
|
2
route.go
2
route.go
|
@ -37,6 +37,6 @@ func setRoutes(mux *http.ServeMux) {
|
||||||
Lang: "json",
|
Lang: "json",
|
||||||
}
|
}
|
||||||
|
|
||||||
serve(w, "home", data)
|
Parse(w, "home", data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
92
util.go
92
util.go
|
@ -2,40 +2,53 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"bytes"
|
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Middleware(next http.Handler) http.Handler {
|
func matchIPGlob(ip, pattern string) bool {
|
||||||
return http.HandlerFunc(
|
parts := strings.Split(pattern, ".")
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
seg := strings.Split(ip, ".")
|
||||||
defer func() {
|
for i, part := range parts {
|
||||||
r := recover()
|
|
||||||
if r != nil {
|
// normalize pattern to 3 digits
|
||||||
log.Println("panic", r)
|
switch len(part) {
|
||||||
w.WriteHeader(500)
|
case 1:
|
||||||
|
if part == "*" {
|
||||||
|
part = "***"
|
||||||
|
} else {
|
||||||
|
part = "00" + part
|
||||||
}
|
}
|
||||||
}()
|
case 2:
|
||||||
abort := false
|
if strings.HasPrefix(part, "*") {
|
||||||
if flagAllow != "" {
|
part = "*" + part
|
||||||
if GetIP(r) != flagAllow {
|
} else if strings.HasSuffix(part, "*") {
|
||||||
HttpWriter(w, 403, "permission denyed")
|
part = part + "*"
|
||||||
abort = true
|
} else {
|
||||||
|
part = "0" + part
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !abort {
|
// normalize ip to 3 digits
|
||||||
next.ServeHTTP(w, r)
|
switch len(seg[i]) {
|
||||||
|
case 1:
|
||||||
|
seg[i] = "00" + seg[i]
|
||||||
|
case 2:
|
||||||
|
seg[i] = "0" + seg[i]
|
||||||
}
|
}
|
||||||
log.Printf("%s %s %s %s\n", GetIP(r), r.Method, r.URL, r.Header.Get("User-Agent"))
|
|
||||||
},
|
for j := range part {
|
||||||
)
|
if string(part[j]) == "*" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if part[j] != seg[i][j] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func bundle(buf io.Writer, paths []string, flat bool) error {
|
func bundle(buf io.Writer, paths []string, flat bool) error {
|
||||||
|
@ -95,36 +108,3 @@ func bundle(buf io.Writer, paths []string, flat bool) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func HttpWriter(w http.ResponseWriter, status int, errStr string) {
|
|
||||||
w.WriteHeader(status)
|
|
||||||
w.Write([]byte(errStr))
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetIP(r *http.Request) string {
|
|
||||||
ip := r.Header.Get("X-Real-Ip")
|
|
||||||
if ip == "" {
|
|
||||||
ips := r.Header.Get("X-Forwarded-For")
|
|
||||||
ipArr := strings.Split(ips, ",")
|
|
||||||
ip = strings.Trim(ipArr[len(ipArr)-1], " ")
|
|
||||||
}
|
|
||||||
if ip == "" {
|
|
||||||
var err error
|
|
||||||
ip, _, err = net.SplitHostPort(r.RemoteAddr)
|
|
||||||
if err != nil {
|
|
||||||
ip = r.RemoteAddr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ip
|
|
||||||
}
|
|
||||||
|
|
||||||
func serve(w http.ResponseWriter, name string, data interface{}) error {
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
err := tmpl.ExecuteTemplate(buf, "home", data)
|
|
||||||
if err != nil {
|
|
||||||
HttpWriter(w, 500, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = w.Write(buf.Bytes())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue