12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628 |
- const assert = require('assert')
- const {remote} = require('electron')
- const {ipcRenderer} = require('electron')
- const http = require('http')
- const url = require('url')
- const {net} = remote
- const {session} = remote
- /* The whole net API doesn't use standard callbacks */
- /* eslint-disable standard/no-callback-literal */
- function randomBuffer (size, start, end) {
- start = start || 0
- end = end || 255
- let range = 1 + end - start
- const buffer = Buffer.allocUnsafe(size)
- for (let i = 0; i < size; ++i) {
- buffer[i] = start + Math.floor(Math.random() * range)
- }
- return buffer
- }
- function randomString (length) {
- let buffer = randomBuffer(length, '0'.charCodeAt(0), 'z'.charCodeAt(0))
- return buffer.toString()
- }
- const kOneKiloByte = 1024
- const kOneMegaByte = kOneKiloByte * kOneKiloByte
- describe('net module', () => {
- let server
- const connections = new Set()
- beforeEach((done) => {
- server = http.createServer()
- server.listen(0, '127.0.0.1', () => {
- server.url = `http://127.0.0.1:${server.address().port}`
- done()
- })
- server.on('connection', (connection) => {
- connections.add(connection)
- connection.once('close', () => {
- connections.delete(connection)
- })
- })
- })
- afterEach((done) => {
- for (const connection of connections) {
- connection.destroy()
- }
- server.close(() => {
- server = null
- done()
- })
- })
- describe('HTTP basics', () => {
- it('should be able to issue a basic GET request', (done) => {
- const requestUrl = '/requestUrl'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert.equal(request.method, 'GET')
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request(`${server.url}${requestUrl}`)
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.end()
- })
- it('should be able to issue a basic POST request', (done) => {
- const requestUrl = '/requestUrl'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert.equal(request.method, 'POST')
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- method: 'POST',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.end()
- })
- it('should fetch correct data in a GET request', (done) => {
- const requestUrl = '/requestUrl'
- const bodyData = 'Hello World!'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert.equal(request.method, 'GET')
- response.write(bodyData)
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request(`${server.url}${requestUrl}`)
- urlRequest.on('response', (response) => {
- let expectedBodyData = ''
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- expectedBodyData += chunk.toString()
- })
- response.on('end', () => {
- assert.equal(expectedBodyData, bodyData)
- done()
- })
- response.resume()
- })
- urlRequest.end()
- })
- it('should post the correct data in a POST request', (done) => {
- const requestUrl = '/requestUrl'
- const bodyData = 'Hello World!'
- server.on('request', (request, response) => {
- let postedBodyData = ''
- switch (request.url) {
- case requestUrl:
- assert.equal(request.method, 'POST')
- request.on('data', (chunk) => {
- postedBodyData += chunk.toString()
- })
- request.on('end', () => {
- assert.equal(postedBodyData, bodyData)
- response.end()
- })
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- method: 'POST',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {})
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.write(bodyData)
- urlRequest.end()
- })
- it('should support chunked encoding', (done) => {
- const requestUrl = '/requestUrl'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.chunkedEncoding = true
- assert.equal(request.method, 'POST')
- assert.equal(request.headers['transfer-encoding'], 'chunked')
- assert(!request.headers['content-length'])
- request.on('data', (chunk) => {
- response.write(chunk)
- })
- request.on('end', (chunk) => {
- response.end(chunk)
- })
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- method: 'POST',
- url: `${server.url}${requestUrl}`
- })
- let chunkIndex = 0
- const chunkCount = 100
- let sentChunks = []
- let receivedChunks = []
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- receivedChunks.push(chunk)
- })
- response.on('end', () => {
- let sentData = Buffer.concat(sentChunks)
- let receivedData = Buffer.concat(receivedChunks)
- assert.equal(sentData.toString(), receivedData.toString())
- assert.equal(chunkIndex, chunkCount)
- done()
- })
- response.resume()
- })
- urlRequest.chunkedEncoding = true
- while (chunkIndex < chunkCount) {
- chunkIndex += 1
- const chunk = randomBuffer(kOneKiloByte)
- sentChunks.push(chunk)
- assert(urlRequest.write(chunk))
- }
- urlRequest.end()
- })
- })
- describe('ClientRequest API', () => {
- afterEach(() => {
- session.defaultSession.webRequest.onBeforeRequest(null)
- })
- it('request/response objects should emit expected events', (done) => {
- const requestUrl = '/requestUrl'
- const bodyData = randomString(kOneMegaByte)
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.write(bodyData)
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- let requestResponseEventEmitted = false
- let requestFinishEventEmitted = false
- let requestCloseEventEmitted = false
- let responseDataEventEmitted = false
- let responseEndEventEmitted = false
- function maybeDone (done) {
- if (!requestCloseEventEmitted || !responseEndEventEmitted) {
- return
- }
- assert(requestResponseEventEmitted)
- assert(requestFinishEventEmitted)
- assert(requestCloseEventEmitted)
- assert(responseDataEventEmitted)
- assert(responseEndEventEmitted)
- done()
- }
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- requestResponseEventEmitted = true
- const statusCode = response.statusCode
- assert.equal(statusCode, 200)
- let buffers = []
- response.pause()
- response.on('data', (chunk) => {
- buffers.push(chunk)
- responseDataEventEmitted = true
- })
- response.on('end', () => {
- let receivedBodyData = Buffer.concat(buffers)
- assert(receivedBodyData.toString() === bodyData)
- responseEndEventEmitted = true
- maybeDone(done)
- })
- response.resume()
- response.on('error', (error) => {
- assert.ifError(error)
- })
- response.on('aborted', () => {
- assert.fail('response aborted')
- })
- })
- urlRequest.on('finish', () => {
- requestFinishEventEmitted = true
- })
- urlRequest.on('error', (error) => {
- assert.ifError(error)
- })
- urlRequest.on('abort', () => {
- assert.fail('request aborted')
- })
- urlRequest.on('close', () => {
- requestCloseEventEmitted = true
- maybeDone(done)
- })
- urlRequest.end()
- })
- it('should be able to set a custom HTTP request header before first write', (done) => {
- const requestUrl = '/requestUrl'
- const customHeaderName = 'Some-Custom-Header-Name'
- const customHeaderValue = 'Some-Customer-Header-Value'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert.equal(request.headers[customHeaderName.toLowerCase()],
- customHeaderValue)
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- const statusCode = response.statusCode
- assert.equal(statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.setHeader(customHeaderName, customHeaderValue)
- assert.equal(urlRequest.getHeader(customHeaderName),
- customHeaderValue)
- assert.equal(urlRequest.getHeader(customHeaderName.toLowerCase()),
- customHeaderValue)
- urlRequest.write('')
- assert.equal(urlRequest.getHeader(customHeaderName),
- customHeaderValue)
- assert.equal(urlRequest.getHeader(customHeaderName.toLowerCase()),
- customHeaderValue)
- urlRequest.end()
- })
- it('should be able to set a non-string object as a header value', (done) => {
- const requestUrl = '/requestUrl'
- const customHeaderName = 'Some-Integer-Value'
- const customHeaderValue = 900
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert.equal(request.headers[customHeaderName.toLowerCase()],
- customHeaderValue.toString())
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.end()
- break
- default:
- assert.equal(request.url, requestUrl)
- }
- })
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- const statusCode = response.statusCode
- assert.equal(statusCode, 200)
- response.pause()
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.setHeader(customHeaderName, customHeaderValue)
- assert.equal(urlRequest.getHeader(customHeaderName),
- customHeaderValue)
- assert.equal(urlRequest.getHeader(customHeaderName.toLowerCase()),
- customHeaderValue)
- urlRequest.write('')
- assert.equal(urlRequest.getHeader(customHeaderName),
- customHeaderValue)
- assert.equal(urlRequest.getHeader(customHeaderName.toLowerCase()),
- customHeaderValue)
- urlRequest.end()
- })
- it('should not be able to set a custom HTTP request header after first write', (done) => {
- const requestUrl = '/requestUrl'
- const customHeaderName = 'Some-Custom-Header-Name'
- const customHeaderValue = 'Some-Customer-Header-Value'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert(!request.headers[customHeaderName.toLowerCase()])
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- const statusCode = response.statusCode
- assert.equal(statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.write('')
- assert.throws(() => {
- urlRequest.setHeader(customHeaderName, customHeaderValue)
- })
- assert(!urlRequest.getHeader(customHeaderName))
- urlRequest.end()
- })
- it('should be able to remove a custom HTTP request header before first write', (done) => {
- const requestUrl = '/requestUrl'
- const customHeaderName = 'Some-Custom-Header-Name'
- const customHeaderValue = 'Some-Customer-Header-Value'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert(!request.headers[customHeaderName.toLowerCase()])
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- const statusCode = response.statusCode
- assert.equal(statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.setHeader(customHeaderName, customHeaderValue)
- assert.equal(urlRequest.getHeader(customHeaderName),
- customHeaderValue)
- urlRequest.removeHeader(customHeaderName)
- assert(!urlRequest.getHeader(customHeaderName))
- urlRequest.write('')
- urlRequest.end()
- })
- it('should not be able to remove a custom HTTP request header after first write', (done) => {
- const requestUrl = '/requestUrl'
- const customHeaderName = 'Some-Custom-Header-Name'
- const customHeaderValue = 'Some-Customer-Header-Value'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert.equal(request.headers[customHeaderName.toLowerCase()],
- customHeaderValue)
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- const statusCode = response.statusCode
- assert.equal(statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.setHeader(customHeaderName, customHeaderValue)
- assert.equal(urlRequest.getHeader(customHeaderName),
- customHeaderValue)
- urlRequest.write('')
- assert.throws(() => {
- urlRequest.removeHeader(customHeaderName)
- })
- assert.equal(urlRequest.getHeader(customHeaderName),
- customHeaderValue)
- urlRequest.end()
- })
- it('should be able to set cookie header line', (done) => {
- const requestUrl = '/requestUrl'
- const cookieHeaderName = 'Cookie'
- const cookieHeaderValue = 'test=12345'
- const customSession = session.fromPartition('test-cookie-header')
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert.equal(request.headers[cookieHeaderName.toLowerCase()],
- cookieHeaderValue)
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- customSession.cookies.set({
- url: `${server.url}`,
- name: 'test',
- value: '11111'
- }, (error) => {
- if (error) return done(error)
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`,
- session: customSession
- })
- urlRequest.on('response', (response) => {
- const statusCode = response.statusCode
- assert.equal(statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {})
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.setHeader(cookieHeaderName, cookieHeaderValue)
- assert.equal(urlRequest.getHeader(cookieHeaderName),
- cookieHeaderValue)
- urlRequest.end()
- })
- })
- it('should be able to abort an HTTP request before first write', (done) => {
- const requestUrl = '/requestUrl'
- server.on('request', (request, response) => {
- response.end()
- assert.fail('Unexpected request event')
- })
- let requestAbortEventEmitted = false
- let requestCloseEventEmitted = false
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- assert.fail('Unexpected response event')
- })
- urlRequest.on('finish', () => {
- assert.fail('Unexpected finish event')
- })
- urlRequest.on('error', () => {
- assert.fail('Unexpected error event')
- })
- urlRequest.on('abort', () => {
- requestAbortEventEmitted = true
- })
- urlRequest.on('close', () => {
- requestCloseEventEmitted = true
- assert(requestAbortEventEmitted)
- assert(requestCloseEventEmitted)
- done()
- })
- urlRequest.abort()
- assert(!urlRequest.write(''))
- urlRequest.end()
- })
- it('it should be able to abort an HTTP request before request end', (done) => {
- const requestUrl = '/requestUrl'
- let requestReceivedByServer = false
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- requestReceivedByServer = true
- cancelRequest()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- let requestAbortEventEmitted = false
- let requestCloseEventEmitted = false
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- assert.fail('Unexpected response event')
- })
- urlRequest.on('finish', () => {
- assert.fail('Unexpected finish event')
- })
- urlRequest.on('error', () => {
- assert.fail('Unexpected error event')
- })
- urlRequest.on('abort', () => {
- requestAbortEventEmitted = true
- })
- urlRequest.on('close', () => {
- requestCloseEventEmitted = true
- assert(requestReceivedByServer)
- assert(requestAbortEventEmitted)
- assert(requestCloseEventEmitted)
- done()
- })
- urlRequest.chunkedEncoding = true
- urlRequest.write(randomString(kOneKiloByte))
- function cancelRequest () {
- urlRequest.abort()
- }
- })
- it('it should be able to abort an HTTP request after request end and before response', (done) => {
- const requestUrl = '/requestUrl'
- let requestReceivedByServer = false
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- requestReceivedByServer = true
- cancelRequest()
- process.nextTick(() => {
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.end()
- })
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- let requestAbortEventEmitted = false
- let requestFinishEventEmitted = false
- let requestCloseEventEmitted = false
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- assert.fail('Unexpected response event')
- })
- urlRequest.on('finish', () => {
- requestFinishEventEmitted = true
- })
- urlRequest.on('error', () => {
- assert.fail('Unexpected error event')
- })
- urlRequest.on('abort', () => {
- requestAbortEventEmitted = true
- })
- urlRequest.on('close', () => {
- requestCloseEventEmitted = true
- assert(requestFinishEventEmitted)
- assert(requestReceivedByServer)
- assert(requestAbortEventEmitted)
- assert(requestCloseEventEmitted)
- done()
- })
- urlRequest.end(randomString(kOneKiloByte))
- function cancelRequest () {
- urlRequest.abort()
- }
- })
- it('it should be able to abort an HTTP request after response start', (done) => {
- const requestUrl = '/requestUrl'
- let requestReceivedByServer = false
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- requestReceivedByServer = true
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.write(randomString(kOneKiloByte))
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- let requestFinishEventEmitted = false
- let requestResponseEventEmitted = false
- let requestAbortEventEmitted = false
- let requestCloseEventEmitted = false
- let responseAbortedEventEmitted = false
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- requestResponseEventEmitted = true
- const statusCode = response.statusCode
- assert.equal(statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- assert.fail('Unexpected end event')
- })
- response.resume()
- response.on('error', () => {
- assert.fail('Unexpected error event')
- })
- response.on('aborted', () => {
- responseAbortedEventEmitted = true
- })
- urlRequest.abort()
- })
- urlRequest.on('finish', () => {
- requestFinishEventEmitted = true
- })
- urlRequest.on('error', () => {
- assert.fail('Unexpected error event')
- })
- urlRequest.on('abort', () => {
- requestAbortEventEmitted = true
- })
- urlRequest.on('close', () => {
- requestCloseEventEmitted = true
- assert(requestFinishEventEmitted, 'request should emit "finish" event')
- assert(requestReceivedByServer, 'request should be received by the server')
- assert(requestResponseEventEmitted, '"response" event should be emitted')
- assert(requestAbortEventEmitted, 'request should emit "abort" event')
- assert(responseAbortedEventEmitted, 'response should emit "aborted" event')
- assert(requestCloseEventEmitted, 'request should emit "close" event')
- done()
- })
- urlRequest.end(randomString(kOneKiloByte))
- })
- it('abort event should be emitted at most once', (done) => {
- const requestUrl = '/requestUrl'
- let requestReceivedByServer = false
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- requestReceivedByServer = true
- cancelRequest()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- let requestFinishEventEmitted = false
- let requestAbortEventCount = 0
- let requestCloseEventEmitted = false
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', () => {
- assert.fail('Unexpected response event')
- })
- urlRequest.on('finish', () => {
- requestFinishEventEmitted = true
- })
- urlRequest.on('error', () => {
- assert.fail('Unexpected error event')
- })
- urlRequest.on('abort', () => {
- ++requestAbortEventCount
- urlRequest.abort()
- })
- urlRequest.on('close', () => {
- requestCloseEventEmitted = true
- // Let all pending async events to be emitted
- setTimeout(() => {
- assert(requestFinishEventEmitted)
- assert(requestReceivedByServer)
- assert.equal(requestAbortEventCount, 1)
- assert(requestCloseEventEmitted)
- done()
- }, 500)
- })
- urlRequest.end(randomString(kOneKiloByte))
- function cancelRequest () {
- urlRequest.abort()
- urlRequest.abort()
- }
- })
- it('Requests should be intercepted by webRequest module', (done) => {
- const requestUrl = '/requestUrl'
- const redirectUrl = '/redirectUrl'
- let requestIsRedirected = false
- server.on('request', (request, response) => {
- switch (request.url) {
- case redirectUrl:
- requestIsRedirected = true
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- let requestIsIntercepted = false
- session.defaultSession.webRequest.onBeforeRequest(
- (details, callback) => {
- if (details.url === `${server.url}${requestUrl}`) {
- requestIsIntercepted = true
- // Disabled due to false positive in StandardJS
- // eslint-disable-next-line standard/no-callback-literal
- callback({
- redirectURL: `${server.url}${redirectUrl}`
- })
- } else {
- callback({
- cancel: false
- })
- }
- })
- const urlRequest = net.request(`${server.url}${requestUrl}`)
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- assert(requestIsRedirected, 'The server should receive a request to the forward URL')
- assert(requestIsIntercepted, 'The request should be intercepted by the webRequest module')
- done()
- })
- response.resume()
- })
- urlRequest.end()
- })
- it('should to able to create and intercept a request using a custom session object', (done) => {
- const requestUrl = '/requestUrl'
- const redirectUrl = '/redirectUrl'
- const customPartitionName = 'custom-partition'
- let requestIsRedirected = false
- server.on('request', (request, response) => {
- switch (request.url) {
- case redirectUrl:
- requestIsRedirected = true
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- session.defaultSession.webRequest.onBeforeRequest((details, callback) => {
- assert.fail('Request should not be intercepted by the default session')
- })
- let customSession = session.fromPartition(customPartitionName, {cache: false})
- let requestIsIntercepted = false
- customSession.webRequest.onBeforeRequest((details, callback) => {
- if (details.url === `${server.url}${requestUrl}`) {
- requestIsIntercepted = true
- // Disabled due to false positive in StandardJS
- // eslint-disable-next-line standard/no-callback-literal
- callback({
- redirectURL: `${server.url}${redirectUrl}`
- })
- } else {
- callback({
- cancel: false
- })
- }
- })
- const urlRequest = net.request({
- url: `${server.url}${requestUrl}`,
- session: customSession
- })
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- assert(requestIsRedirected, 'The server should receive a request to the forward URL')
- assert(requestIsIntercepted, 'The request should be intercepted by the webRequest module')
- done()
- })
- response.resume()
- })
- urlRequest.end()
- })
- it('should throw if given an invalid redirect mode', () => {
- const requestUrl = '/requestUrl'
- const options = {
- url: `${server.url}${requestUrl}`,
- redirect: 'custom'
- }
- assert.throws(() => {
- net.request(options)
- }, 'redirect mode should be one of follow, error or manual')
- })
- it('should throw when calling getHeader without a name', () => {
- assert.throws(() => {
- net.request({url: `${server.url}/requestUrl`}).getHeader()
- }, /`name` is required for getHeader\(name\)\./)
- assert.throws(() => {
- net.request({url: `${server.url}/requestUrl`}).getHeader(null)
- }, /`name` is required for getHeader\(name\)\./)
- })
- it('should throw when calling removeHeader without a name', () => {
- assert.throws(() => {
- net.request({url: `${server.url}/requestUrl`}).removeHeader()
- }, /`name` is required for removeHeader\(name\)\./)
- assert.throws(() => {
- net.request({url: `${server.url}/requestUrl`}).removeHeader(null)
- }, /`name` is required for removeHeader\(name\)\./)
- })
- it('should follow redirect when no redirect mode is provided', (done) => {
- const requestUrl = '/301'
- server.on('request', (request, response) => {
- switch (request.url) {
- case '/301':
- response.statusCode = '301'
- response.setHeader('Location', '/200')
- response.end()
- break
- case '/200':
- response.statusCode = '200'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- done()
- })
- urlRequest.end()
- })
- it('should follow redirect chain when no redirect mode is provided', (done) => {
- const requestUrl = '/redirectChain'
- server.on('request', (request, response) => {
- switch (request.url) {
- case '/redirectChain':
- response.statusCode = '301'
- response.setHeader('Location', '/301')
- response.end()
- break
- case '/301':
- response.statusCode = '301'
- response.setHeader('Location', '/200')
- response.end()
- break
- case '/200':
- response.statusCode = '200'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- done()
- })
- urlRequest.end()
- })
- it('should not follow redirect when mode is error', (done) => {
- const requestUrl = '/301'
- server.on('request', (request, response) => {
- switch (request.url) {
- case '/301':
- response.statusCode = '301'
- response.setHeader('Location', '/200')
- response.end()
- break
- case '/200':
- response.statusCode = '200'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- url: `${server.url}${requestUrl}`,
- redirect: 'error'
- })
- urlRequest.on('error', (error) => {
- assert.equal(error.message, 'Request cannot follow redirect with the current redirect mode')
- })
- urlRequest.on('close', () => {
- done()
- })
- urlRequest.end()
- })
- it('should allow follow redirect when mode is manual', (done) => {
- const requestUrl = '/redirectChain'
- let redirectCount = 0
- server.on('request', (request, response) => {
- switch (request.url) {
- case '/redirectChain':
- response.statusCode = '301'
- response.setHeader('Location', '/301')
- response.end()
- break
- case '/301':
- response.statusCode = '301'
- response.setHeader('Location', '/200')
- response.end()
- break
- case '/200':
- response.statusCode = '200'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- url: `${server.url}${requestUrl}`,
- redirect: 'manual'
- })
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- assert.equal(redirectCount, 2)
- done()
- })
- urlRequest.on('redirect', (status, method, url) => {
- if (url === `${server.url}/301` || url === `${server.url}/200`) {
- redirectCount += 1
- urlRequest.followRedirect()
- }
- })
- urlRequest.end()
- })
- it('should allow cancelling redirect when mode is manual', (done) => {
- const requestUrl = '/redirectChain'
- let redirectCount = 0
- server.on('request', (request, response) => {
- switch (request.url) {
- case '/redirectChain':
- response.statusCode = '301'
- response.setHeader('Location', '/redirect/1')
- response.end()
- break
- case '/redirect/1':
- response.statusCode = '200'
- response.setHeader('Location', '/redirect/2')
- response.end()
- break
- case '/redirect/2':
- response.statusCode = '200'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- url: `${server.url}${requestUrl}`,
- redirect: 'manual'
- })
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- urlRequest.abort()
- })
- response.resume()
- })
- urlRequest.on('close', () => {
- assert.equal(redirectCount, 1)
- done()
- })
- urlRequest.on('redirect', (status, method, url) => {
- if (url === `${server.url}/redirect/1`) {
- redirectCount += 1
- urlRequest.followRedirect()
- }
- })
- urlRequest.end()
- })
- it('should throw if given an invalid session option', (done) => {
- const requestUrl = '/requestUrl'
- try {
- const urlRequest = net.request({
- url: `${server.url}${requestUrl}`,
- session: 1
- })
- // eslint-disable-next-line
- urlRequest
- } catch (exception) {
- done()
- }
- })
- it('should to able to create and intercept a request using a custom partition name', (done) => {
- const requestUrl = '/requestUrl'
- const redirectUrl = '/redirectUrl'
- const customPartitionName = 'custom-partition'
- let requestIsRedirected = false
- server.on('request', (request, response) => {
- switch (request.url) {
- case redirectUrl:
- requestIsRedirected = true
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- session.defaultSession.webRequest.onBeforeRequest((details, callback) => {
- assert.fail('Request should not be intercepted by the default session')
- })
- let customSession = session.fromPartition(customPartitionName, {
- cache: false
- })
- let requestIsIntercepted = false
- customSession.webRequest.onBeforeRequest((details, callback) => {
- if (details.url === `${server.url}${requestUrl}`) {
- requestIsIntercepted = true
- callback({
- redirectURL: `${server.url}${redirectUrl}`
- })
- } else {
- callback({
- cancel: false
- })
- }
- })
- const urlRequest = net.request({
- url: `${server.url}${requestUrl}`,
- partition: customPartitionName
- })
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- assert(requestIsRedirected, 'The server should receive a request to the forward URL')
- assert(requestIsIntercepted, 'The request should be intercepted by the webRequest module')
- done()
- })
- response.resume()
- })
- urlRequest.end()
- })
- it('should throw if given an invalid partition option', (done) => {
- const requestUrl = '/requestUrl'
- try {
- const urlRequest = net.request({
- url: `${server.url}${requestUrl}`,
- partition: 1
- })
- // eslint-disable-next-line
- urlRequest
- } catch (exception) {
- done()
- }
- })
- it('should be able to create a request with options', (done) => {
- const requestUrl = '/'
- const customHeaderName = 'Some-Custom-Header-Name'
- const customHeaderValue = 'Some-Customer-Header-Value'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- assert.equal(request.method, 'GET')
- assert.equal(request.headers[customHeaderName.toLowerCase()],
- customHeaderValue)
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const serverUrl = url.parse(server.url)
- let options = {
- port: serverUrl.port,
- hostname: '127.0.0.1',
- headers: {}
- }
- options.headers[customHeaderName] = customHeaderValue
- const urlRequest = net.request(options)
- urlRequest.on('response', (response) => {
- assert.equal(response.statusCode, 200)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.end()
- })
- it('should be able to pipe a readable stream into a net request', (done) => {
- const nodeRequestUrl = '/nodeRequestUrl'
- const netRequestUrl = '/netRequestUrl'
- const bodyData = randomString(kOneMegaByte)
- let netRequestReceived = false
- let netRequestEnded = false
- server.on('request', (request, response) => {
- switch (request.url) {
- case nodeRequestUrl:
- response.write(bodyData)
- response.end()
- break
- case netRequestUrl:
- netRequestReceived = true
- let receivedBodyData = ''
- request.on('data', (chunk) => {
- receivedBodyData += chunk.toString()
- })
- request.on('end', (chunk) => {
- netRequestEnded = true
- if (chunk) {
- receivedBodyData += chunk.toString()
- }
- assert.equal(receivedBodyData, bodyData)
- response.end()
- })
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- let nodeRequest = http.request(`${server.url}${nodeRequestUrl}`)
- nodeRequest.on('response', (nodeResponse) => {
- const netRequest = net.request(`${server.url}${netRequestUrl}`)
- netRequest.on('response', (netResponse) => {
- assert.equal(netResponse.statusCode, 200)
- netResponse.pause()
- netResponse.on('data', (chunk) => {})
- netResponse.on('end', () => {
- assert(netRequestReceived)
- assert(netRequestEnded)
- done()
- })
- netResponse.resume()
- })
- nodeResponse.pipe(netRequest)
- })
- nodeRequest.end()
- })
- it('should emit error event on server socket close', (done) => {
- const requestUrl = '/requestUrl'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- request.socket.destroy()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- let requestErrorEventEmitted = false
- const urlRequest = net.request(`${server.url}${requestUrl}`)
- urlRequest.on('error', (error) => {
- assert(error)
- requestErrorEventEmitted = true
- })
- urlRequest.on('close', () => {
- assert(requestErrorEventEmitted)
- done()
- })
- urlRequest.end()
- })
- })
- describe('IncomingMessage API', () => {
- it('response object should implement the IncomingMessage API', (done) => {
- const requestUrl = '/requestUrl'
- const customHeaderName = 'Some-Custom-Header-Name'
- const customHeaderValue = 'Some-Customer-Header-Value'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.setHeader(customHeaderName, customHeaderValue)
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- const statusCode = response.statusCode
- assert(typeof statusCode === 'number')
- assert.equal(statusCode, 200)
- const statusMessage = response.statusMessage
- assert(typeof statusMessage === 'string')
- assert.equal(statusMessage, 'OK')
- const headers = response.headers
- assert(typeof headers === 'object')
- assert.deepEqual(headers[customHeaderName.toLowerCase()],
- [customHeaderValue])
- const httpVersion = response.httpVersion
- assert(typeof httpVersion === 'string')
- assert(httpVersion.length > 0)
- const httpVersionMajor = response.httpVersionMajor
- assert(typeof httpVersionMajor === 'number')
- assert(httpVersionMajor >= 1)
- const httpVersionMinor = response.httpVersionMinor
- assert(typeof httpVersionMinor === 'number')
- assert(httpVersionMinor >= 0)
- response.pause()
- response.on('data', (chunk) => {
- })
- response.on('end', () => {
- done()
- })
- response.resume()
- })
- urlRequest.end()
- })
- it('should be able to pipe a net response into a writable stream', (done) => {
- const nodeRequestUrl = '/nodeRequestUrl'
- const netRequestUrl = '/netRequestUrl'
- const bodyData = randomString(kOneMegaByte)
- server.on('request', (request, response) => {
- switch (request.url) {
- case netRequestUrl:
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.write(bodyData)
- response.end()
- break
- case nodeRequestUrl:
- let receivedBodyData = ''
- request.on('data', (chunk) => {
- receivedBodyData += chunk.toString()
- })
- request.on('end', (chunk) => {
- if (chunk) {
- receivedBodyData += chunk.toString()
- }
- assert.equal(receivedBodyData, bodyData)
- response.end()
- })
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- ipcRenderer.once('api-net-spec-done', () => {
- done()
- })
- // Execute below code directly within the browser context without
- // using the remote module.
- ipcRenderer.send('eval', `
- const {net} = require('electron')
- const http = require('http')
- const netRequest = net.request('${server.url}${netRequestUrl}')
- netRequest.on('response', function (netResponse) {
- const serverUrl = url.parse('${server.url}')
- const nodeOptions = {
- method: 'POST',
- path: '${nodeRequestUrl}',
- port: serverUrl.port
- }
- let nodeRequest = http.request(nodeOptions)
- nodeRequest.on('response', function (nodeResponse) {
- nodeResponse.on('data', (chunk) => {
- })
- nodeResponse.on('end', (chunk) => {
- event.sender.send('api-net-spec-done')
- })
- })
- netResponse.pipe(nodeRequest)
- })
- netRequest.end()
- `)
- })
- it('should not emit any event after close', (done) => {
- const requestUrl = '/requestUrl'
- let bodyData = randomString(kOneKiloByte)
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.write(bodyData)
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- let requestCloseEventEmitted = false
- const urlRequest = net.request({
- method: 'GET',
- url: `${server.url}${requestUrl}`
- })
- urlRequest.on('response', (response) => {
- assert(!requestCloseEventEmitted)
- const statusCode = response.statusCode
- assert.equal(statusCode, 200)
- response.pause()
- response.on('data', () => {
- })
- response.on('end', () => {
- })
- response.resume()
- response.on('error', () => {
- assert(!requestCloseEventEmitted)
- })
- response.on('aborted', () => {
- assert(!requestCloseEventEmitted)
- })
- })
- urlRequest.on('finish', () => {
- assert(!requestCloseEventEmitted)
- })
- urlRequest.on('error', () => {
- assert(!requestCloseEventEmitted)
- })
- urlRequest.on('abort', () => {
- assert(!requestCloseEventEmitted)
- })
- urlRequest.on('close', () => {
- requestCloseEventEmitted = true
- // Wait so that all async events get scheduled.
- setTimeout(() => {
- done()
- }, 100)
- })
- urlRequest.end()
- })
- })
- describe('Stability and performance', () => {
- it('should free unreferenced, never-started request objects without crash', (done) => {
- const requestUrl = '/requestUrl'
- ipcRenderer.once('api-net-spec-done', () => {
- done()
- })
- ipcRenderer.send('eval', `
- const {net} = require('electron')
- const urlRequest = net.request('${server.url}${requestUrl}')
- process.nextTick(() => {
- const v8Util = process.atomBinding('v8_util')
- v8Util.requestGarbageCollectionForTesting()
- event.sender.send('api-net-spec-done')
- })
- `)
- })
- it('should not collect on-going requests without crash', (done) => {
- const requestUrl = '/requestUrl'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.write(randomString(kOneKiloByte))
- ipcRenderer.once('api-net-spec-resume', () => {
- response.write(randomString(kOneKiloByte))
- response.end()
- })
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- ipcRenderer.once('api-net-spec-done', () => {
- done()
- })
- // Execute below code directly within the browser context without
- // using the remote module.
- ipcRenderer.send('eval', `
- const {net} = require('electron')
- const urlRequest = net.request('${server.url}${requestUrl}')
- urlRequest.on('response', (response) => {
- response.on('data', () => {
- })
- response.on('end', () => {
- event.sender.send('api-net-spec-done')
- })
- process.nextTick(() => {
- // Trigger a garbage collection.
- const v8Util = process.atomBinding('v8_util')
- v8Util.requestGarbageCollectionForTesting()
- event.sender.send('api-net-spec-resume')
- })
- })
- urlRequest.end()
- `)
- })
- it('should collect unreferenced, ended requests without crash', (done) => {
- const requestUrl = '/requestUrl'
- server.on('request', (request, response) => {
- switch (request.url) {
- case requestUrl:
- response.statusCode = 200
- response.statusMessage = 'OK'
- response.end()
- break
- default:
- handleUnexpectedURL(request, response)
- }
- })
- ipcRenderer.once('api-net-spec-done', () => {
- done()
- })
- ipcRenderer.send('eval', `
- const {net} = require('electron')
- const urlRequest = net.request('${server.url}${requestUrl}')
- urlRequest.on('response', (response) => {
- response.on('data', () => {
- })
- response.on('end', () => {
- })
- })
- urlRequest.on('close', () => {
- process.nextTick(() => {
- const v8Util = process.atomBinding('v8_util')
- v8Util.requestGarbageCollectionForTesting()
- event.sender.send('api-net-spec-done')
- })
- })
- urlRequest.end()
- `)
- })
- })
- })
- function handleUnexpectedURL (request, response) {
- response.statusCode = '500'
- response.end()
- assert.fail(`Unexpected URL: ${request.url}`)
- }
|