parent
1dbb80d326
commit
1d7b8f5868
26
api.go
26
api.go
|
@ -11,7 +11,7 @@ import (
|
|||
func ListFiles(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := json.Marshal(files)
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
w.Write(data)
|
||||
|
@ -21,12 +21,12 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
|
|||
name := r.URL.Query().Get("name")
|
||||
file, ok := files[name]
|
||||
if name == "" || !ok {
|
||||
HttpWriter(w, 404, "file not found")
|
||||
MakeResponse(w, 404, []byte("file not found"))
|
||||
return
|
||||
}
|
||||
data, err := file.Read()
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
response, err := json.Marshal(map[string]string{
|
||||
|
@ -36,7 +36,7 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
|
|||
"data": string(data),
|
||||
})
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
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)
|
||||
r.Body.Close()
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
f := configui.File{}
|
||||
if err := json.Unmarshal(data, &f); err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
file, ok := files[f.Alias]
|
||||
if !ok {
|
||||
HttpWriter(w, 404, "file not found")
|
||||
MakeResponse(w, 404, []byte("file not found"))
|
||||
return
|
||||
}
|
||||
if err := file.Write([]byte(f.Data)); err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
w.Write([]byte("ok"))
|
||||
|
@ -71,12 +71,12 @@ func Apply(w http.ResponseWriter, r *http.Request) {
|
|||
name := r.URL.Query().Get("name")
|
||||
file, ok := files[name]
|
||||
if name == "" || !ok {
|
||||
HttpWriter(w, 404, "file not found")
|
||||
MakeResponse(w, 404, []byte("file not found"))
|
||||
return
|
||||
}
|
||||
result, err := file.Do()
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
w.Write([]byte(result))
|
||||
|
@ -95,12 +95,12 @@ func LoadConfig(w http.ResponseWriter, r *http.Request) {
|
|||
data, err := ioutil.ReadAll(r.Body)
|
||||
r.Body.Close()
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
ftmp, err := configui.ReadConfig(string(data))
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
files = configui.GetFileMap(ftmp)
|
||||
|
@ -110,7 +110,7 @@ func LoadConfig(w http.ResponseWriter, r *http.Request) {
|
|||
func getConfigHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := GetConfig()
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
AbortError(w, err)
|
||||
return
|
||||
}
|
||||
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",
|
||||
}
|
||||
|
||||
serve(w, "home", data)
|
||||
Parse(w, "home", data)
|
||||
})
|
||||
}
|
||||
|
|
98
util.go
98
util.go
|
@ -2,40 +2,53 @@ package main
|
|||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Middleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
log.Println("panic", r)
|
||||
w.WriteHeader(500)
|
||||
}
|
||||
}()
|
||||
abort := false
|
||||
if flagAllow != "" {
|
||||
if GetIP(r) != flagAllow {
|
||||
HttpWriter(w, 403, "permission denyed")
|
||||
abort = true
|
||||
}
|
||||
}
|
||||
func matchIPGlob(ip, pattern string) bool {
|
||||
parts := strings.Split(pattern, ".")
|
||||
seg := strings.Split(ip, ".")
|
||||
for i, part := range parts {
|
||||
|
||||
if !abort {
|
||||
next.ServeHTTP(w, r)
|
||||
// normalize pattern to 3 digits
|
||||
switch len(part) {
|
||||
case 1:
|
||||
if part == "*" {
|
||||
part = "***"
|
||||
} else {
|
||||
part = "00" + part
|
||||
}
|
||||
log.Printf("%s %s %s %s\n", GetIP(r), r.Method, r.URL, r.Header.Get("User-Agent"))
|
||||
},
|
||||
)
|
||||
case 2:
|
||||
if strings.HasPrefix(part, "*") {
|
||||
part = "*" + part
|
||||
} else if strings.HasSuffix(part, "*") {
|
||||
part = part + "*"
|
||||
} else {
|
||||
part = "0" + part
|
||||
}
|
||||
}
|
||||
|
||||
// normalize ip to 3 digits
|
||||
switch len(seg[i]) {
|
||||
case 1:
|
||||
seg[i] = "00" + seg[i]
|
||||
case 2:
|
||||
seg[i] = "0" + seg[i]
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -95,36 +108,3 @@ func bundle(buf io.Writer, paths []string, flat bool) error {
|
|||
|
||||
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