Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 1x 1x 1x 1x 1x 8x 8x 8x 8x 8x 8x 1x 20x 7x 7x 7x 1x 5x 5x 5x 5x 5x 5x 5x 5x 5x 4x 5x 5x 5x 5x 5x 10x 7x 7x 7x 5x 5x 5x 5x 5x 5x 5x 7x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x | 'use strict'; const PerMessageDeflate = require('ws/lib/PerMessageDeflate'); const Extensions = require('ws/lib/Extensions'); const Receiver = require('ws/lib/Receiver'); const Sender = require('ws/lib/Sender'); const acceptExtensions = ({extensions, isServer}) => { const {extensionName} = PerMessageDeflate; const extension = extensions[extensionName]; Iif (!extension) { return {}; } const perMessageDeflate = new PerMessageDeflate({}, isServer); perMessageDeflate.accept(extension); return {[extensionName]: perMessageDeflate}; }; const getMsgHandler = ({interceptor, dataSender, binary}) => { return (data, flags) => { Eif (typeof interceptor !== 'function') { dataSender({data}); return; } const modifiedData = interceptor(data, flags); // if interceptor does not return data then nothing will be sended to the server if (modifiedData) { dataSender({data: modifiedData, binary}); } } }; module.exports = class Interceptor { static create(opts = {}) { return new this(opts); } constructor({socket, options, proxyReq, proxyRes, proxySocket}) { this._socket = socket; this._options = options; this._proxyReq = proxyReq; this._proxyRes = proxyRes; this._proxySocket = proxySocket; this._isSocketOpened = true; this._configure(); } _configure() { this._proxySocket.on('close', () => { this._isSocketOpened = false; }); const secWsExtensions = this._proxyRes.headers['sec-websocket-extensions']; const extensions = Extensions.parse(secWsExtensions); this._isCompressed = secWsExtensions && secWsExtensions.includes('permessage-deflate'); // need both versions of extensions for each side of the proxy connection this._clientExtensions = this._isCompressed ? acceptExtensions({extensions, isServer: false}) : null; this._serverExtensions = this._isCompressed ? acceptExtensions({extensions, isServer: true}) : null; } _getDataSender({sender, event, options}) { return ({data, binary = false}) => { const opts = Object.assign({fin: true, compress: this._isCompressed, binary}, options); sender.send(data, opts); this._proxyReq.emit(event, {data, binary}); }; } _interceptClientMessages() { const receiver = new Receiver(this._clientExtensions); const sender = new Sender(this._proxySocket, this._serverExtensions); // frame must be masked when send from client to server - https://tools.ietf.org/html/rfc6455#section-5.3 const options = {mask: true}; const dataSender = this._getDataSender({sender, event: 'wsClientMsg', options}); receiver.ontext = getMsgHandler({interceptor: this._options.wsInterceptClientMsg, dataSender, binary: false}); receiver.onbinary = getMsgHandler({interceptor: this._options.wsInterceptClientMsg, dataSender, binary: true}); receiver.onclose = (code, msg, {masked: mask}) => this._isSocketOpened && sender.close(code, msg, mask); this._socket.on('data', (data) => receiver.add(data)); } _interceptServerMessages() { const receiver = new Receiver(this._serverExtensions); const sender = new Sender(this._socket, this._clientExtensions); const options = {mask: false}; const dataSender = this._getDataSender({sender, event: 'wsServerMsg', options}); receiver.ontext = getMsgHandler({interceptor: this._options.wsInterceptServerMsg, dataSender, binary: false}); receiver.onbinary = getMsgHandler({interceptor: this._options.wsInterceptServerMsg, dataSender, binary: true}); receiver.onclose = (code, msg, {masked: mask}) => this._isSocketOpened && sender.close(code, msg, mask); this._proxySocket.on('data', (data) => receiver.add(data)); } startDataTransfer() { this._interceptClientMessages(); this._interceptServerMessages(); } }; |