Skip to content

Commit 55b3689

Browse files
authored
Merge pull request #103 from MattCCC/response-parser
Add custom response parser option and enhance binary data handling
2 parents c2d0c3b + f7010c8 commit 55b3689

17 files changed

Lines changed: 159 additions & 105 deletions

README.md

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ You can also use all native [`fetch()` settings](https://developer.mozilla.org/e
572572
| refetchOnReconnect | `boolean` | `false` | When set to `true`, automatically revalidates (refetches) data when the browser regains internet connectivity after being offline. **This uses background revalidation to silently update data** without showing loading states to users. Helps ensure your application displays fresh data after network interruptions. Works by listening to the browser's `online` event. |
573573
| logger | `Logger` | `null` | You can additionally specify logger object with your custom logger to automatically log the errors to the console. It should contain at least `error` and `warn` functions. |
574574
| fetcher | `CustomFetcher` | `undefined` | A custom fetcher async function. By default, the native `fetch()` is used. If you use your own fetcher, default response parsing e.g. `await response.json()` call will be skipped. Your fetcher should return response object / data directly. |
575+
| parser | `(response: Response) => Promise<any>` | `undefined` | A custom response parser function. When provided, it replaces the built-in content-type based parsing entirely. Receives the raw `Response` object and should return the parsed data. Useful for handling custom formats like XML, CSV, or proprietary data. Can be set globally or per-request. |
575576

576577
> 📋 **Additional Settings Available:**
577578
> The table above shows the most commonly used settings. Many more advanced configuration options are available and documented in their respective sections below, including:
@@ -1753,23 +1754,65 @@ If the header is an HTTP-date, the delay will be calculated as the difference be
17531754
<summary><span style="cursor:pointer">Click to expand</span></summary>
17541755
<br>
17551756
1756-
The `fetchff` plugin automatically handles response data transformation for any instance of `Response` returned by the `fetch()` (or a custom `fetcher`) based on the `Content-Type` header, ensuring that data is parsed correctly according to its format.
1757+
The `fetchff` plugin automatically handles response data transformation for any instance of `Response` returned by the `fetch()` (or a custom `fetcher`) based on the `Content-Type` header, ensuring that data is parsed correctly according to its format. It returns functions like `response.json()` that can be called idempotently without throwing errors or consuming the underlying stream multiple times. You can also use `parser` option to fully control returned response (useful for response streaming).
17571758
17581759
### **How It Works**
17591760
17601761
- **JSON (`application/json`):** Parses the response as JSON.
17611762
- **Form Data (`multipart/form-data`):** Parses the response as `FormData`.
1762-
- **Binary Data (`application/octet-stream`):** Parses the response as a `Blob`.
1763+
- **Binary Data (`application/octet-stream`, images, video, audio, pdf, zip):** Parses the response as an `ArrayBuffer`. Use `response.blob()` to get a `Blob`, or `response.bytes()` to get a `Uint8Array`.
17631764
- **URL-encoded Form Data (`application/x-www-form-urlencoded`):** Parses the response as `FormData`.
17641765
- **Text (`text/*`):** Parses the response as plain text.
1766+
- **Other/Custom types (XML, CSV, etc.):** Returns raw text. Use the `parser` option for custom parsing.
17651767
1766-
If the `Content-Type` header is missing or not recognized, the plugin defaults to attempting JSON parsing. If that fails, it will try to parse the response as text.
1768+
If the `Content-Type` header is missing or not recognized, the plugin defaults to returning text. If the text looks like JSON (starts with `{` or `[`), it will be auto-parsed as JSON.
17671769
17681770
This approach ensures that the `fetchff` plugin can handle a variety of response formats, providing a flexible and reliable method for processing data from API requests.
17691771
17701772
> ⚠️ **When using in Node.js:**
17711773
> In Node.js, using FormData, Blob, or ReadableStream may require additional polyfills or will not work unless your fetch polyfill supports them.
17721774
1775+
### Custom `parser` Option
1776+
1777+
You can provide a custom `parser` function to override the default content-type based parsing. This is useful for formats like XML, CSV, or any proprietary format. The `parser` can be set globally (via `createApiFetcher()` or `setDefaultConfig()`) or per-request.
1778+
1779+
```typescript
1780+
import { fetchf } from 'fetchff';
1781+
1782+
// Example: Parse XML responses
1783+
const { data } = await fetchf('/api/data.xml', {
1784+
async parser(response) {
1785+
const text = await response.text();
1786+
return new DOMParser().parseFromString(text, 'application/xml');
1787+
},
1788+
});
1789+
1790+
// Example: Parse CSV responses
1791+
const { data: csvData } = await fetchf('/api/report.csv', {
1792+
async parser(response) {
1793+
const text = await response.text();
1794+
return text.split('\n').map((row) => row.split(','));
1795+
},
1796+
});
1797+
```
1798+
1799+
You can also set it globally:
1800+
1801+
```typescript
1802+
import { createApiFetcher } from 'fetchff';
1803+
1804+
const api = createApiFetcher({
1805+
apiUrl: 'https://example.com/api',
1806+
parser: async (response) => {
1807+
const text = await response.text();
1808+
return new DOMParser().parseFromString(text, 'application/xml');
1809+
},
1810+
endpoints: {
1811+
getReport: { url: '/report' },
1812+
},
1813+
});
1814+
```
1815+
17731816
### `onResponse` Interceptor
17741817
17751818
You can use the `onResponse` interceptor to customize how the response is handled before it reaches your application. This interceptor gives you access to the raw `Response` object, allowing you to transform the data or modify the response behavior based on your needs.

0 commit comments

Comments
 (0)