@webqit/fetch-plus 0.1.30 → 0.1.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "homepage": "https://fetch-plus.netlify.app/",
13
13
  "icon": "https://webqit.io/icon.svg",
14
- "version": "0.1.30",
14
+ "version": "0.1.31",
15
15
  "license": "MIT",
16
16
  "repository": {
17
17
  "type": "git",
@@ -111,34 +111,55 @@ export class HeadersPlus extends Headers {
111
111
 
112
112
  // Parse "Range" request header?
113
113
  if (/^Range$/i.test(name) && structured) {
114
+ const _after = (str, prefix) => str.includes(prefix) ? str.split(prefix)[1] : str;
115
+
114
116
  value = !value ? [] : _after(value, 'bytes=').split(',').map((rangeStr) => {
115
- const range = rangeStr.trim().split('-').map((s) => s ? parseInt(s, 10) : null);
117
+ if (!rangeStr.includes('-')) rangeStr = '-'; // -> [null, null];
118
+
119
+ // "0-499" -> [0, 499] | "500-" -> [500, null] | "-500" -> [null, 500]
120
+ const range = rangeStr.trim().split('-').map((s) => (s.length > 0 ? parseInt(s, 10) : null));
121
+
116
122
  range.resolveAgainst = (totalLength) => {
117
- const offsets = [...range];
118
- if (typeof offsets[1] !== 'number') {
123
+ const offsets = [...range]; // Clone the [start, end] array
124
+
125
+ // 1. Handle Suffix Ranges (e.g., bytes=-500)
126
+ if (offsets[0] === null && offsets[1] !== null) {
127
+ offsets[0] = Math.max(0, totalLength - offsets[1]);
119
128
  offsets[1] = totalLength - 1;
120
- } else {
121
- offsets[1] = Math.min(offsets[1], totalLength) - 1;
122
129
  }
123
- if (typeof offsets[0] !== 'number') {
124
- offsets[0] = offsets[1] ? totalLength - offsets[1] - 1 : 0;
130
+ // 2. Handle Open-ended Ranges (e.g., bytes=500-)
131
+ else if (offsets[0] !== null && offsets[1] === null) {
132
+ offsets[1] = totalLength - 1;
133
+ }
134
+ // 3. Handle Normal Ranges (e.g., bytes=0-499)
135
+ else if (offsets[0] !== null && offsets[1] !== null) {
136
+ offsets[1] = Math.min(offsets[1], totalLength - 1);
125
137
  }
126
- return offsets;
138
+
139
+ return offsets; // Returns [start, end] where both are inclusive indices
127
140
  };
141
+
128
142
  range.canResolveAgainst = (currentStart, totalLength) => {
129
- const offsets = [
130
- typeof range[0] === 'number' ? range[0] : currentStart,
131
- typeof range[1] === 'number' ? range[1] : totalLength - 1
132
- ];
133
- // Start higher than end or vice versa?
134
- if (offsets[0] > offsets[1]) return false;
135
- // Stretching beyond valid start/end?
136
- if (offsets[0] < currentStart || offsets[1] >= totalLength) return false;
143
+ const resolved = range.resolveAgainst(totalLength);
144
+
145
+ // 1. Check for NaN or unparsed nulls (invalid formats)
146
+ if (Number.isNaN(resolved[0]) || Number.isNaN(resolved[1]) || resolved[0] === null || resolved[1] === null) {
147
+ return false;
148
+ }
149
+
150
+ // 2. Validate start (end is always clamped):
151
+ // - Range cannot be inverted (start > end)
152
+ // - Start cannot be beyond file length
153
+ // - Start cannot be below file start
154
+ if (resolved[0] > resolved[1] || resolved[0] >= totalLength || resolved[0] < currentStart) {
155
+ return false;
156
+ }
157
+
137
158
  return true;
138
159
  };
139
- range.toString = () => {
140
- return rangeStr;
141
- };
160
+
161
+ range.toString = () => rangeStr;
162
+
142
163
  return range;
143
164
  });
144
165
  }
@@ -86,12 +86,12 @@ describe('Core API Tests', function () {
86
86
  // "range[0] < currentStart" is check.
87
87
  // If currentStart is 500, range 0-499 is NOT valid
88
88
 
89
- expect(range.canResolveAgainst(0, 400)).to.be.false; // range end > total
89
+ expect(range.canResolveAgainst(0, 400)).to.be.true; // range end > total, but clamped
90
90
 
91
91
  // Render
92
- // range is [0, 499]
92
+ // range is [0, 500] -> 501 bytes
93
93
  const rendered = range.resolveAgainst(1000);
94
- expect(rendered).to.deep.equal([0, 499]);
94
+ expect(rendered).to.deep.equal([0, 500]);
95
95
  });
96
96
 
97
97
  it('should handle open-ended ranges', function () {