mirror of
https://github.com/alice-lg/birdwatcher.git
synced 2025-03-09 00:00:05 +01:00
111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
package endpoints
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"compress/gzip"
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/alice-lg/birdwatcher/bird"
|
|
"github.com/julienschmidt/httprouter"
|
|
)
|
|
|
|
type endpoint func(*http.Request, httprouter.Params, bool) (bird.Parsed, bool)
|
|
|
|
var Conf ServerConfig
|
|
|
|
func CheckAccess(req *http.Request) error {
|
|
if len(Conf.AllowFrom) == 0 {
|
|
return nil // AllowFrom ALL
|
|
}
|
|
|
|
// Extract IP
|
|
tokens := strings.Split(req.RemoteAddr, ":")
|
|
ip := strings.Join(tokens[:len(tokens)-1], ":")
|
|
ip = strings.Replace(ip, "[", "", -1)
|
|
ip = strings.Replace(ip, "]", "", -1)
|
|
|
|
// Check Access
|
|
for _, allowed := range Conf.AllowFrom {
|
|
if ip == allowed {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Log this request
|
|
log.Println("Rejecting access from:", ip)
|
|
|
|
return fmt.Errorf("%s is not allowed to access this service.", ip)
|
|
}
|
|
|
|
func CheckUseCache(req *http.Request) bool {
|
|
qs := req.URL.Query()
|
|
|
|
if Conf.AllowUncached &&
|
|
len(qs["uncached"]) == 1 && qs["uncached"][0] == "true" {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func Endpoint(wrapped endpoint) httprouter.Handle {
|
|
return func(w http.ResponseWriter,
|
|
r *http.Request,
|
|
ps httprouter.Params) {
|
|
|
|
// Access Control
|
|
if err := CheckAccess(r); err != nil {
|
|
http.Error(w, err.Error(), http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
res := make(map[string]interface{})
|
|
|
|
useCache := CheckUseCache(r)
|
|
ret, from_cache := wrapped(r, ps, useCache)
|
|
|
|
if reflect.DeepEqual(ret, bird.NilParse) {
|
|
w.WriteHeader(http.StatusTooManyRequests)
|
|
return
|
|
}
|
|
if reflect.DeepEqual(ret, bird.BirdError) {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Header().Set("Content-Type", "application/json")
|
|
js, _ := json.Marshal(ret)
|
|
w.Write(js)
|
|
return
|
|
}
|
|
res["api"] = GetApiInfo(&ret, from_cache)
|
|
|
|
for k, v := range ret {
|
|
res[k] = v
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
// Check if compression is supported
|
|
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
|
// Compress response
|
|
w.Header().Set("Content-Encoding", "gzip")
|
|
gz := gzip.NewWriter(w)
|
|
defer gz.Close()
|
|
json := json.NewEncoder(gz)
|
|
json.Encode(res)
|
|
} else {
|
|
json := json.NewEncoder(w)
|
|
json.Encode(res) // Fall back to uncompressed response
|
|
}
|
|
}
|
|
}
|
|
|
|
func Version(version string) httprouter.Handle {
|
|
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
w.Write([]byte(version))
|
|
}
|
|
}
|