XHR Adapter
The XHR adapter uses the XMLHttpRequest API (Level 2) to make HTTP requests from the browser. Its main advantage over the Fetch adapter is built-in upload and download progress events, making it the preferred choice when progress tracking is required in a browser environment.
import rezo from 'rezo/adapters/xhr'; Import and Setup
import rezo, {
Rezo,
RezoError,
RezoHeaders,
RezoFormData
} from 'rezo/adapters/xhr';
// Default instance
const { data } = await rezo.get('https://api.example.com/users');
// Custom instance
const client = new Rezo({
baseURL: 'https://api.example.com',
timeout: 10000
}); Upload Progress
The XHR adapter is the only browser adapter that provides real upload progress events via XMLHttpRequest.upload.onprogress:
const client = new Rezo({
hooks: {
onUploadProgress: [({ loaded, total, percent }) => {
console.log(`Uploaded: ${percent.toFixed(1)}%`);
updateProgressBar(percent);
}]
}
});
const form = new RezoFormData();
form.append('video', fileInput.files[0]);
await client.upload('https://api.example.com/upload', form); This is particularly useful for large file uploads where users need visual feedback. The Fetch adapter does not support upload progress.
Download Progress
Download progress is also tracked through XHR events:
const client = new Rezo({
hooks: {
onDownloadProgress: [({ loaded, total, percent }) => {
if (total) {
console.log(`Downloaded: ${percent.toFixed(1)}%`);
} else {
console.log(`Downloaded: ${(loaded / 1024).toFixed(0)} KB`);
}
}]
}
});
const { data } = await client.get('https://api.example.com/large-dataset'); Response Type Configuration
The adapter maps Rezo’s responseType to XMLHttpRequest.responseType:
// JSON (default) -- automatically parsed
const { data } = await rezo.get('https://api.example.com/users');
// Raw text
const { data: html } = await rezo.get('https://example.com', {
responseType: 'text'
});
// ArrayBuffer for binary data
const { data: buffer } = await rezo.get('https://example.com/image.png', {
responseType: 'arraybuffer'
});
// Blob for file handling in the browser
const { data: blob } = await rezo.get('https://example.com/document.pdf', {
responseType: 'blob'
});
// Create a download link from the blob
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'document.pdf';
a.click();
URL.revokeObjectURL(url); Cross-Origin Credentials
The adapter supports withCredentials for sending cookies and authorization headers with cross-origin requests:
const client = new Rezo({
withCredentials: true
});
// Cookies and auth headers are sent with cross-origin requests
const { data } = await client.get('https://api.different-domain.com/data'); This maps directly to XMLHttpRequest.withCredentials. The server must include appropriate CORS headers (Access-Control-Allow-Credentials: true) for this to work.
Abort Signal Support
Cancel requests using an AbortController:
const controller = new AbortController();
const promise = rezo.get('https://api.example.com/slow-endpoint', {
signal: controller.signal
});
// Cancel after 2 seconds
setTimeout(() => controller.abort(), 2000);
try {
const { data } = await promise;
} catch (error) {
if (error.code === 'ECONNABORTED') {
console.log('Request cancelled');
}
} The adapter also supports Rezo’s built-in timeout, which creates an internal abort signal:
const { data } = await rezo.get('https://slow-api.example.com/data', {
timeout: 5000
}); Retry Logic
Same retry mechanism as all other adapters:
const { data } = await rezo.get('https://flaky-api.example.com/data', {
retry: {
limit: 3,
delay: 1000,
backoff: 'exponential',
statusCodes: [429, 500, 502, 503]
}
}); Rate Limit Wait
const client = new Rezo({ rateLimitWait: true });
const { data } = await client.get('https://rate-limited-api.com/data');
// Automatically waits and retries on 429 + Retry-After Response Caching
const client = new Rezo({
cache: {
maxAge: 60000,
maxEntries: 100
}
});
const { data } = await client.get('https://api.example.com/config'); Form Data Uploads
The XHR adapter works with both Rezo’s RezoFormData and the browser’s native FormData:
// Using RezoFormData
const rezoForm = new RezoFormData();
rezoForm.append('name', 'report.xlsx');
rezoForm.append('file', fileInput.files[0]);
await rezo.post('https://api.example.com/upload', rezoForm);
// Using native FormData (also works)
const nativeForm = new FormData();
nativeForm.append('name', 'report.xlsx');
nativeForm.append('file', fileInput.files[0]);
await rezo.post('https://api.example.com/upload', nativeForm); Cookie Handling
In browser environments, cookies are managed by the browser itself. The XHR adapter does not use a cookie jar. Instead, cookies are sent and received according to browser rules:
- Same-origin requests include cookies automatically
- Cross-origin requests require
withCredentials: trueand server CORS headers httpOnlycookies are not accessible to JavaScript
// Same-origin: cookies are sent automatically
const { data } = await rezo.get('/api/profile');
// Cross-origin: requires withCredentials
const { data } = await rezo.get('https://api.other-domain.com/profile', {
withCredentials: true
}); Debug Mode
const { data } = await rezo.get('https://api.example.com/users', {
debug: true
});
// [Rezo Debug] GET https://api.example.com/users
// [Rezo Debug] Adapter: xhr
// [Rezo Debug] Response: 200 OK (112.45ms)
// [Rezo Debug] Response Headers: { ... } Limitations
| Feature | Status | Reason |
|---|---|---|
| Proxy support | Not available | Browser security restrictions |
| Response streaming | Not available | XHR buffers the entire response body |
| HTTP/2 configuration | Not available | Browser handles protocol negotiation |
| DNS caching | Not available | Browser handles DNS resolution |
| TLS configuration | Not available | Browser handles TLS |
| Cookie jar | Not available | Browser controls cookie storage |
| Compression control | Not available | Browser handles Accept-Encoding |
The biggest limitation compared to the Fetch adapter is the lack of response streaming. XHR buffers the entire response in memory before making it available, which can be problematic for very large responses.
Browser Compatibility
The XHR adapter requires XMLHttpRequest Level 2, which is supported by:
- Chrome 31+
- Firefox 20+
- Safari 7+
- Edge 12+
- IE 11 (partial — no
responseType: 'json') - Opera 18+
For IE11, the adapter automatically falls back to manual JSON parsing when responseType: 'json' is not supported.
When to Use This Adapter
The XHR adapter is the right choice when:
- You need upload progress events in the browser (Fetch does not support this)
- You need to support IE11 or older browsers
- You need
responseType: 'blob'for in-browser file handling - You want
withCredentialssupport for CORS requests with cookies
For modern browsers where upload progress is not needed, the Fetch adapter is lighter. For server-side Node.js, use the HTTP adapter.