123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package main
- import (
- "fmt"
- "io"
- "log"
- "net/http"
- "strconv"
- "github.com/abh/geodns/monitor"
- "github.com/abh/geodns/zones"
- "github.com/prometheus/client_golang/prometheus/promhttp"
- )
- type httpServer struct {
- mux *http.ServeMux
- zones *zones.MuxManager
- serverInfo *monitor.ServerInfo
- }
- type rate struct {
- Name string
- Count int64
- Metrics zones.ZoneMetrics
- }
- type rates []*rate
- func (s rates) Len() int { return len(s) }
- func (s rates) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
- type ratesByCount struct{ rates }
- func (s ratesByCount) Less(i, j int) bool {
- ic := s.rates[i].Count
- jc := s.rates[j].Count
- if ic == jc {
- return s.rates[i].Name < s.rates[j].Name
- }
- return ic > jc
- }
- func topParam(req *http.Request, def int) int {
- req.ParseForm()
- topOption := def
- topParam := req.Form["top"]
- if len(topParam) > 0 {
- var err error
- topOption, err = strconv.Atoi(topParam[0])
- if err != nil {
- topOption = def
- }
- }
- return topOption
- }
- func NewHTTPServer(mm *zones.MuxManager, serverInfo *monitor.ServerInfo) *httpServer {
- hs := &httpServer{
- zones: mm,
- mux: &http.ServeMux{},
- serverInfo: serverInfo,
- }
- hs.mux.HandleFunc("/", hs.mainServer)
- hs.mux.Handle("/metrics", promhttp.Handler())
- return hs
- }
- func (hs *httpServer) Mux() *http.ServeMux {
- return hs.mux
- }
- func (hs *httpServer) Run(listen string) {
- log.Println("Starting HTTP interface on", listen)
- log.Fatal(http.ListenAndServe(listen, &basicauth{h: hs.mux}))
- }
- func (hs *httpServer) mainServer(w http.ResponseWriter, req *http.Request) {
- if req.RequestURI != "/version" {
- http.NotFound(w, req)
- return
- }
- w.Header().Set("Content-Type", "text/plain")
- w.WriteHeader(200)
- io.WriteString(w, `GeoDNS `+hs.serverInfo.Version+`\n`)
- }
- type basicauth struct {
- h http.Handler
- }
- func (b *basicauth) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- cfgMutex.RLock()
- user := Config.HTTP.User
- password := Config.HTTP.Password
- cfgMutex.RUnlock()
- if len(user) == 0 {
- b.h.ServeHTTP(w, r)
- return
- }
- ruser, rpass, ok := r.BasicAuth()
- if ok {
- if ruser == user && rpass == password {
- b.h.ServeHTTP(w, r)
- return
- }
- }
- w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm=%q`, "GeoDNS Status"))
- http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
- return
- }
|