mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-29 23:54:24 +00:00
fix: preserve axios default Accept header when setting User-Agent (#7820)
Assigning `defaults.headers.common = { 'User-Agent': ... }` replaced the
entire common headers object, nuking axios's built-in default:
Accept: application/json, text/plain, */*
This caused servers relying on content-negotiation to receive requests
with no Accept header. Fix by extending the existing object with a
property assignment instead.
Add regression tests for both electron and CLI axios instances verifying
that Accept is preserved and User-Agent is set correctly.
Co-authored-by: Pragadesh-45 <temporaryg7904@gmail.com>
This commit is contained in:
@@ -92,10 +92,11 @@ function makeAxiosInstance({
|
||||
headers: {}
|
||||
});
|
||||
|
||||
// Set User-Agent manually (using transformRequest to delete headers instead)
|
||||
instance.defaults.headers.common = {
|
||||
'User-Agent': `bruno-runtime/${CLI_VERSION}`
|
||||
};
|
||||
// Extend common headers with User-Agent rather than replacing the object.
|
||||
// axios.create() preserves defaults.headers.common = { Accept: 'application/json, text/plain, */*' }.
|
||||
// Assigning a new object (= { 'User-Agent': ... }) would nuke that default, causing servers that
|
||||
// rely on content-negotiation to receive requests with no Accept header.
|
||||
instance.defaults.headers.common['User-Agent'] = `bruno-runtime/${CLI_VERSION}`;
|
||||
|
||||
instance.interceptors.request.use((config) => {
|
||||
config.headers['request-start-time'] = Date.now();
|
||||
|
||||
37
packages/bruno-cli/tests/utils/axios-instance.spec.js
Normal file
37
packages/bruno-cli/tests/utils/axios-instance.spec.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const { describe, it, expect } = require('@jest/globals');
|
||||
const { makeAxiosInstance } = require('../../src/utils/axios-instance');
|
||||
|
||||
function createStubAdapter() {
|
||||
let capturedConfig = null;
|
||||
|
||||
const adapter = (config) => {
|
||||
capturedConfig = config;
|
||||
return Promise.resolve({ data: {}, status: 200, statusText: 'OK', headers: {}, config });
|
||||
};
|
||||
|
||||
adapter.getConfig = () => capturedConfig;
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
describe('makeAxiosInstance', () => {
|
||||
it('setting User-Agent does not clobber the axios default Accept header', async () => {
|
||||
const stubAdapter = createStubAdapter();
|
||||
const instance = makeAxiosInstance();
|
||||
|
||||
await instance({ url: 'https://api.example.com/test', method: 'get', adapter: stubAdapter });
|
||||
|
||||
// axios.create() sets Accept by default; assigning a new object to defaults.headers.common
|
||||
// would nuke it. Guard against that regression.
|
||||
expect(stubAdapter.getConfig().headers['Accept']).toMatch(/application\/json/);
|
||||
});
|
||||
|
||||
it('sets User-Agent header to bruno-runtime version', async () => {
|
||||
const stubAdapter = createStubAdapter();
|
||||
const instance = makeAxiosInstance();
|
||||
|
||||
await instance({ url: 'https://api.example.com/test', method: 'get', adapter: stubAdapter });
|
||||
|
||||
expect(stubAdapter.getConfig().headers['User-Agent']).toMatch(/^bruno-runtime\//);
|
||||
});
|
||||
});
|
||||
@@ -99,10 +99,11 @@ function makeAxiosInstance({
|
||||
headers: {}
|
||||
});
|
||||
|
||||
// Set User-Agent manually (using transformRequest to delete headers instead)
|
||||
instance.defaults.headers.common = {
|
||||
'User-Agent': `bruno-runtime/${version}`
|
||||
};
|
||||
// Extend common headers with User-Agent rather than replacing the object.
|
||||
// axios.create() preserves defaults.headers.common = { Accept: 'application/json, text/plain, */*' }.
|
||||
// Assigning a new object (= { 'User-Agent': ... }) would nuke that default, causing servers that
|
||||
// rely on content-negotiation to receive requests with no Accept header.
|
||||
instance.defaults.headers.common['User-Agent'] = `bruno-runtime/${version}`;
|
||||
|
||||
instance.interceptors.request.use(async (config) => {
|
||||
const url = URL.parse(config.url);
|
||||
|
||||
@@ -51,6 +51,28 @@ function createStubAdapter() {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
describe('axios-instance: default headers', () => {
|
||||
test('setting User-Agent does not clobber the axios default Accept header', async () => {
|
||||
const stubAdapter = createStubAdapter();
|
||||
const instance = makeAxiosInstance();
|
||||
|
||||
await instance({ url: 'https://api.example.com/test', method: 'get', adapter: stubAdapter });
|
||||
|
||||
// axios.create() sets Accept by default; assigning a new object to defaults.headers.common
|
||||
// would nuke it. Guard against that regression.
|
||||
expect(stubAdapter.getConfig().headers['Accept']).toMatch(/application\/json/);
|
||||
});
|
||||
|
||||
test('sets User-Agent header to bruno-runtime version', async () => {
|
||||
const stubAdapter = createStubAdapter();
|
||||
const instance = makeAxiosInstance();
|
||||
|
||||
await instance({ url: 'https://api.example.com/test', method: 'get', adapter: stubAdapter });
|
||||
|
||||
expect(stubAdapter.getConfig().headers['User-Agent']).toMatch(/^bruno-runtime\//);
|
||||
});
|
||||
});
|
||||
|
||||
describe('axios-instance: DNS lookup behavior (GitHub #7343)', () => {
|
||||
let axiosInstance;
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
meta {
|
||||
name: echo default request headers
|
||||
type: http
|
||||
seq: 14
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{echo-host}}
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
|
||||
tests {
|
||||
test("sends Accept header with application/json by default", function() {
|
||||
// The echo server reflects request headers back as response headers.
|
||||
// Verifies that axios's default Accept header is not clobbered when
|
||||
// setting User-Agent (regression for: defaults.headers.common object replacement).
|
||||
const accept = res.getHeaders()["accept"];
|
||||
expect(accept).to.be.a("string");
|
||||
expect(accept).to.include("application/json");
|
||||
});
|
||||
|
||||
test("sends User-Agent header with bruno-runtime prefix", function() {
|
||||
const userAgent = res.getHeaders()["user-agent"];
|
||||
expect(userAgent).to.be.a("string");
|
||||
expect(userAgent).to.match(/^bruno-runtime\//);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user