Describe the bug
I'm connecting with nodejs/puppeteer to a self-hosted browserless docker image. When the queue is full, a 429 is sent back to nodejs. However, the 429 response is not properly received and triggers a Websocket error "invalid header value char" on nodejs side:
ERROR ErrorEvent {
[Symbol(kTarget)]: WebSocket {
_events: [Object: null prototype] {
open: [Function],
error: [Function]
},
_eventsCount: 2,
_maxListeners: undefined,
_binaryType: 'nodebuffer',
_closeCode: 1006,
_closeFrameReceived: false,
_closeFrameSent: false,
_closeMessage: <Buffer >,
_closeTimer: null,
_extensions: {},
_paused: false,
_protocol: '',
_readyState: 3,
_receiver: null,
_sender: null,
_socket: null,
_bufferedAmount: 0,
_isServer: false,
_redirects: 0,
_url: 'ws://browserless:3000',
_originalIpc: false,
_originalSecure: false,
_originalHostOrSocketPath: 'browserless:3000',
_req: null,
[Symbol(kCapture)]: false
},
[Symbol(kType)]: 'error',
[Symbol(kError)]: Error: Parse Error: Invalid header value char
at Socket.socketOnData (node:_http_client:534:22)
at Socket.emit (node:events:513:28)
at Socket.emit (node:domain:489:12)
at addChunk (node:internal/streams/readable:324:12)
at readableAddChunk (node:internal/streams/readable:297:9)
at Readable.push (node:internal/streams/readable:234:10)
at TCP.onStreamRead (node:internal/stream_base_commons:190:23) {
bytesParsed: 70,
code: 'HPE_INVALID_HEADER_TOKEN',
reason: 'Invalid header value char',
rawPacket: <Buffer 48 54 54 50 2f 31 2e 31 20 34 32 39 20 54 6f 6f 20 4d 61 6e 79 20 52 65 71 75 65 73 74 73 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 65 78 74 2f ... 107 more bytes>
},
[Symbol(kMessage)]: 'Parse Error: Invalid header value char'
}
My assumption is that something in the HTTP-response compiled within rejectSocket is malformed and is now rejected by nodejs/Websocket in a recent version. Could be the header Content-Encoding
which provides "UTF-8" as value. However, this is not a valid value for content encoding (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding).
To Reproduce
docker image: image: browserless/chrome:[email protected]:ca9c1a56ff88ba91c3aac908713cfe92f4e308c941a64e408d00d26bf1de036a
Consumer:
nodejs: node:[email protected]:32b920f09c28e3b27c9c5620d843aab0d2bb2f46e7d0505686626ba20cb5da0e
puppeteer-core: 19.1.0
Consumer code (shortened for brevity):
router.use('/pdf', async (req, res) => {
let browser = null
try {
browser = await puppeteer.connect({browserWSEndpoint})
const context = await browser.createIncognitoBrowserContext()
const page = await context.newPage()
page.setUserAgent('Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0')
await page.goto(url)
const pdf = await page.pdf()
browser.disconnect()
res.contentType('application/pdf')
res.send(pdf)
} catch (error) {
if (browser) {
browser.disconnect()
}
let errorMessage = null
if (error.error) {
// error is a WebScocket ErrorEvent Object which contains an error property
errorMessage = error.error.toString()
res.status(503)
} else {
errorMessage = error.toString()
res.status(500)
}
console.error(error)
res.contentType('application/json')
res.send({ error: errorMessage })
}
})
Steps to reproduce the behavior:
Expected behavior
Expected to receive a proper HTTP-response with status code 429
Just noticed I was running on an old version of browserless. Upgraded to 1.56.0-puppeteer-18.0.5 and now the error seems to match with what I expected:
ERROR ErrorEvent {
[Symbol(kTarget)]: WebSocket {
_events: [Object: null prototype] {
open: [Function],
error: [Function]
},
_eventsCount: 2,
_maxListeners: undefined,
_binaryType: 'nodebuffer',
_closeCode: 1006,
_closeFrameReceived: false,
_closeFrameSent: false,
_closeMessage: <Buffer >,
_closeTimer: null,
_extensions: {},
_paused: false,
_protocol: '',
_readyState: 3,
_receiver: null,
_sender: null,
_socket: null,
_bufferedAmount: 0,
_isServer: false,
_redirects: 0,
_url: 'ws://browserless:3000',
_originalIpc: false,
_originalSecure: false,
_originalHostOrSocketPath: 'browserless:3000',
_req: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 4,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: false,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: 0,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: [Socket],
_header: 'GET / HTTP/1.1\r\n' +
'User-Agent: Puppeteer 19.1.0\r\n' +
'Sec-WebSocket-Version: 13\r\n' +
'Sec-WebSocket-Key: ORIpk17BKH1vooGr3yNDcQ==\r\n' +
'Connection: Upgrade\r\n' +
'Upgrade: websocket\r\n' +
'Host: browserless:3000\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: undefined,
socketPath: undefined,
method: 'GET',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
path: '/',
_ended: false,
res: [IncomingMessage],
aborted: true,
timeoutCb: null,
upgradeOrConnect: false,
parser: [HTTPParser],
maxHeadersCount: null,
reusedSocket: false,
host: 'browserless',
protocol: 'http:',
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kEndCalled)]: true,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype],
[Symbol(kUniqueHeaders)]: null,
[Symbol(kAborted)]: true,
[Symbol(kError)]: undefined
},
[Symbol(kCapture)]: false
},
[Symbol(kType)]: 'error',
[Symbol(kError)]: Error: Unexpected server response: 429
at ClientRequest.<anonymous> (/app/node_modules/ws/lib/websocket.js:886:7)
at ClientRequest.emit (node:events:513:28)
at ClientRequest.emit (node:domain:489:12)
at HTTPParser.parserOnIncomingClient [as onIncoming] (node:_http_client:693:27)
at HTTPParser.parserOnHeadersComplete (node:_http_common:117:17)
at Socket.socketOnData (node:_http_client:534:22)
at Socket.emit (node:events:513:28)
at Socket.emit (node:domain:489:12)
at addChunk (node:internal/streams/readable:324:12)
at readableAddChunk (node:internal/streams/readable:297:9)
at Readable.push (node:internal/streams/readable:234:10)
at TCP.onStreamRead (node:internal/stream_base_commons:190:23),
[Symbol(kMessage)]: 'Unexpected server response: 429'
}
Might still be worth to verify, if Content-Encoding is properly used above.
Owner Name | browserless |
Repo Name | chrome |
Full Name | browserless/chrome |
Language | TypeScript |
Created Date | 2017-11-17 |
Updated Date | 2023-03-22 |
Star Count | 5309 |
Watcher Count | 47 |
Fork Count | 516 |
Issue Count | 29 |
Issue Title | Created Date | Updated Date |
---|