2022-01-10 04:47:40 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2022-01-10 05:11:15 +00:00
|
|
|
"encoding/json"
|
2022-01-10 04:53:23 +00:00
|
|
|
"fmt"
|
2022-01-10 05:13:42 +00:00
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/spf13/viper"
|
2022-01-10 04:53:23 +00:00
|
|
|
"net"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"path"
|
2022-01-10 05:11:15 +00:00
|
|
|
"strings"
|
2022-01-10 04:47:40 +00:00
|
|
|
)
|
|
|
|
|
2022-01-10 05:13:42 +00:00
|
|
|
func statusHandler(w http.ResponseWriter, r *http.Request) {
|
2022-01-10 04:53:23 +00:00
|
|
|
w.WriteHeader(http.StatusOK)
|
2022-01-10 04:47:40 +00:00
|
|
|
}
|
|
|
|
|
2022-01-10 05:13:42 +00:00
|
|
|
func mirrorsHandler(w http.ResponseWriter, r *http.Request) {
|
2022-01-10 05:11:15 +00:00
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
|
|
|
json.NewEncoder(w).Encode(servers)
|
|
|
|
}
|
|
|
|
|
2022-01-10 05:13:42 +00:00
|
|
|
func redirectHandler(w http.ResponseWriter, r *http.Request) {
|
2022-01-10 04:53:23 +00:00
|
|
|
ipStr, _, err := net.SplitHostPort(r.RemoteAddr)
|
2022-01-10 04:47:40 +00:00
|
|
|
|
2022-01-10 04:53:23 +00:00
|
|
|
if err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
2022-01-10 04:47:40 +00:00
|
|
|
|
2022-01-10 04:53:23 +00:00
|
|
|
ip := net.ParseIP(ipStr)
|
2022-01-10 04:47:40 +00:00
|
|
|
|
2022-01-10 04:53:23 +00:00
|
|
|
// TODO: This is temporary to allow testing on private addresses.
|
|
|
|
if ip.IsPrivate() {
|
|
|
|
ip = net.ParseIP("1.1.1.1")
|
|
|
|
}
|
2022-01-10 04:47:40 +00:00
|
|
|
|
2022-01-10 04:53:23 +00:00
|
|
|
server, distance, err := servers.Closest(ip)
|
2022-01-10 04:47:40 +00:00
|
|
|
|
2022-01-10 04:53:23 +00:00
|
|
|
if err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
2022-01-10 04:47:40 +00:00
|
|
|
|
2022-03-31 01:01:25 +00:00
|
|
|
scheme := r.URL.Scheme
|
|
|
|
|
|
|
|
if scheme == "" {
|
|
|
|
scheme = "https"
|
|
|
|
}
|
|
|
|
|
2022-01-10 05:11:15 +00:00
|
|
|
redirectPath := path.Join(server.Path, r.URL.Path)
|
|
|
|
|
|
|
|
if dlMap != nil {
|
|
|
|
if newPath, exists := dlMap[strings.TrimLeft(r.URL.Path, "/")]; exists {
|
2022-01-11 06:05:20 +00:00
|
|
|
downloadsMapped.Inc()
|
2022-01-10 05:11:15 +00:00
|
|
|
redirectPath = path.Join(server.Path, newPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-10 04:53:23 +00:00
|
|
|
u := &url.URL{
|
2022-03-31 01:01:25 +00:00
|
|
|
Scheme: scheme,
|
2022-01-10 04:53:23 +00:00
|
|
|
Host: server.Host,
|
2022-01-10 05:11:15 +00:00
|
|
|
Path: redirectPath,
|
2022-01-10 04:53:23 +00:00
|
|
|
}
|
2022-01-10 04:47:40 +00:00
|
|
|
|
2022-01-11 06:05:20 +00:00
|
|
|
server.Redirects.Inc()
|
|
|
|
redirectsServed.Inc()
|
|
|
|
|
2022-01-10 04:53:23 +00:00
|
|
|
w.Header().Set("X-Geo-Distance", fmt.Sprintf("%f", distance))
|
|
|
|
w.Header().Set("Location", u.String())
|
|
|
|
w.WriteHeader(http.StatusFound)
|
|
|
|
}
|
2022-01-10 05:13:42 +00:00
|
|
|
|
|
|
|
func reloadHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if mapFile := viper.GetString("dl_map"); mapFile != "" {
|
|
|
|
log.WithField("file", mapFile).Info("Loading download map")
|
|
|
|
|
|
|
|
newMap, err := loadMap(mapFile)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
dlMap = newMap
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
w.WriteHeader(http.StatusNotFound)
|
|
|
|
}
|
2022-01-10 05:15:07 +00:00
|
|
|
|
|
|
|
func dlMapHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if dlMap == nil {
|
|
|
|
w.WriteHeader(http.StatusNotFound)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
|
|
|
json.NewEncoder(w).Encode(dlMap)
|
|
|
|
}
|