summaryrefslogtreecommitdiff
path: root/internal/httpclient
diff options
context:
space:
mode:
authorLibravatar kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>2024-04-02 12:12:26 +0100
committerLibravatar GitHub <noreply@github.com>2024-04-02 13:12:26 +0200
commitd61d5c8a6ad045fe7779fe8d0efe2fd06f691fba (patch)
tree12b1f1ed8e2cee3875c74347e0f034bbb8f57134 /internal/httpclient
parent[chore] Try to parse public key as both Actor + bare key (#2710) (diff)
downloadgotosocial-d61d5c8a6ad045fe7779fe8d0efe2fd06f691fba.tar.xz
[bugfix] httpclient not signing subsequent redirect requests (#2798)
* move http request signing to transport * actually hook up the http roundtripper ... * add code comments for the new gtscontext functions
Diffstat (limited to 'internal/httpclient')
-rw-r--r--internal/httpclient/client.go25
-rw-r--r--internal/httpclient/sign.go41
2 files changed, 42 insertions, 24 deletions
diff --git a/internal/httpclient/client.go b/internal/httpclient/client.go
index 7adea7459..6c2427372 100644
--- a/internal/httpclient/client.go
+++ b/internal/httpclient/client.go
@@ -32,7 +32,6 @@ import (
"time"
"codeberg.org/gruf/go-bytesize"
- "codeberg.org/gruf/go-byteutil"
"codeberg.org/gruf/go-cache/v3"
errorsv2 "codeberg.org/gruf/go-errors/v2"
"codeberg.org/gruf/go-iotools"
@@ -163,7 +162,7 @@ func New(cfg Config) *Client {
}
// Set underlying HTTP client roundtripper.
- c.client.Transport = &http.Transport{
+ c.client.Transport = &signingtransport{http.Transport{
Proxy: http.ProxyFromEnvironment,
ForceAttemptHTTP2: true,
DialContext: d.DialContext,
@@ -175,7 +174,7 @@ func New(cfg Config) *Client {
ReadBufferSize: cfg.ReadBufferSize,
WriteBufferSize: cfg.WriteBufferSize,
DisableCompression: cfg.DisableCompression,
- }
+ }}
// Initiate outgoing bad hosts lookup cache.
c.badHosts = cache.NewTTL[string, struct{}](0, 1000, 0)
@@ -239,23 +238,6 @@ func (c *Client) DoSigned(r *http.Request, sign SignFunc) (rsp *http.Response, e
for i := 0; i < maxRetries; i++ {
var backoff time.Duration
- // Reset signing header fields
- now := time.Now().UTC()
- r.Header.Set("Date", now.Format("Mon, 02 Jan 2006 15:04:05")+" GMT")
- r.Header.Del("Signature")
- r.Header.Del("Digest")
-
- // Rewind body reader and content-length if set.
- if rc, ok := r.Body.(*byteutil.ReadNopCloser); ok {
- rc.Rewind() // set len AFTER rewind
- r.ContentLength = int64(rc.Len())
- }
-
- // Sign the outgoing request.
- if err := sign(r); err != nil {
- return nil, err
- }
-
l.Info("performing request")
// Perform the request.
@@ -276,6 +258,9 @@ func (c *Client) DoSigned(r *http.Request, sign SignFunc) (rsp *http.Response, e
// Search for a provided "Retry-After" header value.
if after := rsp.Header.Get("Retry-After"); after != "" {
+ // Get current time.
+ now := time.Now()
+
if u, _ := strconv.ParseUint(after, 10, 32); u != 0 {
// An integer number of backoff seconds was provided.
backoff = time.Duration(u) * time.Second
diff --git a/internal/httpclient/sign.go b/internal/httpclient/sign.go
index 78046aa28..8e66d1bda 100644
--- a/internal/httpclient/sign.go
+++ b/internal/httpclient/sign.go
@@ -17,12 +17,45 @@
package httpclient
-import "net/http"
+import (
+ "net/http"
+ "time"
+
+ "codeberg.org/gruf/go-byteutil"
+ "github.com/superseriousbusiness/gotosocial/internal/gtscontext"
+)
// SignFunc is a function signature that provides request signing.
type SignFunc func(r *http.Request) error
-type SigningClient interface {
- Do(r *http.Request) (*http.Response, error)
- DoSigned(r *http.Request, sign SignFunc) (*http.Response, error)
+// signingtransport wraps an http.Transport{}
+// (RoundTripper implementer) to check request
+// context for a signing function and using for
+// all subsequent trips through RoundTrip().
+type signingtransport struct {
+ http.Transport // underlying transport
+}
+
+func (t *signingtransport) RoundTrip(r *http.Request) (*http.Response, error) {
+ if sign := gtscontext.HTTPClientSignFunc(r.Context()); sign != nil {
+ // Reset signing header fields
+ now := time.Now().UTC()
+ r.Header.Set("Date", now.Format("Mon, 02 Jan 2006 15:04:05")+" GMT")
+ r.Header.Del("Signature")
+ r.Header.Del("Digest")
+
+ // Rewind body reader and content-length if set.
+ if rc, ok := r.Body.(*byteutil.ReadNopCloser); ok {
+ rc.Rewind() // set len AFTER rewind
+ r.ContentLength = int64(rc.Len())
+ }
+
+ // Sign the outgoing request.
+ if err := sign(r); err != nil {
+ return nil, err
+ }
+ }
+
+ // Pass to underlying transport.
+ return t.Transport.RoundTrip(r)
}