feat(har): store textual content without base64 encoding (#14772)
This commit is contained in:
		
							parent
							
								
									7a568a2952
								
							
						
					
					
						commit
						868e00253f
					
				|  | @ -191,7 +191,7 @@ export class HarTracer { | |||
|     const contentType = event.headers['content-type']; | ||||
|     if (contentType) | ||||
|       content.mimeType = contentType; | ||||
|     this._storeResponseContent(event.body, content); | ||||
|     this._storeResponseContent(event.body, content, 'other'); | ||||
| 
 | ||||
|     if (this._started) | ||||
|       this._delegate.onEntryFinished(harEntry); | ||||
|  | @ -261,7 +261,7 @@ export class HarTracer { | |||
| 
 | ||||
|       const content = harEntry.response.content; | ||||
|       compressionCalculationBarrier.setDecodedBodySize(buffer.length); | ||||
|       this._storeResponseContent(buffer, content); | ||||
|       this._storeResponseContent(buffer, content, request.resourceType()); | ||||
|     }).catch(() => { | ||||
|       compressionCalculationBarrier.setDecodedBodySize(0); | ||||
|     }).then(() => { | ||||
|  | @ -296,15 +296,21 @@ export class HarTracer { | |||
|       this._delegate.onEntryFinished(harEntry); | ||||
|   } | ||||
| 
 | ||||
|   private _storeResponseContent(buffer: Buffer | undefined, content: har.Content) { | ||||
|   private _storeResponseContent(buffer: Buffer | undefined, content: har.Content, resourceType: string) { | ||||
|     if (!buffer) { | ||||
|       content.size = 0; | ||||
|       return; | ||||
|     } | ||||
|     content.size = buffer.length; | ||||
|     if (this._options.content === 'embedded') { | ||||
|       content.text = buffer.toString('base64'); | ||||
|       content.encoding = 'base64'; | ||||
|       // Sometimes, we can receive a font/media file with textual mime type. Browser
 | ||||
|       // still interprets them correctly, but the 'content-type' header is obviously wrong.
 | ||||
|       if (isTextualMimeType(content.mimeType) && resourceType !== 'font') { | ||||
|         content.text = buffer.toString(); | ||||
|       } else { | ||||
|         content.text = buffer.toString('base64'); | ||||
|         content.encoding = 'base64'; | ||||
|       } | ||||
|     } else if (this._options.content === 'sha1') { | ||||
|       content._sha1 = calculateSha1(buffer) + '.' + (mime.getExtension(content.mimeType) || 'dat'); | ||||
|       if (this._started) | ||||
|  | @ -529,3 +535,7 @@ function parseCookie(c: string): har.Cookie { | |||
|   } | ||||
|   return cookie; | ||||
| } | ||||
| 
 | ||||
| function isTextualMimeType(mimeType: string) { | ||||
|   return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/); | ||||
| } | ||||
|  |  | |||
|  | @ -248,21 +248,26 @@ it('should include secure set-cookies', async ({ contextFactory, httpsServer }, | |||
| it('should include content @smoke', async ({ contextFactory, server }, testInfo) => { | ||||
|   const { page, getLog } = await pageWithHar(contextFactory, testInfo); | ||||
|   await page.goto(server.PREFIX + '/har.html'); | ||||
|   await page.evaluate(() => fetch('/pptr.png').then(r => r.arrayBuffer())); | ||||
|   const log = await getLog(); | ||||
| 
 | ||||
|   expect(log.entries[0].response.httpVersion).toBe('HTTP/1.1'); | ||||
|   expect(log.entries[0].response.content.encoding).toBe('base64'); | ||||
|   expect(log.entries[0].response.content.encoding).toBe(undefined); | ||||
|   expect(log.entries[0].response.content.mimeType).toBe('text/html; charset=utf-8'); | ||||
|   expect(Buffer.from(log.entries[0].response.content.text, 'base64').toString()).toContain('HAR Page'); | ||||
|   expect(log.entries[0].response.content.text).toContain('HAR Page'); | ||||
|   expect(log.entries[0].response.content.size).toBeGreaterThanOrEqual(96); | ||||
|   expect(log.entries[0].response.content.compression).toBe(0); | ||||
| 
 | ||||
|   expect(log.entries[1].response.httpVersion).toBe('HTTP/1.1'); | ||||
|   expect(log.entries[1].response.content.encoding).toBe('base64'); | ||||
|   expect(log.entries[1].response.content.encoding).toBe(undefined); | ||||
|   expect(log.entries[1].response.content.mimeType).toBe('text/css; charset=utf-8'); | ||||
|   expect(Buffer.from(log.entries[1].response.content.text, 'base64').toString()).toContain('pink'); | ||||
|   expect(log.entries[1].response.content.text).toContain('pink'); | ||||
|   expect(log.entries[1].response.content.size).toBeGreaterThanOrEqual(37); | ||||
|   expect(log.entries[1].response.content.compression).toBe(0); | ||||
| 
 | ||||
|   expect(log.entries[2].response.content.encoding).toBe('base64'); | ||||
|   expect(log.entries[2].response.content.mimeType).toBe('image/png'); | ||||
|   expect(Buffer.from(log.entries[2].response.content.text, 'base64').byteLength).toBeGreaterThan(0); | ||||
|   expect(log.entries[2].response.content.size).toBeGreaterThanOrEqual(6000); | ||||
|   expect(log.entries[2].response.content.compression).toBe(0); | ||||
| }); | ||||
| 
 | ||||
| it('should filter by glob', async ({ contextFactory, server }, testInfo) => { | ||||
|  | @ -580,7 +585,7 @@ it('should contain http2 for http2 requests', async ({ contextFactory, browserNa | |||
|   const log = await getLog(); | ||||
|   expect(log.entries[0].request.httpVersion).toBe('HTTP/2.0'); | ||||
|   expect(log.entries[0].response.httpVersion).toBe('HTTP/2.0'); | ||||
|   expect(Buffer.from(log.entries[0].response.content.text, 'base64').toString()).toBe('<h1>Hello World</h1>'); | ||||
|   expect(log.entries[0].response.content.text).toBe('<h1>Hello World</h1>'); | ||||
|   server.close(); | ||||
| }); | ||||
| 
 | ||||
|  | @ -734,7 +739,7 @@ it('should include API request', async ({ contextFactory, server }, testInfo) => | |||
|   expect(entry.response.status).toBe(200); | ||||
|   expect(entry.response.headers.find(h => h.name.toLowerCase() === 'content-type')?.value).toContain('application/json'); | ||||
|   expect(entry.response.content.size).toBe(15); | ||||
|   expect(entry.response.content.text).toBe(responseBody.toString('base64')); | ||||
|   expect(entry.response.content.text).toBe(responseBody.toString()); | ||||
| }); | ||||
| 
 | ||||
| it('should not hang on resources served from cache', async ({ contextFactory, server, browserName }, testInfo) => { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue