···11package main
2233import (
44+ "encoding/json"
45 "errors"
56 "fmt"
67 "net/http"
···5859 }
59606061 // forward on to any sibling instances (note that sometimes is, sometimes isn't an admin request)
6161- go s.ForwardAdminRequest(c)
6262+ b, err := json.Marshal(body)
6363+ if err != nil {
6464+ return err
6565+ }
6666+ go s.ForwardSiblingRequest(c, b)
62676368 return s.relay.SubscribeToHost(ctx, hostname, noSSL, false)
6469}
+44-16
cmd/relay/handlers_admin.go
···11package main
2233import (
44+ "bytes"
55+ "encoding/json"
46 "errors"
57 "fmt"
88+ "io"
69 "net/http"
710 "strconv"
811 "strings"
···98101 }
99102100103 // forward on to any sibling instances
101101- go s.ForwardAdminRequest(c)
104104+ b, err := json.Marshal(body)
105105+ if err != nil {
106106+ return err
107107+ }
108108+ go s.ForwardSiblingRequest(c, b)
102109103110 return c.JSON(http.StatusOK, map[string]any{
104111 "success": "true",
···138145 }
139146140147 // forward on to any sibling instances
141141- go s.ForwardAdminRequest(c)
148148+ b, err := json.Marshal(body)
149149+ if err != nil {
150150+ return err
151151+ }
152152+ go s.ForwardSiblingRequest(c, b)
142153143154 return c.JSON(http.StatusOK, map[string]any{
144155 "success": "true",
···344355 _ = s.relay.Slurper.KillUpstreamConnection(ctx, host.Hostname, false)
345356346357 // forward on to any sibling instances
347347- go s.ForwardAdminRequest(c)
358358+ go s.ForwardSiblingRequest(c, nil)
348359349360 return c.JSON(http.StatusOK, map[string]any{
350361 "success": "true",
···375386 }
376387377388 // forward on to any sibling instances
378378- go s.ForwardAdminRequest(c)
389389+ go s.ForwardSiblingRequest(c, nil)
379390380391 return c.JSON(http.StatusOK, map[string]any{
381392 "success": "true",
···423434 }
424435425436 // forward on to any sibling instances
426426- go s.ForwardAdminRequest(c)
437437+ b, err := json.Marshal(body)
438438+ if err != nil {
439439+ return err
440440+ }
441441+ go s.ForwardSiblingRequest(c, b)
427442428443 return c.JSON(http.StatusOK, map[string]any{
429444 "success": "true",
···444459 }
445460446461 // forward on to any sibling instances
447447- go s.ForwardAdminRequest(c)
462462+ b, err := json.Marshal(body)
463463+ if err != nil {
464464+ return err
465465+ }
466466+ go s.ForwardSiblingRequest(c, b)
448467449468 return c.JSON(http.StatusOK, map[string]any{
450469 "success": "true",
···485504 }
486505487506 // forward on to any sibling instances
488488- go s.ForwardAdminRequest(c)
507507+ b, err := json.Marshal(body)
508508+ if err != nil {
509509+ return err
510510+ }
511511+ go s.ForwardSiblingRequest(c, b)
489512490513 return c.JSON(http.StatusOK, map[string]any{
491514 "success": "true",
···493516}
494517495518// this method expects to be run in a goroutine. it does not take a `context.Context`, the input `echo.Context` has likely be cancelled/closed, and does not return an error (only logs)
496496-func (s *Service) ForwardAdminRequest(c echo.Context) {
519519+func (s *Service) ForwardSiblingRequest(c echo.Context, body []byte) {
497520498521 if len(s.config.SiblingRelayHosts) == 0 {
499522 return
···531554 } else {
532555 u.Scheme = "https"
533556 }
534534- upstreamReq, err := http.NewRequest(req.Method, u.String(), req.Body)
557557+ var b io.Reader
558558+ if body != nil {
559559+ b = bytes.NewBuffer(body)
560560+ }
561561+ upstreamReq, err := http.NewRequest(req.Method, u.String(), b)
535562 if err != nil {
536563 s.logger.Error("creating admin forward request failed", "method", req.Method, "url", u.String(), "err", err)
537564 continue
538565 }
539566540567 // copy some headers from inbound request
541541- for k, vals := range req.Header {
542542- if strings.ToLower(k) == "accept" || strings.ToLower(k) == "authentication" {
543543- upstreamReq.Header.Add(k, vals[0])
568568+ for _, hdr := range []string{"Accept", "User-Agent", "Authorization", "Content-Type"} {
569569+ val := req.Header.Get(hdr)
570570+ if val != "" {
571571+ upstreamReq.Header.Set(hdr, val)
544572 }
545573 }
546546- upstreamReq.Header.Add("User-Agent", s.relay.Config.UserAgent)
547547- upstreamReq.Header.Add("Forwarded", "by=relay")
574574+ upstreamReq.Header.Add("Via", s.relay.Config.UserAgent)
548575549576 upstreamResp, err := client.Do(upstreamReq)
550577 if err != nil {
551578 s.logger.Error("forwarded admin HTTP request failed", "method", req.Method, "url", u.String(), "err", err)
552579 continue
553580 }
554554- upstreamResp.Body.Close()
555581 if upstreamResp.StatusCode != http.StatusOK {
556556- s.logger.Error("forwarded admin HTTP request failed", "method", req.Method, "url", u.String(), "statusCode", upstreamResp.StatusCode)
582582+ respBytes, _ := io.ReadAll(upstreamResp.Body)
583583+ s.logger.Error("forwarded admin HTTP request failed", "method", req.Method, "url", u.String(), "statusCode", upstreamResp.StatusCode, "body", string(respBytes))
557584 continue
558585 }
586586+ upstreamResp.Body.Close()
559587 s.logger.Info("successfully forwarded admin HTTP request", "method", req.Method, "url", u.String())
560588 }
561589}