Skip to content

Commit b101614

Browse files
yaronfcursoragent
andcommitted
refactor: single-pass Signature-Input walk for DetailsByTag
Build all MessageDetails from headers once instead of listing labels and re-parsing per name; share psiSignatureFromInnerList with parse path. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 6e9ca53 commit b101614

2 files changed

Lines changed: 67 additions & 32 deletions

File tree

signatures.go

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -976,13 +976,17 @@ func parseSignatureInput(input string, sigName string) (*psiSignature, error) {
976976
}
977977
memberForName, _ := sigs.Get(sigName)
978978
fieldsList, ok := memberForName.(httpsfv.InnerList)
979+
if !ok {
980+
return nil, fmt.Errorf("Signature-Input: signature %s does not have an inner list", sigName)
981+
}
982+
return psiSignatureFromInnerList(sigName, fieldsList)
983+
}
984+
985+
func psiSignatureFromInnerList(sigName string, fieldsList httpsfv.InnerList) (*psiSignature, error) {
979986
osp, err := httpsfv.Marshal(fieldsList) // undocumented functionality
980987
if err != nil {
981988
return nil, fmt.Errorf("could not marshal inner list: %w", err)
982989
}
983-
if !ok {
984-
return nil, fmt.Errorf("Signature-Input: signature %s does not have an inner list", sigName)
985-
}
986990
var f Fields
987991
for _, ff := range fieldsList.Items {
988992
f.f = append(f.f, field(ff))
@@ -999,6 +1003,53 @@ func parseSignatureInput(input string, sigName string) (*psiSignature, error) {
9991003
return &psiSignature{sigName, osp, f, params}, nil
10001004
}
10011005

1006+
// signatureDetailsListFromHeaders builds MessageDetails for each Signature-Input member
1007+
// in a single SFV pass. Each label must also appear in Signature (RFC 9421). Missing
1008+
// Signature / Signature-Input yields an empty list (same spirit as RequestSignatureNames).
1009+
func signatureDetailsListFromHeaders(headers http.Header) ([]*MessageDetails, error) {
1010+
if headers == nil {
1011+
return nil, nil
1012+
}
1013+
normalized := normalizeHeaderNames(headers)
1014+
siVals := normalized["signature-input"] //nolint:staticcheck // SA1008: lowercase map keys by design
1015+
sigVals := normalized["signature"] //nolint:staticcheck // SA1008: lowercase map keys by design
1016+
if len(siVals) == 0 || len(sigVals) == 0 {
1017+
return nil, nil
1018+
}
1019+
siDict, err := httpsfv.UnmarshalDictionary(siVals)
1020+
if err != nil {
1021+
return nil, fmt.Errorf("cannot parse Signature-Input: %w", err)
1022+
}
1023+
sigDict, err := httpsfv.UnmarshalDictionary(sigVals)
1024+
if err != nil {
1025+
return nil, fmt.Errorf("cannot parse Signature: %w", err)
1026+
}
1027+
var out []*MessageDetails
1028+
for _, name := range siDict.Names() {
1029+
if _, ok := sigDict.Get(name); !ok {
1030+
return nil, fmt.Errorf("Signature-Input label %q missing from Signature", name)
1031+
}
1032+
member, ok := siDict.Get(name)
1033+
if !ok {
1034+
return nil, fmt.Errorf("cannot read Signature-Input member %q", name)
1035+
}
1036+
inner, ok := member.(httpsfv.InnerList)
1037+
if !ok {
1038+
return nil, fmt.Errorf("Signature-Input: signature %s does not have an inner list", name)
1039+
}
1040+
psi, err := psiSignatureFromInnerList(name, inner)
1041+
if err != nil {
1042+
return nil, err
1043+
}
1044+
details, err := signatureDetails(name, psi)
1045+
if err != nil {
1046+
return nil, err
1047+
}
1048+
out = append(out, details)
1049+
}
1050+
return out, nil
1051+
}
1052+
10021053
func parseWantSignature(wantSignature string) ([]byte, error) {
10031054
wantSigItem, err := httpsfv.UnmarshalItem([]string{wantSignature})
10041055
if err != nil {

signtag.go

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@ func RequestDetailsByTag(req *http.Request, tag string) (*MessageDetails, error)
2323
if req == nil {
2424
return nil, fmt.Errorf("nil request")
2525
}
26-
names, err := RequestSignatureNames(req, false)
26+
all, err := signatureDetailsListFromHeaders(req.Header)
2727
if err != nil {
2828
return nil, err
2929
}
30-
return detailsByTag(names, tag, func(name string) (*MessageDetails, error) {
31-
return RequestDetails(name, req)
32-
})
30+
return detailsByTag(all, tag)
3331
}
3432

3533
// ResponseDetailsByTag returns MessageDetails for the unique Signature whose
@@ -41,13 +39,11 @@ func ResponseDetailsByTag(res *http.Response, tag string) (*MessageDetails, erro
4139
if res == nil {
4240
return nil, fmt.Errorf("nil response")
4341
}
44-
names, err := ResponseSignatureNames(res, false)
42+
all, err := signatureDetailsListFromHeaders(res.Header)
4543
if err != nil {
4644
return nil, err
4745
}
48-
return detailsByTag(names, tag, func(name string) (*MessageDetails, error) {
49-
return ResponseDetails(name, res)
50-
})
46+
return detailsByTag(all, tag)
5147
}
5248

5349
// RequestDetailsListByTag returns MessageDetails for every Signature whose
@@ -57,13 +53,11 @@ func RequestDetailsListByTag(req *http.Request, tag string) ([]*MessageDetails,
5753
if req == nil {
5854
return nil, fmt.Errorf("nil request")
5955
}
60-
names, err := RequestSignatureNames(req, false)
56+
all, err := signatureDetailsListFromHeaders(req.Header)
6157
if err != nil {
6258
return nil, err
6359
}
64-
return detailsListByTag(names, tag, func(name string) (*MessageDetails, error) {
65-
return RequestDetails(name, req)
66-
})
60+
return detailsListByTag(all, tag), nil
6761
}
6862

6963
// ResponseDetailsListByTag returns MessageDetails for every Signature whose
@@ -73,37 +67,27 @@ func ResponseDetailsListByTag(res *http.Response, tag string) ([]*MessageDetails
7367
if res == nil {
7468
return nil, fmt.Errorf("nil response")
7569
}
76-
names, err := ResponseSignatureNames(res, false)
70+
all, err := signatureDetailsListFromHeaders(res.Header)
7771
if err != nil {
7872
return nil, err
7973
}
80-
return detailsListByTag(names, tag, func(name string) (*MessageDetails, error) {
81-
return ResponseDetails(name, res)
82-
})
74+
return detailsListByTag(all, tag), nil
8375
}
8476

85-
func detailsListByTag(names []string, tag string, detailsFn func(string) (*MessageDetails, error)) ([]*MessageDetails, error) {
77+
func detailsListByTag(all []*MessageDetails, tag string) []*MessageDetails {
8678
var found []*MessageDetails
87-
for _, name := range names {
88-
details, err := detailsFn(name)
89-
if err != nil {
90-
return nil, fmt.Errorf("details for %q: %w", name, err)
91-
}
79+
for _, details := range all {
9280
if details.Tag != nil && *details.Tag == tag {
9381
found = append(found, details)
9482
}
9583
}
96-
return found, nil
84+
return found
9785
}
9886

99-
func detailsByTag(names []string, tag string, detailsFn func(string) (*MessageDetails, error)) (*MessageDetails, error) {
87+
func detailsByTag(all []*MessageDetails, tag string) (*MessageDetails, error) {
10088
var match *MessageDetails
10189
n := 0
102-
for _, name := range names {
103-
details, err := detailsFn(name)
104-
if err != nil {
105-
return nil, fmt.Errorf("details for %q: %w", name, err)
106-
}
90+
for _, details := range all {
10791
if details.Tag == nil || *details.Tag != tag {
10892
continue
10993
}

0 commit comments

Comments
 (0)