Skip to content

Commit 5379d04

Browse files
authored
fix(W-17812967): Heroku-cli-command: Header overflow (#159)
* fix(W-17812967): Heroku-cli-command: Header overflow * Adjusted the Request-Id header limit to 7k and updated unit tests
1 parent 6968767 commit 5379d04

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

src/api-client.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,20 @@ export class APIClient {
176176

177177
static async request<T>(url: string, opts: APIClient.Options = {}, retries = 3): Promise<APIHTTPClient<T>> {
178178
opts.headers = opts.headers || {}
179-
opts.headers[requestIdHeader] = RequestId.create() && RequestId.headerValue
179+
const currentRequestId = RequestId.create() && RequestId.headerValue
180+
181+
// Accumulation of requestIds in the header
182+
// causes a header overflow error. Headers have been
183+
// observed to be larger than 8k (Node default max)
184+
// in long running poll operations such as pg:wait
185+
// We limit the Request-Id header to 7k to allow some
186+
// room fo other headers.
187+
if (Buffer.from(currentRequestId).byteLength > 1024 * 7) {
188+
RequestId.empty()
189+
opts.headers[requestIdHeader] = RequestId.create()
190+
} else {
191+
opts.headers[requestIdHeader] = currentRequestId
192+
}
180193

181194
if (!Object.keys(opts.headers).some(h => h.toLowerCase() === 'authorization')) {
182195
opts.headers.authorization = `Bearer ${self.auth}`

test/api-client.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,5 +635,32 @@ describe('api_client', () => {
635635

636636
expect(secondRequest.getHeader(requestIdHeader)).to.deep.equal('second-random-uuid,first-existing-request-id,second-existing-request-id,random-uuid')
637637
})
638+
639+
test
640+
.it('resets request id when it exceeds 7KB', async ctx => {
641+
const cmd = new Command([], ctx.config)
642+
// Create a large request ID that exceeds 7KB
643+
const largeRequestId = 'x'.repeat(1024 * 8)
644+
Reflect.set(RequestId, 'ids', [largeRequestId])
645+
646+
generateStub.returns('new-uuid-after-reset')
647+
api = nock('https://api.heroku.com').get('/apps').reply(200, [{name: 'myapp'}])
648+
649+
const {request} = await cmd.heroku.get('/apps')
650+
expect(request.getHeader(requestIdHeader)).to.deep.equal(['new-uuid-after-reset'])
651+
})
652+
653+
test
654+
.it('keeps existing request id when under 7KB', async ctx => {
655+
const cmd = new Command([], ctx.config)
656+
// Create a request ID that's under 7KB
657+
const normalRequestId = 'normal-request-id'
658+
Reflect.set(RequestId, 'ids', [normalRequestId])
659+
660+
api = nock('https://api.heroku.com').get('/apps').reply(200, [{name: 'myapp'}])
661+
662+
const {request} = await cmd.heroku.get('/apps')
663+
expect(request.getHeader(requestIdHeader)).to.deep.equal(',normal-request-id')
664+
})
638665
})
639666
})

0 commit comments

Comments
 (0)