Skip to content

feat(enhancement): add resetter interface, call reset appropriately, improve code, and test#1124

Merged
jeevatkm merged 1 commit into
v3from
add-resetter-interface-and-improvements
Mar 15, 2026
Merged

feat(enhancement): add resetter interface, call reset appropriately, improve code, and test#1124
jeevatkm merged 1 commit into
v3from
add-resetter-interface-and-improvements

Conversation

@jeevatkm

Copy link
Copy Markdown
Member

No description provided.

@jeevatkm jeevatkm added this to the v3.0.0 Milestone milestone Mar 14, 2026
@jeevatkm jeevatkm requested a review from Copilot March 14, 2026 23:37
@jeevatkm jeevatkm self-assigned this Mar 14, 2026
@jeevatkm jeevatkm added enhancement v3 For resty v3 labels Mar 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances streaming/decoding utilities by introducing a reset-capable interface for readers, tightening decoder behavior to avoid infinite streams, and expanding test coverage around JSON/XML decoding and pooled decompressors.

Changes:

  • Add a decode object-count limit for JSON/XML decoding to prevent unbounded streams.
  • Introduce a resetter interface and implement Reset() for limitReadCloser; broaden nopReadCloser to support resetting more underlying reader types.
  • Expand/organize stream-related tests, including new decode scenarios and reset behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
stream.go Adds decode limits, introduces resetter + limitReadCloser.Reset, and updates nopReadCloser reset behavior.
stream_test.go Refactors JSON decode tests into subtests, adds XML decode tests, adds resetter test, and adds decode-limit tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread stream.go
Comment on lines 105 to 116
func decodeXML(r io.Reader, v any) error {
dec := xml.NewDecoder(r)
for {
if err := dec.Decode(v); err == io.EOF {
break
} else if err != nil {
for range maxDecodeObjects {
if err := dec.Decode(v); err != nil {
if err == io.EOF {
return nil
}
return err
}
}
return nil
return fmt.Errorf("resty: XML decode exceeded %d objects without EOF", maxDecodeObjects)
}
Comment thread stream.go
Comment on lines 305 to 320
func (l *limitReadCloser) Read(p []byte) (n int, err error) {
if l.l == 0 {
switch {
case l.l <= unlimitedRead:
n, err = l.r.Read(p)
l.t += int64(n)
l.f(l.t)
return n, err
default:
if l.t >= l.l {
return 0, ErrReadExceedsThresholdLimit
}
n, err = l.r.Read(p)
l.t += int64(n)
l.f(l.t)
return n, err
}
Comment thread stream_test.go
Comment on lines +99 to +117
t.Run("exceeds maxDecodeObjects limit", func(t *testing.T) {
// Build a reader that returns maxDecodeObjects+1 objects without EOF
// by using a custom reader that signals no EOF until asked enough times.
// Simplest approach: patch the limit via the loop by creating a reader
// backed by a sufficient number of elements. Since maxDecodeObjects is 1M,
// we instead test the boundary by constructing exactly that many elements
// with a streaming reader built from io.MultiReader.
elem := []byte(`{"key": "value"}`)
readers := make([]io.Reader, maxDecodeObjects+1)
for i := range readers {
readers[i] = bytes.NewReader(elem)
}
r := io.MultiReader(readers...)

var v map[string]any
err := decodeJSON(r, &v)
assertNotNil(t, err)
assertEqual(t, "resty: JSON decode exceeded 1000000 objects without EOF", err.Error())
})
Comment thread stream_test.go
Comment on lines +568 to +586
t.Run("exceeds maxDecodeObjects limit", func(t *testing.T) {
// Build a reader that returns maxDecodeObjects+1 objects without EOF
// by using a custom reader that signals no EOF until asked enough times.
// Simplest approach: patch the limit via the loop by creating a reader
// backed by a sufficient number of elements. Since maxDecodeObjects is 1M,
// we instead test the boundary by constructing exactly that many elements
// with a streaming reader built from io.MultiReader.
elem := []byte(`<Item><name>x</name></Item>`)
readers := make([]io.Reader, maxDecodeObjects+1)
for i := range readers {
readers[i] = bytes.NewReader(elem)
}
r := io.MultiReader(readers...)

var v Item
err := decodeXML(r, &v)
assertNotNil(t, err)
assertEqual(t, "resty: XML decode exceeded 1000000 objects without EOF", err.Error())
})
Comment thread stream.go
Comment on lines 88 to 99
func doDecodeJSON(dec *json.Decoder, v any) error {
// Decode all JSON objects in the data
for {
if err := dec.Decode(v); err == io.EOF {
break
} else if err != nil {
for range maxDecodeObjects {
if err := dec.Decode(v); err != nil {
if err == io.EOF {
return nil
}
return err
}
}
return nil
return fmt.Errorf("resty: JSON decode exceeded %d objects without EOF", maxDecodeObjects)
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot for range starts from 0 similar to for loop

Copilot AI commented Mar 15, 2026

Copy link
Copy Markdown

@jeevatkm I've opened a new pull request, #1125, to work on those changes. Once the pull request is ready, I'll request review from you.

@codecov

codecov Bot commented Mar 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.74%. Comparing base (30421b5) to head (614260f).
⚠️ Report is 1 commits behind head on v3.

Additional details and impacted files
@@            Coverage Diff             @@
##               v3    #1124      +/-   ##
==========================================
- Coverage   99.81%   99.74%   -0.08%     
==========================================
  Files          19       19              
  Lines        3838     3850      +12     
==========================================
+ Hits         3831     3840       +9     
- Misses          4        6       +2     
- Partials        3        4       +1     
Flag Coverage Δ
unittests 99.74% <100.00%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jeevatkm jeevatkm force-pushed the add-resetter-interface-and-improvements branch from 0e3b358 to 614260f Compare March 15, 2026 01:28
@jeevatkm jeevatkm merged commit 8c57f2c into v3 Mar 15, 2026
2 checks passed
@jeevatkm jeevatkm deleted the add-resetter-interface-and-improvements branch March 15, 2026 01:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement v3 For resty v3

Development

Successfully merging this pull request may close these issues.

3 participants