Skip to content

Commit

Permalink
cmd/strelaypoolsrv: smaller response
Browse files Browse the repository at this point in the history
  • Loading branch information
calmh committed May 7, 2024
1 parent a5bf110 commit a9d61fa
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 40 deletions.
6 changes: 3 additions & 3 deletions cmd/strelaypoolsrv/gui/index.html
Expand Up @@ -259,7 +259,7 @@ <h1>Relay Pool Data</h1>
return a.value > b.value ? 1 : -1;
}

$http.get("/endpoint").then(function(response) {
$http.get("/endpoint/full").then(function(response) {
$scope.relays = response.data.relays;

angular.forEach($scope.relays, function(relay) {
Expand Down Expand Up @@ -338,7 +338,7 @@ <h1>Relay Pool Data</h1>
relay.showMarker = function() {
relay.marker.openPopup();
}

relay.hideMarker = function() {
relay.marker.closePopup();
}
Expand All @@ -347,7 +347,7 @@ <h1>Relay Pool Data</h1>

function addCircleToMap(relay) {
console.log(relay.location.latitude)
L.circle([relay.location.latitude, relay.location.longitude],
L.circle([relay.location.latitude, relay.location.longitude],
{
radius: ((relay.stats.bytesProxied * 100) / $scope.totals.bytesProxied) * 10000,
color: "FF0000",
Expand Down
92 changes: 56 additions & 36 deletions cmd/strelaypoolsrv/main.go
Expand Up @@ -27,9 +27,7 @@ import (
"github.com/syncthing/syncthing/cmd/strelaypoolsrv/auto"
"github.com/syncthing/syncthing/lib/assets"
_ "github.com/syncthing/syncthing/lib/automaxprocs"
"github.com/syncthing/syncthing/lib/httpcache"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/relay/client"
"github.com/syncthing/syncthing/lib/sync"
"github.com/syncthing/syncthing/lib/tlsutil"
Expand All @@ -51,6 +49,10 @@ type relay struct {
StatsRetrieved time.Time `json:"statsRetrieved"`
}

type relayShort struct {
URL string `json:"url"`
}

type stats struct {
StartTime time.Time `json:"startTime"`
UptimeSeconds int `json:"uptimeSeconds"`
Expand Down Expand Up @@ -215,7 +217,8 @@ func main() {

handler := http.NewServeMux()
handler.HandleFunc("/", handleAssets)
handler.Handle("/endpoint", httpcache.SinglePath(http.HandlerFunc(handleRequest), 15*time.Second))
handler.HandleFunc("/endpoint", withAPIMetrics(handleEndpoint))
handler.HandleFunc("/endpoint/full", withAPIMetrics(handleEndpointFull))
handler.HandleFunc("/metrics", handleMetrics)

srv := http.Server{
Expand Down Expand Up @@ -255,57 +258,74 @@ func handleAssets(w http.ResponseWriter, r *http.Request) {
assets.Serve(w, r, as)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
timer := prometheus.NewTimer(apiRequestsSeconds.WithLabelValues(r.Method))

w = NewLoggingResponseWriter(w)
defer func() {
timer.ObserveDuration()
lw := w.(*loggingResponseWriter)
apiRequestsTotal.WithLabelValues(r.Method, strconv.Itoa(lw.statusCode)).Inc()
}()

if ipHeader != "" {
hdr := r.Header.Get(ipHeader)
fields := strings.Split(hdr, ",")
if len(fields) > 0 {
r.RemoteAddr = strings.TrimSpace(fields[len(fields)-1])
}
}
w.Header().Set("Access-Control-Allow-Origin", "*")
switch r.Method {
case "GET":
handleGetRequest(w, r)
case "POST":
handlePostRequest(w, r)
default:
if debug {
log.Println("Unhandled HTTP method", r.Method)
}
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
func withAPIMetrics(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
timer := prometheus.NewTimer(apiRequestsSeconds.WithLabelValues(r.Method))
w = NewLoggingResponseWriter(w)
defer func() {
timer.ObserveDuration()
lw := w.(*loggingResponseWriter)
apiRequestsTotal.WithLabelValues(r.Method, strconv.Itoa(lw.statusCode)).Inc()
}()
next(w, r)
}
}

func handleGetRequest(rw http.ResponseWriter, r *http.Request) {
// handleEndpointFull returns the relay list with full metadata and
// statistics. Large, and expensive.
func handleEndpointFull(rw http.ResponseWriter, r *http.Request) {
rw.Header().Set("Content-Type", "application/json; charset=utf-8")
rw.Header().Set("Access-Control-Allow-Origin", "*")

mut.RLock()
relays := make([]*relay, len(permanentRelays)+len(knownRelays))
n := copy(relays, permanentRelays)
copy(relays[n:], knownRelays)
mut.RUnlock()

// Shuffle
rand.Shuffle(relays)

_ = json.NewEncoder(rw).Encode(map[string][]*relay{
"relays": relays,
})
}

func handlePostRequest(w http.ResponseWriter, r *http.Request) {
func handleEndpoint(rw http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
handleEndpointShort(rw, r)
case http.MethodPost:
handleRegister(rw, r)
default:
http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
}
}

// handleEndpointShort returns the relay list with only the URL.
func handleEndpointShort(rw http.ResponseWriter, r *http.Request) {
rw.Header().Set("Content-Type", "application/json; charset=utf-8")
rw.Header().Set("Access-Control-Allow-Origin", "*")

mut.RLock()
relays := make([]relayShort, len(permanentRelays)+len(knownRelays))
for i, r := range append(permanentRelays, knownRelays...) {
relays[i].URL = r.URL
}
mut.RUnlock()

_ = json.NewEncoder(rw).Encode(map[string][]relayShort{
"relays": relays,
})
}

func handleRegister(w http.ResponseWriter, r *http.Request) {
// Get the IP address of the client
rhost := r.RemoteAddr
if ipHeader != "" {
hdr := r.Header.Get(ipHeader)
fields := strings.Split(hdr, ",")
if len(fields) > 0 {
rhost = strings.TrimSpace(fields[len(fields)-1])
}
}
if host, _, err := net.SplitHostPort(rhost); err == nil {
rhost = host
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/strelaypoolsrv/main_test.go
Expand Up @@ -42,7 +42,7 @@ func TestHandleGetRequest(t *testing.T) {

w := httptest.NewRecorder()
w.Body = new(bytes.Buffer)
handleGetRequest(w, httptest.NewRequest("GET", "/", nil))
handleEndpointFull(w, httptest.NewRequest("GET", "/", nil))

result := make(map[string][]*relay)
err := json.NewDecoder(w.Body).Decode(&result)
Expand Down

0 comments on commit a9d61fa

Please sign in to comment.