UNPKG

aws-mqtt

Version:
125 lines (115 loc) 3.98 kB
const crypto = require('crypto') const https = require('https') const tls = require('tls') const WS = require('ws') import { signedUrl } from '../src/urlSigner' import AWS from 'aws-sdk/global' import config from '../examples/config' // NOTE: make sure to copy config.example.js to config.js and fill in your values // These tests ensure that the version of ws.WebSocket is compatible with the usage in this module // and with AWS IoT WebSocket connections (connecting to a signed AWS url) describe('WebSocket compatibility', () => { describe('https.get', () => { // This replicates the way ws.WebSocket makes initial connection, // which seems to fails test('with { createConnection: tls.connect } fails!!!', done => { const request = https.get({ ...echoServer(), headers: webSocketHeaders(), createConnection: tls.connect, // This is what's being tested }) request.on('upgrade', function() { request.abort() done(new Error('Should have failed here')) }) request.on('error', function(err) { request.abort() // we expect this error expect(err.message).toMatch(/ENOTSOCK/) done() }) }) // But passing 'agent' option works test('with agent succeeds', done => { const agent = new https.Agent() const request = https.get({ ...echoServer(), headers: webSocketHeaders(), agent: agent, // This is what's being tested }) request.on('upgrade', function() { request.abort() done() }) request.on('error', function(err) { request.abort() done(err) }) }) }) describe('WebSocket connection to echo server', () => { test('with createConnection option', done => { const socket = new WS('wss://echo.websocket.org/', [], {}) socket.on('upgrade', res => { res.destroy() done() }) socket.on('error', err => { done(err) }) }) }) describe('WebSocket connection to AWS MQTT server', () => { // Skipping: This passes with ws@6.0.0 but fails with ws@6.1.4 - so the problem tested here // has been fixed in ws@6.1.4 test.skip('with no options (createConnection: tls.connect used by ws.WebSocket internally) connection fails', done => { const socket = new WS(awsMqttUrl(), ['mqtt'], { /* no agent passed */}) socket.on('upgrade', res => { res.destroy() done(new Error('Expected to fail connection')) }) socket.on('error', err => { expect(err.message).toMatch(/Unexpected server response: 403/) done() }) }) test('with agent option succeeds', done => { // This imitate the way NodeClient makes a WS connection to AWS MQTT, and should work with // WS v6.0.0 - v6.1.4. Passing an agent seems to be the way to make it work for both ws versions const agent = new https.Agent() const socket = new WS(awsMqttUrl(), ['mqtt'], { agent }) socket.on('upgrade', res => { res.destroy() done() }) socket.on('error', err => { done(err) }) }) }) }) function webSocketHeaders(overrides = {}) { return { 'Sec-WebSocket-Key': crypto.randomBytes(16).toString('base64'), 'Sec-WebSocket-Version': 13, 'Sec-WebSocket-Protocol': 'mqtt', 'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits', 'Connection': 'Upgrade', 'Upgrade': 'websocket', ...overrides, } } function echoServer() { return { hostname: 'echo.websocket.org', path: '/', port: 443, } } function awsMqttUrl() { // For this to work must hace configured aws cli profile named 'aws-mqtt' const credentials = new AWS.SharedIniFileCredentials({ profile: 'aws-mqtt' }) const region = 'us-east-1' const expires = 10000 const endpoint = config.aws.iot.endpoint return signedUrl({ credentials, endpoint, region, expires }) }