mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 07:22:24 -05:00
[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
This commit is contained in:
parent
4bbdef02f1
commit
d61d5c8a6a
6 changed files with 98 additions and 34 deletions
|
|
@ -37,7 +37,6 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/federation/federatingdb"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/httpclient"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||
)
|
||||
|
||||
|
|
@ -54,14 +53,14 @@ type controller struct {
|
|||
state *state.State
|
||||
fedDB federatingdb.DB
|
||||
clock pub.Clock
|
||||
client httpclient.SigningClient
|
||||
client pub.HttpClient
|
||||
trspCache cache.TTLCache[string, *transport]
|
||||
userAgent string
|
||||
senders int // no. concurrent batch delivery routines.
|
||||
}
|
||||
|
||||
// NewController returns an implementation of the Controller interface for creating new transports
|
||||
func NewController(state *state.State, federatingDB federatingdb.DB, clock pub.Clock, client httpclient.SigningClient) Controller {
|
||||
func NewController(state *state.State, federatingDB federatingdb.DB, clock pub.Clock, client pub.HttpClient) Controller {
|
||||
var (
|
||||
host = config.GetHost()
|
||||
proto = config.GetProtocol()
|
||||
|
|
|
|||
|
|
@ -93,30 +93,61 @@ func (t *transport) GET(r *http.Request) (*http.Response, error) {
|
|||
if r.Method != http.MethodGet {
|
||||
return nil, errors.New("must be GET request")
|
||||
}
|
||||
ctx := r.Context() // extract, set pubkey ID.
|
||||
|
||||
// Prepare HTTP GET signing func with opts.
|
||||
sign := t.signGET(httpsig.SignatureOption{
|
||||
ExcludeQueryStringFromPathPseudoHeader: false,
|
||||
})
|
||||
|
||||
ctx := r.Context() // update with signing details.
|
||||
ctx = gtscontext.SetOutgoingPublicKeyID(ctx, t.pubKeyID)
|
||||
ctx = gtscontext.SetHTTPClientSignFunc(ctx, sign)
|
||||
r = r.WithContext(ctx) // replace request ctx.
|
||||
|
||||
// Set our predefined controller user-agent.
|
||||
r.Header.Set("User-Agent", t.controller.userAgent)
|
||||
|
||||
resp, err := t.controller.client.DoSigned(r, t.signGET(httpsig.SignatureOption{ExcludeQueryStringFromPathPseudoHeader: false}))
|
||||
// Pass to underlying HTTP client.
|
||||
resp, err := t.controller.client.Do(r)
|
||||
if err != nil || resp.StatusCode != http.StatusUnauthorized {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// try again without the path included in the HTTP signature for better compatibility
|
||||
// Ignore this response.
|
||||
_ = resp.Body.Close()
|
||||
return t.controller.client.DoSigned(r, t.signGET(httpsig.SignatureOption{ExcludeQueryStringFromPathPseudoHeader: true}))
|
||||
|
||||
// Try again without the path included in
|
||||
// the HTTP signature for better compatibility.
|
||||
sign = t.signGET(httpsig.SignatureOption{
|
||||
ExcludeQueryStringFromPathPseudoHeader: true,
|
||||
})
|
||||
|
||||
ctx = r.Context() // update with signing details.
|
||||
ctx = gtscontext.SetHTTPClientSignFunc(ctx, sign)
|
||||
r = r.WithContext(ctx) // replace request ctx.
|
||||
|
||||
// Pass to underlying HTTP client.
|
||||
return t.controller.client.Do(r)
|
||||
}
|
||||
|
||||
func (t *transport) POST(r *http.Request, body []byte) (*http.Response, error) {
|
||||
if r.Method != http.MethodPost {
|
||||
return nil, errors.New("must be POST request")
|
||||
}
|
||||
ctx := r.Context() // extract, set pubkey ID.
|
||||
|
||||
// Prepare POST signer.
|
||||
sign := t.signPOST(body)
|
||||
|
||||
ctx := r.Context() // update with signing details.
|
||||
ctx = gtscontext.SetOutgoingPublicKeyID(ctx, t.pubKeyID)
|
||||
ctx = gtscontext.SetHTTPClientSignFunc(ctx, sign)
|
||||
r = r.WithContext(ctx) // replace request ctx.
|
||||
|
||||
// Set our predefined controller user-agent.
|
||||
r.Header.Set("User-Agent", t.controller.userAgent)
|
||||
return t.controller.client.DoSigned(r, t.signPOST(body))
|
||||
|
||||
// Pass to underlying HTTP client.
|
||||
return t.controller.client.Do(r)
|
||||
}
|
||||
|
||||
// signGET will safely sign an HTTP GET request.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue