Best JavaScript code snippet using mountebank
socket_test.js
Source:socket_test.js
1import assert from "assert"2import jsdom from "jsdom"3import sinon from "sinon"4import {WebSocket, Server as WebSocketServer} from "mock-socket"5import {encode, decode} from "./serializer"6import {Socket, LongPoll} from "../js/phoenix"7let socket8describe("constructor", () => {9 before(() => {10 window.XMLHttpRequest = sinon.useFakeXMLHttpRequest()11 })12 after(() => {13 window.XMLHttpRequest = null14 })15 it("sets defaults", () => {16 socket = new Socket("/socket")17 assert.equal(socket.channels.length, 0)18 assert.equal(socket.sendBuffer.length, 0)19 assert.equal(socket.ref, 0)20 assert.equal(socket.endPoint, "/socket/websocket")21 assert.deepEqual(socket.stateChangeCallbacks, {open: [], close: [], error: [], message: []})22 assert.equal(socket.transport, LongPoll)23 assert.equal(socket.timeout, 10000)24 assert.equal(socket.longpollerTimeout, 20000)25 assert.equal(socket.heartbeatIntervalMs, 30000)26 assert.equal(typeof socket.logger, "function")27 assert.equal(typeof socket.reconnectAfterMs, "function")28 })29 it("overrides some defaults with options", () => {30 const customTransport = function transport() {}31 const customLogger = function logger() {}32 const customReconnect = function reconnect() {}33 socket = new Socket("/socket", {34 timeout: 40000,35 longpollerTimeout: 50000,36 heartbeatIntervalMs: 60000,37 transport: customTransport,38 logger: customLogger,39 reconnectAfterMs: customReconnect,40 params: {one: "two"},41 })42 assert.equal(socket.timeout, 40000)43 assert.equal(socket.longpollerTimeout, 50000)44 assert.equal(socket.heartbeatIntervalMs, 60000)45 assert.equal(socket.transport, customTransport)46 assert.equal(socket.logger, customLogger)47 assert.equal(socket.reconnectAfterMs, customReconnect)48 assert.deepEqual(socket.params, {one: "two"})49 })50 describe("with Websocket", () => {51 let mockServer52 before(() => {53 mockServer = new WebSocketServer("wss://example.com/")54 })55 after((done) => {56 mockServer.stop(() => {57 window.WebSocket = null58 done()59 })60 })61 it("defaults to Websocket transport if available", () => {62 socket = new Socket("/socket")63 assert.equal(socket.transport, WebSocket)64 })65 })66})67describe("protocol", () => {68 beforeEach(() => {69 socket = new Socket("/socket")70 })71 it("returns wss when location.protocol is https", () => {72 jsdom.changeURL(window, "https://example.com/");73 assert.equal(socket.protocol(), "wss")74 })75 it("returns ws when location.protocol is http", () => {76 jsdom.changeURL(window, "http://example.com/");77 assert.equal(socket.protocol(), "ws")78 })79})80describe("endpointURL", () => {81 it("returns endpoint for given full url", () => {82 jsdom.changeURL(window, "https://example.com/");83 socket = new Socket("wss://example.org/chat")84 assert.equal(socket.endPointURL(), "wss://example.org/chat/websocket?vsn=2.0.0")85 })86 it("returns endpoint for given protocol-relative url", () => {87 jsdom.changeURL(window, "https://example.com/");88 socket = new Socket("//example.org/chat")89 assert.equal(socket.endPointURL(), "wss://example.org/chat/websocket?vsn=2.0.0")90 })91 it("returns endpoint for given path on https host", () => {92 jsdom.changeURL(window, "https://example.com/");93 socket = new Socket("/socket")94 assert.equal(socket.endPointURL(), "wss://example.com/socket/websocket?vsn=2.0.0")95 })96 it("returns endpoint for given path on http host", () => {97 jsdom.changeURL(window, "http://example.com/");98 socket = new Socket("/socket")99 assert.equal(socket.endPointURL(), "ws://example.com/socket/websocket?vsn=2.0.0")100 })101})102describe("connect with WebSocket", () => {103 let mockServer104 before(() => {105 mockServer = new WebSocketServer("wss://example.com/")106 })107 after((done) => {108 mockServer.stop(() => {109 window.WebSocket = null110 done()111 })112 })113 beforeEach(() => {114 socket = new Socket("/socket")115 })116 it("establishes websocket connection with endpoint", () => {117 socket.connect()118 let conn = socket.conn119 assert.ok(conn instanceof WebSocket)120 assert.equal(conn.url, socket.endPointURL())121 })122 it("sets callbacks for connection", () => {123 let opens = 0124 socket.onOpen(() => ++opens)125 let closes = 0126 socket.onClose(() => ++closes)127 let lastError128 socket.onError((error) => lastError = error)129 let lastMessage130 socket.onMessage((message) => lastMessage = message.payload)131 socket.connect()132 socket.conn.onopen[0]()133 assert.equal(opens, 1)134 socket.conn.onclose[0]()135 assert.equal(closes, 1)136 socket.conn.onerror[0]("error")137 assert.equal(lastError, "error")138 const data = {"topic":"topic","event":"event","payload":"payload","status":"ok"}139 socket.conn.onmessage[0]({data: encode(data)})140 assert.equal(lastMessage, "payload")141 })142 it("is idempotent", () => {143 socket.connect()144 let conn = socket.conn145 socket.connect()146 assert.deepStrictEqual(conn, socket.conn)147 })148})149describe("connect with long poll", () => {150 before(() => {151 window.XMLHttpRequest = sinon.useFakeXMLHttpRequest()152 })153 after(() => {154 window.XMLHttpRequest = null155 })156 beforeEach(() => {157 socket = new Socket("/socket")158 })159 it("establishes long poll connection with endpoint", () => {160 socket.connect()161 let conn = socket.conn162 assert.ok(conn instanceof LongPoll)163 assert.equal(conn.pollEndpoint, "http://example.com/socket/longpoll?vsn=2.0.0")164 assert.equal(conn.timeout, 20000)165 })166 it("sets callbacks for connection", () => {167 let opens = 0168 socket.onOpen(() => ++opens)169 let closes = 0170 socket.onClose(() => ++closes)171 let lastError172 socket.onError((error) => lastError = error)173 let lastMessage174 socket.onMessage((message) => lastMessage = message.payload)175 socket.connect()176 socket.conn.onopen()177 assert.equal(opens, 1)178 socket.conn.onclose()179 assert.equal(closes, 1)180 socket.conn.onerror("error")181 assert.equal(lastError, "error")182 socket.connect()183 const data = {"topic":"topic","event":"event","payload":"payload","status":"ok"}184 socket.conn.onmessage({data: encode(data)})185 assert.equal(lastMessage, "payload")186 })187 it("is idempotent", () => {188 socket.connect()189 let conn = socket.conn190 socket.connect()191 assert.deepStrictEqual(conn, socket.conn)192 })193})194describe("disconnect", () => {195 let mockServer196 before(() => {197 mockServer = new WebSocketServer('wss://example.com/')198 })199 after((done) => {200 mockServer.stop(() => {201 window.WebSocket = null202 done()203 })204 })205 beforeEach(() => {206 socket = new Socket("/socket")207 })208 it("removes existing connection", () => {209 socket.connect()210 socket.disconnect()211 assert.equal(socket.conn, null)212 })213 it("calls callback", () => {214 let count = 0215 socket.connect()216 socket.disconnect(() => count++)217 assert.equal(count, 1)218 })219 it("calls connection close callback", () => {220 socket.connect()221 const spy = sinon.spy(socket.conn, "close")222 socket.disconnect(null, "code", "reason")223 assert(spy.calledWith("code", "reason"))224 })225 it("does not throw when no connection", () => {226 assert.doesNotThrow(() => {227 socket.disconnect()228 })229 })230})231describe("connectionState", () => {232 before(() => {233 window.XMLHttpRequest = sinon.useFakeXMLHttpRequest()234 })235 after(() => {236 window.XMLHttpRequest = null237 })238 beforeEach(() => {239 socket = new Socket("/socket")240 })241 it("defaults to closed", () => {242 assert.equal(socket.connectionState(), "closed")243 })244 it("returns closed if readyState unrecognized", () => {245 socket.connect()246 socket.conn.readyState = 5678247 assert.equal(socket.connectionState(), "closed")248 })249 it("returns connecting", () => {250 socket.connect()251 socket.conn.readyState = 0252 assert.equal(socket.connectionState(), "connecting")253 assert.ok(!socket.isConnected(), "is not connected")254 })255 it("returns open", () => {256 socket.connect()257 socket.conn.readyState = 1258 assert.equal(socket.connectionState(), "open")259 assert.ok(socket.isConnected(), "is connected")260 })261 it("returns closing", () => {262 socket.connect()263 socket.conn.readyState = 2264 assert.equal(socket.connectionState(), "closing")265 assert.ok(!socket.isConnected(), "is not connected")266 })267 it("returns closed", () => {268 socket.connect()269 socket.conn.readyState = 3270 assert.equal(socket.connectionState(), "closed")271 assert.ok(!socket.isConnected(), "is not connected")272 })273})274describe("channel", () => {275 let channel276 beforeEach(() => {277 socket = new Socket("/socket")278 })279 it("returns channel with given topic and params", () => {280 channel = socket.channel("topic", {one: "two"})281 assert.deepStrictEqual(channel.socket, socket)282 assert.equal(channel.topic, "topic")283 assert.deepEqual(channel.params, {one: "two"})284 })285 it("adds channel to sockets channels list", () => {286 assert.equal(socket.channels.length, 0)287 channel = socket.channel("topic", {one: "two"})288 assert.equal(socket.channels.length, 1)289 const [foundChannel] = socket.channels290 assert.deepStrictEqual(foundChannel, channel)291 })292})293describe("remove", () => {294 beforeEach(() => {295 socket = new Socket("/socket")296 })297 it("removes given channel from channels", () => {298 const channel1 = socket.channel("topic-1")299 const channel2 = socket.channel("topic-2")300 sinon.stub(channel1, "joinRef").returns(1)301 sinon.stub(channel2, "joinRef").returns(2)302 socket.remove(channel1)303 assert.equal(socket.channels.length, 1)304 const [foundChannel] = socket.channels305 assert.deepStrictEqual(foundChannel, channel2)306 })307})308describe("push", () => {309 const data = {topic: "topic", event: "event", payload: "payload", ref: "ref"}310 const json = encode(data)311 before(() => {312 window.XMLHttpRequest = sinon.useFakeXMLHttpRequest()313 })314 after(() => {315 window.XMLHttpRequest = null316 })317 beforeEach(() => {318 socket = new Socket("/socket")319 })320 it("sends data to connection when connected", () => {321 socket.connect()322 socket.conn.readyState = 1 // open323 const spy = sinon.spy(socket.conn, "send")324 socket.push(data)325 assert.ok(spy.calledWith(json))326 })327 it("buffers data when not connected", () => {328 socket.connect()329 socket.conn.readyState = 0 // connecting330 const spy = sinon.spy(socket.conn, "send")331 assert.equal(socket.sendBuffer.length, 0)332 socket.push(data)333 assert.ok(spy.neverCalledWith(json))334 assert.equal(socket.sendBuffer.length, 1)335 const [callback] = socket.sendBuffer336 callback()337 assert.ok(spy.calledWith(json))338 })339})340describe("makeRef", () => {341 beforeEach(() => {342 socket = new Socket("/socket")343 })344 it("returns next message ref", () => {345 assert.strictEqual(socket.ref, 0)346 assert.strictEqual(socket.makeRef(), "1")347 assert.strictEqual(socket.ref, 1)348 assert.strictEqual(socket.makeRef(), "2")349 assert.strictEqual(socket.ref, 2)350 })351 it("restarts for overflow", () => {352 socket.ref = Number.MAX_SAFE_INTEGER + 1353 assert.strictEqual(socket.makeRef(), "0")354 assert.strictEqual(socket.ref, 0)355 })356})357describe("sendHeartbeat", () => {358 before(() => {359 window.XMLHttpRequest = sinon.useFakeXMLHttpRequest()360 })361 after(() => {362 window.XMLHttpRequest = null363 })364 beforeEach(() => {365 socket = new Socket("/socket")366 socket.connect()367 })368 it("closes socket when heartbeat is not ack'd within heartbeat window", () => {369 let closed = false370 socket.conn.readyState = 1 // open371 socket.conn.onclose = () => closed = true372 socket.sendHeartbeat()373 assert.equal(closed, false)374 socket.sendHeartbeat()375 assert.equal(closed, true)376 })377 it("pushes heartbeat data when connected", () => {378 socket.conn.readyState = 1 // open379 const spy = sinon.spy(socket.conn, "send")380 const data = "[null,\"1\",\"phoenix\",\"heartbeat\",{}]"381 socket.sendHeartbeat()382 assert.ok(spy.calledWith(data))383 })384 it("no ops when not connected", () => {385 socket.conn.readyState = 0 // connecting386 const spy = sinon.spy(socket.conn, "send")387 const data = encode({topic: "phoenix", event: "heartbeat", payload: {},ref: "1"})388 socket.sendHeartbeat()389 assert.ok(spy.neverCalledWith(data))390 })391})392describe("flushSendBuffer", () => {393 before(() => {394 window.XMLHttpRequest = sinon.useFakeXMLHttpRequest()395 })396 after(() => {397 window.XMLHttpRequest = null398 })399 beforeEach(() => {400 socket = new Socket("/socket")401 socket.connect()402 })403 it("calls callbacks in buffer when connected", () => {404 socket.conn.readyState = 1 // open405 const spy1 = sinon.spy()406 const spy2 = sinon.spy()407 const spy3 = sinon.spy()408 socket.sendBuffer.push(spy1)409 socket.sendBuffer.push(spy2)410 socket.flushSendBuffer()411 assert.ok(spy1.calledOnce)412 assert.ok(spy2.calledOnce)413 assert.equal(spy3.callCount, 0)414 })415 it("empties sendBuffer", () => {416 socket.conn.readyState = 1 // open417 socket.sendBuffer.push(() => {})418 socket.flushSendBuffer()419 assert.deepEqual(socket.sendBuffer.length, 0)420 })421})422describe("onConnOpen", () => {423 let mockServer424 before(() => {425 mockServer = new WebSocketServer('wss://example.com/')426 })427 after((done) => {428 mockServer.stop(() => {429 window.WebSocket = null430 done()431 })432 })433 beforeEach(() => {434 socket = new Socket("/socket", {435 reconnectAfterMs: () => 100000436 })437 socket.connect()438 })439 it("flushes the send buffer", () => {440 socket.conn.readyState = 1 // open441 const spy = sinon.spy()442 socket.sendBuffer.push(spy)443 socket.onConnOpen()444 assert.ok(spy.calledOnce)445 })446 it("resets reconnectTimer", () => {447 const spy = sinon.spy(socket.reconnectTimer, "reset")448 socket.onConnOpen()449 assert.ok(spy.calledOnce)450 })451 it("triggers onOpen callback", () => {452 const spy = sinon.spy()453 socket.onOpen(spy)454 socket.onConnOpen()455 assert.ok(spy.calledOnce)456 })457})458describe("onConnClose", () => {459 let mockServer460 before(() => {461 mockServer = new WebSocketServer('wss://example.com/')462 })463 after((done) => {464 mockServer.stop(() => {465 window.WebSocket = null466 done()467 })468 })469 beforeEach(() => {470 socket = new Socket("/socket", {471 reconnectAfterMs: () => 100000472 })473 socket.connect()474 })475 it("schedules reconnectTimer timeout", () => {476 const spy = sinon.spy(socket.reconnectTimer, "scheduleTimeout")477 socket.onConnClose()478 assert.ok(spy.calledOnce)479 })480 it("triggers onClose callback", () => {481 const spy = sinon.spy()482 socket.onClose(spy)483 socket.onConnClose("event")484 assert.ok(spy.calledWith("event"))485 })486 it("triggers channel error", () => {487 const channel = socket.channel("topic")488 const spy = sinon.spy(channel, "trigger")489 socket.onConnClose()490 assert.ok(spy.calledWith("phx_error"))491 })492})493describe("onConnError", () => {494 let mockServer495 before(() => {496 mockServer = new WebSocketServer('wss://example.com/')497 })498 after((done) => {499 mockServer.stop(() => {500 window.WebSocket = null501 done()502 })503 })504 beforeEach(() => {505 socket = new Socket("/socket", {506 reconnectAfterMs: () => 100000507 })508 socket.connect()509 })510 it("triggers onClose callback", () => {511 const spy = sinon.spy()512 socket.onError(spy)513 socket.onConnError("error")514 assert.ok(spy.calledWith("error"))515 })516 it("triggers channel error", () => {517 const channel = socket.channel("topic")518 const spy = sinon.spy(channel, "trigger")519 socket.onConnError("error")520 assert.ok(spy.calledWith("phx_error"))521 })522})523describe("onConnMessage", () => {524 let mockServer525 before(() => {526 mockServer = new WebSocketServer('wss://example.com/')527 })528 after((done) => {529 mockServer.stop(() => {530 window.WebSocket = null531 done()532 })533 })534 beforeEach(() => {535 socket = new Socket("/socket", {536 reconnectAfterMs: () => 100000537 })538 socket.connect()539 })540 it("parses raw message and triggers channel event", () => {541 const message = encode({topic: "topic", event: "event", payload: "payload", ref: "ref"})542 const data = {data: message}543 const targetChannel = socket.channel("topic")544 const otherChannel = socket.channel("off-topic")545 const targetSpy = sinon.spy(targetChannel, "trigger")546 const otherSpy = sinon.spy(otherChannel, "trigger")547 socket.onConnMessage(data)548 assert.ok(targetSpy.calledWith("event", "payload", "ref"))549 assert.equal(targetSpy.callCount, 1)550 assert.equal(otherSpy.callCount, 0)551 })552 it("triggers onMessage callback", () => {553 const message = {"topic":"topic","event":"event","payload":"payload","ref":"ref"}554 const spy = sinon.spy()555 socket.onMessage(spy)556 socket.onConnMessage({data: encode(message)})557 assert.ok(spy.calledWith({558 "topic": "topic",559 "event": "event",560 "payload": "payload",561 "ref": "ref",562 "join_ref": null563 }))564 })565})566describe("custom encoder and decoder", () => {567 it("encodes to JSON array by default", () => {568 socket = new Socket("/socket")569 let payload = {topic: "topic", ref: "2", join_ref: "1", event: "join", payload: {foo: "bar"}}570 socket.encode(payload, encoded => {571 assert.deepStrictEqual(encoded, '["1","2","topic","join",{"foo":"bar"}]')572 })573 })574 it("allows custom encoding when using WebSocket transport", () => {575 let encoder = (payload, callback) => callback("encode works")576 socket = new Socket("/socket", {transport: WebSocket, encode: encoder})577 socket.encode({foo: "bar"}, encoded => {578 assert.deepStrictEqual(encoded, "encode works")579 })580 })581 it("forces JSON encoding when using LongPoll transport", () => {582 let encoder = (payload, callback) => callback("encode works")583 socket = new Socket("/socket", {transport: LongPoll, encode: encoder})584 let payload = {topic: "topic", ref: "2", join_ref: "1", event: "join", payload: {foo: "bar"}}585 socket.encode(payload, encoded => {586 assert.deepStrictEqual(encoded, '["1","2","topic","join",{"foo":"bar"}]')587 })588 })589 it("decodes JSON by default", () => {590 socket = new Socket("/socket")591 let encoded = '["1","2","topic","join",{"foo":"bar"}]'592 socket.decode(encoded, decoded => {593 assert.deepStrictEqual(decoded, {topic: "topic", ref: "2", join_ref: "1", event: "join", payload: {foo: "bar"}})594 })595 })596 it("allows custom decoding when using WebSocket transport", () => {597 let decoder = (payload, callback) => callback("decode works")598 socket = new Socket("/socket", {transport: WebSocket, decode: decoder})599 socket.decode("...esoteric format...", decoded => {600 assert.deepStrictEqual(decoded, "decode works")601 })602 })603 it("forces JSON decoding when using LongPoll transport", () => {604 let decoder = (payload, callback) => callback("decode works")605 socket = new Socket("/socket", {transport: LongPoll, decode: decoder})606 let payload = {topic: "topic", ref: "2", join_ref: "1", event: "join", payload: {foo: "bar"}}607 socket.decode('["1","2","topic","join",{"foo":"bar"}]', decoded => {608 assert.deepStrictEqual(decoded, payload)609 })610 })...
connection.js
Source:connection.js
...81 socket.emit('getUtf8');82 });83 it('should connect to a namespace after connection established', function (done) {84 var manager = io.Manager();85 var socket = manager.socket('/');86 socket.on('connect', function () {87 var foo = manager.socket('/foo');88 foo.on('connect', function () {89 foo.close();90 socket.close();91 manager.close();92 done();93 });94 });95 });96 it('should open a new namespace after connection gets closed', function (done) {97 var manager = io.Manager();98 var socket = manager.socket('/');99 socket.on('connect', function () {100 socket.disconnect();101 }).on('disconnect', function () {102 var foo = manager.socket('/foo');103 foo.on('connect', function () {104 foo.disconnect();105 manager.close();106 done();107 });108 });109 });110 it('should reconnect by default', function (done) {111 var socket = io({ forceNew: true });112 socket.io.on('reconnect', function () {113 socket.disconnect();114 done();115 });116 setTimeout(function () {117 socket.io.engine.close();118 }, 500);119 });120 it('should reconnect manually', function (done) {121 var socket = io({ forceNew: true });122 socket.once('connect', function () {123 socket.disconnect();124 }).once('disconnect', function () {125 socket.once('connect', function () {126 socket.disconnect();127 done();128 });129 socket.connect();130 });131 });132 it('should reconnect automatically after reconnecting manually', function (done) {133 var socket = io({ forceNew: true });134 socket.once('connect', function () {135 socket.disconnect();136 }).once('disconnect', function () {137 socket.on('reconnect', function () {138 socket.disconnect();139 done();140 });141 socket.connect();142 setTimeout(function () {143 socket.io.engine.close();144 }, 500);145 });146 });147 it('should attempt reconnects after a failed reconnect', function (done) {148 var manager = io.Manager({ reconnection: true, timeout: 0, reconnectionAttempts: 2, reconnectionDelay: 10 });149 var socket = manager.socket('/timeout');150 socket.once('reconnect_failed', function () {151 var reconnects = 0;152 var reconnectCb = function () {153 reconnects++;154 };155 manager.on('reconnect_attempt', reconnectCb);156 manager.on('reconnect_failed', function failed () {157 expect(reconnects).to.be(2);158 socket.close();159 manager.close();160 done();161 });162 socket.connect();163 });164 });165 it('reconnect delay should increase every time', function (done) {166 var manager = io.Manager({ reconnection: true, timeout: 0, reconnectionAttempts: 3, reconnectionDelay: 100, randomizationFactor: 0.2 });167 var socket = manager.socket('/timeout');168 var reconnects = 0;169 var increasingDelay = true;170 var startTime;171 var prevDelay = 0;172 socket.on('connect_error', function () {173 startTime = new Date().getTime();174 });175 socket.on('reconnect_attempt', function () {176 reconnects++;177 var currentTime = new Date().getTime();178 var delay = currentTime - startTime;179 if (delay <= prevDelay) {180 increasingDelay = false;181 }182 prevDelay = delay;183 });184 socket.on('reconnect_failed', function failed () {185 expect(reconnects).to.be(3);186 expect(increasingDelay).to.be.ok();187 socket.close();188 manager.close();189 done();190 });191 });192 it('reconnect event should fire in socket', function (done) {193 var socket = io({ forceNew: true });194 socket.on('reconnect', function () {195 socket.disconnect();196 done();197 });198 setTimeout(function () {199 socket.io.engine.close();200 }, 500);201 });202 it('should not reconnect when force closed', function (done) {203 var socket = io('/invalid', { forceNew: true, timeout: 0, reconnectionDelay: 10 });204 socket.on('connect_error', function () {205 socket.on('reconnect_attempt', function () {206 expect().fail();207 });208 socket.disconnect();209 // set a timeout to let reconnection possibly fire210 setTimeout(function () {211 done();212 }, 500);213 });214 });215 it('should stop reconnecting when force closed', function (done) {216 var socket = io('/invalid', { forceNew: true, timeout: 0, reconnectionDelay: 10 });217 socket.once('reconnect_attempt', function () {218 socket.on('reconnect_attempt', function () {219 expect().fail();220 });221 socket.disconnect();222 // set a timeout to let reconnection possibly fire223 setTimeout(function () {224 done();225 }, 500);226 });227 });228 it('should reconnect after stopping reconnection', function (done) {229 var socket = io('/invalid', { forceNew: true, timeout: 0, reconnectionDelay: 10 });230 socket.once('reconnect_attempt', function () {231 socket.on('reconnect_attempt', function () {232 socket.disconnect();233 done();234 });235 socket.disconnect();236 socket.connect();237 });238 });239 it('should stop reconnecting on a socket and keep to reconnect on another', function (done) {240 var manager = io.Manager();241 var socket1 = manager.socket('/');242 var socket2 = manager.socket('/asd');243 manager.on('reconnect_attempt', function () {244 socket1.on('connect', function () {245 expect().fail();246 });247 socket2.on('connect', function () {248 setTimeout(function () {249 socket2.disconnect();250 manager.disconnect();251 done();252 }, 500);253 });254 socket1.disconnect();255 });256 setTimeout(function () {257 manager.engine.close();258 }, 1000);259 });260 it('should try to reconnect twice and fail when requested two attempts with immediate timeout and reconnect enabled', function (done) {261 var manager = io.Manager({ reconnection: true, timeout: 0, reconnectionAttempts: 2, reconnectionDelay: 10 });262 var socket;263 var reconnects = 0;264 var reconnectCb = function () {265 reconnects++;266 };267 manager.on('reconnect_attempt', reconnectCb);268 manager.on('reconnect_failed', function failed () {269 expect(reconnects).to.be(2);270 socket.close();271 manager.close();272 done();273 });274 socket = manager.socket('/timeout');275 });276 it('should fire reconnect_* events on socket', function (done) {277 var manager = io.Manager({ reconnection: true, timeout: 0, reconnectionAttempts: 2, reconnectionDelay: 10 });278 var socket = manager.socket('/timeout_socket');279 var reconnects = 0;280 var reconnectCb = function (attempts) {281 reconnects++;282 expect(attempts).to.be(reconnects);283 };284 socket.on('reconnect_attempt', reconnectCb);285 socket.on('reconnect_failed', function failed () {286 expect(reconnects).to.be(2);287 socket.close();288 manager.close();289 done();290 });291 });292 it('should fire error on socket', function (done) {293 var manager = io.Manager({ reconnection: true });294 var socket = manager.socket('/timeout_socket');295 socket.on('error', function (data) {296 expect(data.code).to.be('test');297 socket.close();298 manager.close();299 done();300 });301 socket.on('connect', function () {302 manager.engine.onPacket({ type: 'error', data: 'test' });303 });304 });305 it('should fire reconnecting (on socket) with attempts number when reconnecting twice', function (done) {306 var manager = io.Manager({ reconnection: true, timeout: 0, reconnectionAttempts: 2, reconnectionDelay: 10 });307 var socket = manager.socket('/timeout_socket');308 var reconnects = 0;309 var reconnectCb = function (attempts) {310 reconnects++;311 expect(attempts).to.be(reconnects);312 };313 socket.on('reconnecting', reconnectCb);314 socket.on('reconnect_failed', function failed () {315 expect(reconnects).to.be(2);316 socket.close();317 manager.close();318 done();319 });320 });321 it('should not try to reconnect and should form a connection when connecting to correct port with default timeout', function (done) {322 var manager = io.Manager({ reconnection: true, reconnectionDelay: 10 });323 var cb = function () {324 socket.close();325 expect().fail();326 };327 manager.on('reconnect_attempt', cb);328 var socket = manager.socket('/valid');329 socket.on('connect', function () {330 // set a timeout to let reconnection possibly fire331 setTimeout(function () {332 socket.close();333 manager.close();334 done();335 }, 1000);336 });337 });338 it('should connect while disconnecting another socket', function (done) {339 var manager = io.Manager();340 var socket1 = manager.socket('/foo');341 socket1.on('connect', function () {342 var socket2 = manager.socket('/asd');343 socket2.on('connect', done);344 socket1.disconnect();345 });346 });347 // Ignore incorrect connection test for old IE due to no support for348 // `script.onerror` (see: http://requirejs.org/docs/api.html#ieloadfail)349 if (!global.document || hasCORS) {350 it('should try to reconnect twice and fail when requested two attempts with incorrect address and reconnect enabled', function (done) {351 var manager = io.Manager('http://localhost:3940', { reconnection: true, reconnectionAttempts: 2, reconnectionDelay: 10 });352 var socket = manager.socket('/asd');353 var reconnects = 0;354 var cb = function () {355 reconnects++;356 };357 manager.on('reconnect_attempt', cb);358 manager.on('reconnect_failed', function () {359 expect(reconnects).to.be(2);360 socket.disconnect();361 manager.close();362 done();363 });364 });365 it('should not try to reconnect with incorrect port when reconnection disabled', function (done) {366 var manager = io.Manager('http://localhost:9823', { reconnection: false });367 var cb = function () {368 socket.close();369 expect().fail();370 };371 manager.on('reconnect_attempt', cb);372 manager.on('connect_error', function () {373 // set a timeout to let reconnection possibly fire374 setTimeout(function () {375 socket.disconnect();376 manager.close();377 done();378 }, 1000);379 });380 var socket = manager.socket('/invalid');381 });382 }383 it('should emit date as string', function (done) {384 var socket = io({ forceNew: true });385 socket.on('takeDate', function (data) {386 socket.close();387 expect(data).to.be.a('string');388 done();389 });390 socket.emit('getDate');391 });392 it('should emit date in object', function (done) {393 var socket = io({ forceNew: true });394 socket.on('takeDateObj', function (data) {...
agent.js
Source:agent.js
1'use strict';2const OriginalAgent = require('http').Agent;3const ms = require('humanize-ms');4const debug = require('debug')('agentkeepalive');5const deprecate = require('depd')('agentkeepalive');6const {7 INIT_SOCKET,8 CURRENT_ID,9 CREATE_ID,10 SOCKET_CREATED_TIME,11 SOCKET_NAME,12 SOCKET_REQUEST_COUNT,13 SOCKET_REQUEST_FINISHED_COUNT,14} = require('./constants');15// OriginalAgent come from16// - https://github.com/nodejs/node/blob/v8.12.0/lib/_http_agent.js17// - https://github.com/nodejs/node/blob/v10.12.0/lib/_http_agent.js18// node <= 1019let defaultTimeoutListenerCount = 1;20const majorVersion = parseInt(process.version.split('.', 1)[0].substring(1));21if (majorVersion >= 11 && majorVersion <= 12) {22 defaultTimeoutListenerCount = 2;23} else if (majorVersion >= 13) {24 defaultTimeoutListenerCount = 3;25}26class Agent extends OriginalAgent {27 constructor(options) {28 options = options || {};29 options.keepAlive = options.keepAlive !== false;30 // default is keep-alive and 4s free socket timeout31 // see https://medium.com/ssense-tech/reduce-networking-errors-in-nodejs-23b4eb9f2d8332 if (options.freeSocketTimeout === undefined) {33 options.freeSocketTimeout = 4000;34 }35 // Legacy API: keepAliveTimeout should be rename to `freeSocketTimeout`36 if (options.keepAliveTimeout) {37 deprecate('options.keepAliveTimeout is deprecated, please use options.freeSocketTimeout instead');38 options.freeSocketTimeout = options.keepAliveTimeout;39 delete options.keepAliveTimeout;40 }41 // Legacy API: freeSocketKeepAliveTimeout should be rename to `freeSocketTimeout`42 if (options.freeSocketKeepAliveTimeout) {43 deprecate('options.freeSocketKeepAliveTimeout is deprecated, please use options.freeSocketTimeout instead');44 options.freeSocketTimeout = options.freeSocketKeepAliveTimeout;45 delete options.freeSocketKeepAliveTimeout;46 }47 // Sets the socket to timeout after timeout milliseconds of inactivity on the socket.48 // By default is double free socket timeout.49 if (options.timeout === undefined) {50 // make sure socket default inactivity timeout >= 8s51 options.timeout = Math.max(options.freeSocketTimeout * 2, 8000);52 }53 // support humanize format54 options.timeout = ms(options.timeout);55 options.freeSocketTimeout = ms(options.freeSocketTimeout);56 options.socketActiveTTL = options.socketActiveTTL ? ms(options.socketActiveTTL) : 0;57 super(options);58 this[CURRENT_ID] = 0;59 // create socket success counter60 this.createSocketCount = 0;61 this.createSocketCountLastCheck = 0;62 this.createSocketErrorCount = 0;63 this.createSocketErrorCountLastCheck = 0;64 this.closeSocketCount = 0;65 this.closeSocketCountLastCheck = 0;66 // socket error event count67 this.errorSocketCount = 0;68 this.errorSocketCountLastCheck = 0;69 // request finished counter70 this.requestCount = 0;71 this.requestCountLastCheck = 0;72 // including free socket timeout counter73 this.timeoutSocketCount = 0;74 this.timeoutSocketCountLastCheck = 0;75 this.on('free', socket => {76 // https://github.com/nodejs/node/pull/3200077 // Node.js native agent will check socket timeout eqs agent.options.timeout.78 // Use the ttl or freeSocketTimeout to overwrite.79 const timeout = this.calcSocketTimeout(socket);80 if (timeout > 0 && socket.timeout !== timeout) {81 socket.setTimeout(timeout);82 }83 });84 }85 get freeSocketKeepAliveTimeout() {86 deprecate('agent.freeSocketKeepAliveTimeout is deprecated, please use agent.options.freeSocketTimeout instead');87 return this.options.freeSocketTimeout;88 }89 get timeout() {90 deprecate('agent.timeout is deprecated, please use agent.options.timeout instead');91 return this.options.timeout;92 }93 get socketActiveTTL() {94 deprecate('agent.socketActiveTTL is deprecated, please use agent.options.socketActiveTTL instead');95 return this.options.socketActiveTTL;96 }97 calcSocketTimeout(socket) {98 /**99 * return <= 0: should free socket100 * return > 0: should update socket timeout101 * return undefined: not find custom timeout102 */103 let freeSocketTimeout = this.options.freeSocketTimeout;104 const socketActiveTTL = this.options.socketActiveTTL;105 if (socketActiveTTL) {106 // check socketActiveTTL107 const aliveTime = Date.now() - socket[SOCKET_CREATED_TIME];108 const diff = socketActiveTTL - aliveTime;109 if (diff <= 0) {110 return diff;111 }112 if (freeSocketTimeout && diff < freeSocketTimeout) {113 freeSocketTimeout = diff;114 }115 }116 // set freeSocketTimeout117 if (freeSocketTimeout) {118 // set free keepalive timer119 // try to use socket custom freeSocketTimeout first, support headers['keep-alive']120 // https://github.com/node-modules/urllib/blob/b76053020923f4d99a1c93cf2e16e0c5ba10bacf/lib/urllib.js#L498121 const customFreeSocketTimeout = socket.freeSocketTimeout || socket.freeSocketKeepAliveTimeout;122 return customFreeSocketTimeout || freeSocketTimeout;123 }124 }125 keepSocketAlive(socket) {126 const result = super.keepSocketAlive(socket);127 // should not keepAlive, do nothing128 if (!result) return result;129 const customTimeout = this.calcSocketTimeout(socket);130 if (typeof customTimeout === 'undefined') {131 return true;132 }133 if (customTimeout <= 0) {134 debug('%s(requests: %s, finished: %s) free but need to destroy by TTL, request count %s, diff is %s',135 socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], customTimeout);136 return false;137 }138 if (socket.timeout !== customTimeout) {139 socket.setTimeout(customTimeout);140 }141 return true;142 }143 // only call on addRequest144 reuseSocket(...args) {145 // reuseSocket(socket, req)146 super.reuseSocket(...args);147 const socket = args[0];148 const req = args[1];149 req.reusedSocket = true;150 const agentTimeout = this.options.timeout;151 if (getSocketTimeout(socket) !== agentTimeout) {152 // reset timeout before use153 socket.setTimeout(agentTimeout);154 debug('%s reset timeout to %sms', socket[SOCKET_NAME], agentTimeout);155 }156 socket[SOCKET_REQUEST_COUNT]++;157 debug('%s(requests: %s, finished: %s) reuse on addRequest, timeout %sms',158 socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT],159 getSocketTimeout(socket));160 }161 [CREATE_ID]() {162 const id = this[CURRENT_ID]++;163 if (this[CURRENT_ID] === Number.MAX_SAFE_INTEGER) this[CURRENT_ID] = 0;164 return id;165 }166 [INIT_SOCKET](socket, options) {167 // bugfix here.168 // https on node 8, 10 won't set agent.options.timeout by default169 // TODO: need to fix on node itself170 if (options.timeout) {171 const timeout = getSocketTimeout(socket);172 if (!timeout) {173 socket.setTimeout(options.timeout);174 }175 }176 if (this.options.keepAlive) {177 // Disable Nagle's algorithm: http://blog.caustik.com/2012/04/08/scaling-node-js-to-100k-concurrent-connections/178 // https://fengmk2.com/benchmark/nagle-algorithm-delayed-ack-mock.html179 socket.setNoDelay(true);180 }181 this.createSocketCount++;182 if (this.options.socketActiveTTL) {183 socket[SOCKET_CREATED_TIME] = Date.now();184 }185 // don't show the hole '-----BEGIN CERTIFICATE----' key string186 socket[SOCKET_NAME] = `sock[${this[CREATE_ID]()}#${options._agentKey}]`.split('-----BEGIN', 1)[0];187 socket[SOCKET_REQUEST_COUNT] = 1;188 socket[SOCKET_REQUEST_FINISHED_COUNT] = 0;189 installListeners(this, socket, options);190 }191 createConnection(options, oncreate) {192 let called = false;193 const onNewCreate = (err, socket) => {194 if (called) return;195 called = true;196 if (err) {197 this.createSocketErrorCount++;198 return oncreate(err);199 }200 this[INIT_SOCKET](socket, options);201 oncreate(err, socket);202 };203 const newSocket = super.createConnection(options, onNewCreate);204 if (newSocket) onNewCreate(null, newSocket);205 }206 get statusChanged() {207 const changed = this.createSocketCount !== this.createSocketCountLastCheck ||208 this.createSocketErrorCount !== this.createSocketErrorCountLastCheck ||209 this.closeSocketCount !== this.closeSocketCountLastCheck ||210 this.errorSocketCount !== this.errorSocketCountLastCheck ||211 this.timeoutSocketCount !== this.timeoutSocketCountLastCheck ||212 this.requestCount !== this.requestCountLastCheck;213 if (changed) {214 this.createSocketCountLastCheck = this.createSocketCount;215 this.createSocketErrorCountLastCheck = this.createSocketErrorCount;216 this.closeSocketCountLastCheck = this.closeSocketCount;217 this.errorSocketCountLastCheck = this.errorSocketCount;218 this.timeoutSocketCountLastCheck = this.timeoutSocketCount;219 this.requestCountLastCheck = this.requestCount;220 }221 return changed;222 }223 getCurrentStatus() {224 return {225 createSocketCount: this.createSocketCount,226 createSocketErrorCount: this.createSocketErrorCount,227 closeSocketCount: this.closeSocketCount,228 errorSocketCount: this.errorSocketCount,229 timeoutSocketCount: this.timeoutSocketCount,230 requestCount: this.requestCount,231 freeSockets: inspect(this.freeSockets),232 sockets: inspect(this.sockets),233 requests: inspect(this.requests),234 };235 }236}237// node 8 don't has timeout attribute on socket238// https://github.com/nodejs/node/pull/21204/files#diff-e6ef024c3775d787c38487a6309e491dR408239function getSocketTimeout(socket) {240 return socket.timeout || socket._idleTimeout;241}242function installListeners(agent, socket, options) {243 debug('%s create, timeout %sms', socket[SOCKET_NAME], getSocketTimeout(socket));244 // listener socket events: close, timeout, error, free245 function onFree() {246 // create and socket.emit('free') logic247 // https://github.com/nodejs/node/blob/master/lib/_http_agent.js#L311248 // no req on the socket, it should be the new socket249 if (!socket._httpMessage && socket[SOCKET_REQUEST_COUNT] === 1) return;250 socket[SOCKET_REQUEST_FINISHED_COUNT]++;251 agent.requestCount++;252 debug('%s(requests: %s, finished: %s) free',253 socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT]);254 // should reuse on pedding requests?255 const name = agent.getName(options);256 if (socket.writable && agent.requests[name] && agent.requests[name].length) {257 // will be reuse on agent free listener258 socket[SOCKET_REQUEST_COUNT]++;259 debug('%s(requests: %s, finished: %s) will be reuse on agent free event',260 socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT]);261 }262 }263 socket.on('free', onFree);264 function onClose(isError) {265 debug('%s(requests: %s, finished: %s) close, isError: %s',266 socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], isError);267 agent.closeSocketCount++;268 }269 socket.on('close', onClose);270 // start socket timeout handler271 function onTimeout() {272 // onTimeout and emitRequestTimeout(_http_client.js)273 // https://github.com/nodejs/node/blob/v12.x/lib/_http_client.js#L711274 const listenerCount = socket.listeners('timeout').length;275 // node <= 10, default listenerCount is 1, onTimeout276 // 11 < node <= 12, default listenerCount is 2, onTimeout and emitRequestTimeout277 // node >= 13, default listenerCount is 3, onTimeout,278 // onTimeout(https://github.com/nodejs/node/pull/32000/files#diff-5f7fb0850412c6be189faeddea6c5359R333)279 // and emitRequestTimeout280 const timeout = getSocketTimeout(socket);281 const req = socket._httpMessage;282 const reqTimeoutListenerCount = req && req.listeners('timeout').length || 0;283 debug('%s(requests: %s, finished: %s) timeout after %sms, listeners %s, defaultTimeoutListenerCount %s, hasHttpRequest %s, HttpRequest timeoutListenerCount %s',284 socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT],285 timeout, listenerCount, defaultTimeoutListenerCount, !!req, reqTimeoutListenerCount);286 if (debug.enabled) {287 debug('timeout listeners: %s', socket.listeners('timeout').map(f => f.name).join(', '));288 }289 agent.timeoutSocketCount++;290 const name = agent.getName(options);291 if (agent.freeSockets[name] && agent.freeSockets[name].indexOf(socket) !== -1) {292 // free socket timeout, destroy quietly293 socket.destroy();294 // Remove it from freeSockets list immediately to prevent new requests295 // from being sent through this socket.296 agent.removeSocket(socket, options);297 debug('%s is free, destroy quietly', socket[SOCKET_NAME]);298 } else {299 // if there is no any request socket timeout handler,300 // agent need to handle socket timeout itself.301 //302 // custom request socket timeout handle logic must follow these rules:303 // 1. Destroy socket first304 // 2. Must emit socket 'agentRemove' event tell agent remove socket305 // from freeSockets list immediately.306 // Otherise you may be get 'socket hang up' error when reuse307 // free socket and timeout happen in the same time.308 if (reqTimeoutListenerCount === 0) {309 const error = new Error('Socket timeout');310 error.code = 'ERR_SOCKET_TIMEOUT';311 error.timeout = timeout;312 // must manually call socket.end() or socket.destroy() to end the connection.313 // https://nodejs.org/dist/latest-v10.x/docs/api/net.html#net_socket_settimeout_timeout_callback314 socket.destroy(error);315 agent.removeSocket(socket, options);316 debug('%s destroy with timeout error', socket[SOCKET_NAME]);317 }318 }319 }320 socket.on('timeout', onTimeout);321 function onError(err) {322 const listenerCount = socket.listeners('error').length;323 debug('%s(requests: %s, finished: %s) error: %s, listenerCount: %s',324 socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT],325 err, listenerCount);326 agent.errorSocketCount++;327 if (listenerCount === 1) {328 // if socket don't contain error event handler, don't catch it, emit it again329 debug('%s emit uncaught error event', socket[SOCKET_NAME]);330 socket.removeListener('error', onError);331 socket.emit('error', err);332 }333 }334 socket.on('error', onError);335 function onRemove() {336 debug('%s(requests: %s, finished: %s) agentRemove',337 socket[SOCKET_NAME],338 socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT]);339 // We need this function for cases like HTTP 'upgrade'340 // (defined by WebSockets) where we need to remove a socket from the341 // pool because it'll be locked up indefinitely342 socket.removeListener('close', onClose);343 socket.removeListener('error', onError);344 socket.removeListener('free', onFree);345 socket.removeListener('timeout', onTimeout);346 socket.removeListener('agentRemove', onRemove);347 }348 socket.on('agentRemove', onRemove);349}350module.exports = Agent;351function inspect(obj) {352 const res = {};353 for (const key in obj) {354 res[key] = obj[key].length;355 }356 return res;...
chatServer.js
Source:chatServer.js
1// Require the packages we will use:2const http = require("http"),3fs = require("fs");4const { SocketAddress } = require("net");5const port = 3456;6const file = "chatClient.html";7// Listen for HTTP connections. This is essentially a miniature static file server that only serves our one file, client.html, on port 3456:8const server = http.createServer(function (req, res) {9 // This callback runs when a new connection is made to our HTTP server.10 fs.readFile(file, function (err, data) {11 // This callback runs when the client.html file has been read from the filesystem.12 if (err) return res.writeHead(500);13 res.writeHead(200);14 res.end(data);15 });16});17server.listen(port);18// Import Socket.IO and pass our HTTP server object to it.19const socketio = require("socket.io")(http, {20 wsEngine: 'ws'21});22// Attach our Socket.IO server to our HTTP server to listen23const io = socketio.listen(server);24let starterRooms = [{"name" : "Home"}, {"name" : "Room2"}];25let joinedSocketId = {};26let socketIds = {};27let currUsers = {};28let listOfRooms = {};29let setSocketIds = new Set();30io.sockets.on("connection", function (socket) {31 // This callback runs when a new Socket.IO connection is established.32 socket.on("newUser", function(username){33 if(username == ""){34 socket.emit("displayInformation", "You must enter a username. Refresh the page and try again.")35 }36 let newUser = {};37 //let newUser = username["userName"]38 newUser.username = username; 39 newUser.room = "Home";40 //console.log("Current Users:", currUsers);41 socket.room = "Home";42 socket.join("Home");43 setSocketIds.add(socket.id);44 socket.username = username;45 socket.bannedFrom = new Set();46 socketIds[username] = socket.id;47 currUsers[username] = newUser;48 socket.to("Home").emit('displayInfo', username + ' has joined to this room');49 newUser.room= socket.room;50 currUsers[username] = newUser;51 io.to(socket.id).emit("updateRoomDisplay", socket.room, starterRooms);52 io.to(socket.room).emit("displayWhoInRoom", getWhoInRoom(socket.room));53 });54 socket.on('message_to_server', function (data) {55 // This callback runs when the server receives a new message from the client.56 console.log("message123: " + data["message"]);57 console.log("Room: " + socket.room)// log it to the Node.JS output58 //this function iterates through every socket that exists and checks to see if it is in the current room59 //not very efficient but idrc60 if(data["message"] == "/currentusers"){61 inRoom = getWhoInRoom(socket.room)62 io.to(socket.id).emit("displayInfo", "Current Occupents of Room: " + inRoom);63 return;64 }65 //basic broadcast66 io.to(socket.room).emit("message_to_client", socket.username, {message: data["message"]});67 });68 socket.on("changeRoom", function(roomToChangeTo){69 if(socket.bannedFrom.has(roomToChangeTo)){70 io.sockets.in(socket.room).emit("displayInfo", "You may not enter that room, you have been banned.");71 return;72 }73 console.log("Changing rooms to: " + roomToChangeTo);74 socket.to(socket.room).emit("displayInfo", socket.username + " has left the room.");75 socket.leave(socket.room)76 socket.join(roomToChangeTo);77 socket.room = roomToChangeTo;78 currUsers[socket.username].room = roomToChangeTo;79 socket.to(roomToChangeTo).emit("displayInfo", socket.username + " has joined the room.");80 socket.emit('updateRoomDisplay', roomToChangeTo, starterRooms);81 io.to(socket.room).emit("displayWhoInRoom", getWhoInRoom(socket.room));82 });83 socket.on("addRoom", function(roomName){84 listOfRooms[roomName] = socket.username;85 starterRooms.push({name:roomName, creator: socket.username});86 io.emit("updateRoomDisplay", socket.room, starterRooms);87 });88 socket.on("kick", function(usernameToKick){89 if(socket.room == "Home"){90 console.log("You are in room: " + socket.room);91 socket.emit("improperPermission");92 return;93 }94 if(socket.username != listOfRooms[socket.room]){95 console.log("Recorded Owner Of Room: " + listOfRooms[socket.room]);96 console.log("User that tried to kick: " + socket.username)97 socket.emit("improperPermission");98 return;99 }100 let kickedUser = io.sockets.connected[socketIds[usernameToKick]]101 if(kickedUser == null){102 io.to(socket.id).emit("displayInfo", "User does not exist."); 103 return; 104 }105 if(kickedUser.room != socket.room){106 io.to(socket.id).emit("displayInfo", "That user is not in your room"); 107 return; 108 }109 console.log("Username to Kick: " + usernameToKick)110 console.log("Socket ID: " + socketIds[usernameToKick])111 kickedUser.leave(kickedUser.room);112 kickedUser.join("Home");113 kickedUser.room = "Home";114 console.log("Kicked Users new room: " + kickedUser.room + " (should be home)")115 io.to(socketIds[usernameToKick]).emit("updateRoomDisplay", "Home", starterRooms)116 io.to(socket.room).emit("displayInfo", "User has been kicked.");117 io.to(socket.room).emit("displayWhoInRoom", getWhoInRoom(socket.room));118 io.to(kickedUser.room).emit("displayWhoInRoom", getWhoInRoom(socket.room));119 io.to(socketIds[usernameToKick]).emit("displayInfo", "You have been kicked from the room.");120 });121 socket.on("ban", function(usernameToBan){122 if(socket.room == "Home"){123 console.log("You are in room: " + socket.room);124 socket.emit("improperPermission");125 return;126 }127 if(socket.username != listOfRooms[socket.room]){128 console.log("Recorded Owner Of Room: " + listOfRooms[socket.room]);129 console.log("User that tried to kick: " + socket.username)130 socket.emit("improperPermission");131 return;132 } 133 let kickedUser = io.sockets.connected[socketIds[usernameToBan]]134 if(kickedUser == null){135 io.to(socket.id).emit("displayInfo", "User does not exist."); 136 return; 137 }138 if(kickedUser.room != socket.room){139 io.to(socket.id).emit("displayInfo", "That user is not in your room"); 140 return; 141 }142 console.log("Username to Ban: " + usernameToBan)143 console.log("Socket ID: " + socketIds[usernameToBan])144 kickedUser.leave(kickedUser.room);145 kickedUser.join("Home");146 kickedUser.room = "Home";147 kickedUser.bannedFrom.add(socket.room);148 io.to(socketIds[usernameToBan]).emit("updateRoomDisplay", "Home", starterRooms)149 io.to(socket.room).emit("displayInfo", "User has been banned.");150 io.to(socket.room).emit("displayWhoInRoom", getWhoInRoom(socket.room));151 io.to(kickedUser.room).emit("displayWhoInRoom", getWhoInRoom(socket.room));152 io.to(socketIds[usernameToBan]).emit("displayInfo", "You have been banned from that room.");153 })154 socket.on("disconnect", function(){155 setSocketIds.delete(socket.id);156 io.to(socket.room).emit("displayWhoInRoom", getWhoInRoom(socket.room));157 console.log(socket.username + " has disconnected.");158 })159 function getWhoInRoom(currentRoom){160 let inRoom = "";161 setSocketIds.forEach(id =>{162 let randomSocket = io.sockets.connected[id];163 if(randomSocket.room == currentRoom){164 inRoom = inRoom + " " + randomSocket.username;165 } 166 })167 inRoom.replace("null", "");168 return inRoom;169 }170 socket.on("joinPrivateRoom", function(privateRoom, guess){171 //every private room should open a prompt onclick, redirect to that function in the html172 console.log("in joinPrivateRoom (js)")173 for(var i=0; i<starterRooms.length; i++){174 console.log(starterRooms[i].hasOwnProperty('password'));175 if(starterRooms[i].name == privateRoom){176 if(starterRooms[i].hasOwnProperty('password')){177 //check password guess with real password178 if(starterRooms[i].password == guess){179 //currUsers[socket.user].room = room_name;180 console.log("password approved");181 socket.broadcast.to(socket.room).emit("displayInfo", socket.username + ' has left this room');182 socket.leave(socket.room);183 console.log(socket.user + " left room: " + socket.room);184 socket.join(privateRoom);185 socket.room = privateRoom;186 currUsers[socket.username].room = privateRoom;187 //socket.to(socket.room).emit("displayInfo", socket.username + " has joined this room.");188 189 socket.to(privateRoom).emit("displayInfo", socket.username + " has joined the room.");190 socket.emit('updateRoomDisplay', privateRoom, starterRooms);191 io.to(socket.room).emit("displayWhoInRoom", getWhoInRoom(socket.room));192 //socket.broadcast.to(privateRoom).emit("displayInfo", socket.username + ' has joined this room');193 return;194 } else {195 socket.emit("displayInfo", 'wrong password for ' +privateRoom);196 return;197 }198 }199 }200 201 }202 });203 socket.on("addWithPassword", function(roomName, password){204 starterRooms.push({name:roomName, creator: socket.username, password: password});205 listOfRooms[roomName] = socket.username;206 //io.emit('addRoom', starterRooms, socket.room);207 //socket.emit("updateRoomDisplay", socket.room, starterRooms);208 io.emit("updateRoomDisplay", socket.room, starterRooms);209 });210 211 socket.on("pm", function(to, msg){212 let from = socket.username;213 io.to(socketIds[to]).emit('sendPM', from, msg);214 });215 socket.on("passOnCreator", function(newCreator){216 listOfRooms[socket.room] = newCreator;217 for(var i = 0; i < starterRooms.length; i++){218 if(starterRooms[i].name == socket.room){219 if(starterRooms[i].creator == socket.username){220 starterRooms[i].creator = newCreator;221 }222 else {223 console.log("Recorded creator Of Room: " + starterRooms[i].creator);224 console.log("User that tried to give privileges: " + socket.username)225 socket.emit("improperPermission");226 }227 } 228 }229 console.log("New creator for room " + socket.room + " : " + newCreator);230 });231 socket.on("deleteRoom", function(room_name){232 if(room_name == "Home"){233 console.log("You are in the home room");234 io.to(socket.id).emit("displayInfo", "You can't delete the home room"); 235 return;236 }237 for(var i=0; i<starterRooms.length; i++){238 if(starterRooms[i].name == room_name){239 //find room to be deleted in the array of rooms240 if(socket.username != starterRooms[i].creator){241 console.log("Recorded Owner Of Room: " + starterRooms[i].creator);242 console.log("User that tried to delete room: " + socket.username)243 socket.emit("improperPermission");244 return; 245 }246 else{247 //iterate through connected sockets and move them to the home room.248 setSocketIds.forEach(id =>{249 if(io.sockets.connected[id].room == room_name){250 io.sockets.connected[id].leave(room_name);251 io.sockets.connected[id].join("Home");252 io.to(socket.id).emit("displayInfo", "The room you were in has been deleted. Click a room to join."); 253 }254 })255 starterRooms.splice(i,1);256 io.sockets.emit("updateRoomDisplay", socket.room, starterRooms);257 }258 } 259 }260 //go through all the users in this room and leave room and put them back in home261 262 //run thru the chat rooms array to remove room263 /*264 for (let i in starterRooms){265 if(starterRooms[i].name==room_name){266 starterRooms.splice(i,1);267 }268 }269 */270 io.sockets.emit("updateRoomDisplay", socket.room, starterRooms);271 });...
user.js
Source:user.js
1'use strict';2var async = require('async');3var winston = require('winston');4var user = require('../user');5var topics = require('../topics');6var notifications = require('../notifications');7var messaging = require('../messaging');8var plugins = require('../plugins');9var meta = require('../meta');10var events = require('../events');11var emailer = require('../emailer');12var db = require('../database');13var userController = require('../controllers/user');14var privileges = require('../privileges');15var SocketUser = module.exports;16require('./user/profile')(SocketUser);17require('./user/search')(SocketUser);18require('./user/status')(SocketUser);19require('./user/picture')(SocketUser);20require('./user/ban')(SocketUser);21SocketUser.exists = function (socket, data, callback) {22 if (!data || !data.username) {23 return callback(new Error('[[error:invalid-data]]'));24 }25 meta.userOrGroupExists(data.username, callback);26};27SocketUser.deleteAccount = function (socket, data, callback) {28 if (!socket.uid) {29 return callback(new Error('[[error:no-privileges]]'));30 }31 async.waterfall([32 function (next) {33 user.isPasswordCorrect(socket.uid, data.password, function (err, ok) {34 next(err || !ok ? new Error('[[error:invalid-password]]') : undefined);35 });36 },37 function (next) {38 user.isAdministrator(socket.uid, next);39 },40 function (isAdmin, next) {41 if (isAdmin) {42 return next(new Error('[[error:cant-delete-admin]]'));43 }44 user.deleteAccount(socket.uid, next);45 },46 function (next) {47 require('./index').server.sockets.emit('event:user_status_change', { uid: socket.uid, status: 'offline' });48 events.log({49 type: 'user-delete',50 uid: socket.uid,51 targetUid: socket.uid,52 ip: socket.ip,53 });54 next();55 },56 ], function (err) {57 if (err) {58 return setTimeout(function () {59 callback(err);60 }, 2500);61 }62 callback();63 });64};65SocketUser.emailExists = function (socket, data, callback) {66 if (!data || !data.email) {67 return callback(new Error('[[error:invalid-data]]'));68 }69 user.email.exists(data.email, callback);70};71SocketUser.emailConfirm = function (socket, data, callback) {72 if (!socket.uid) {73 return callback(new Error('[[error:no-privileges]]'));74 }75 if (parseInt(meta.config.requireEmailConfirmation, 10) !== 1) {76 return callback(new Error('[[error:email-confirmations-are-disabled]]'));77 }78 user.email.sendValidationEmail(socket.uid, callback);79};80// Password Reset81SocketUser.reset = {};82SocketUser.reset.send = function (socket, email, callback) {83 if (!email) {84 return callback(new Error('[[error:invalid-data]]'));85 }86 user.reset.send(email, function (err) {87 if (err) {88 switch (err.message) {89 case '[[error:invalid-email]]':90 winston.warn('[user/reset] Invalid email attempt: ' + email + ' by IP ' + socket.ip + (socket.uid ? ' (uid: ' + socket.uid + ')' : ''));91 err = null;92 break;93 case '[[error:reset-rate-limited]]':94 err = null;95 break;96 }97 }98 setTimeout(callback.bind(err), 2500);99 });100};101SocketUser.reset.commit = function (socket, data, callback) {102 if (!data || !data.code || !data.password) {103 return callback(new Error('[[error:invalid-data]]'));104 }105 var uid;106 async.waterfall([107 function (next) {108 async.parallel({109 uid: async.apply(db.getObjectField, 'reset:uid', data.code),110 reset: async.apply(user.reset.commit, data.code, data.password),111 hook: async.apply(plugins.fireHook, 'action:password.reset', { uid: socket.uid }),112 }, next);113 },114 function (results, next) {115 uid = results.uid;116 events.log({117 type: 'password-reset',118 uid: uid,119 ip: socket.ip,120 });121 user.getUserField(uid, 'username', next);122 },123 function (username, next) {124 var now = new Date();125 var parsedDate = now.getFullYear() + '/' + (now.getMonth() + 1) + '/' + now.getDate();126 emailer.send('reset_notify', uid, {127 username: username,128 date: parsedDate,129 subject: '[[email:reset.notify.subject]]',130 });131 next();132 },133 ], callback);134};135SocketUser.isFollowing = function (socket, data, callback) {136 if (!socket.uid || !data.uid) {137 return callback(null, false);138 }139 user.isFollowing(socket.uid, data.uid, callback);140};141SocketUser.follow = function (socket, data, callback) {142 if (!socket.uid || !data) {143 return callback(new Error('[[error:invalid-data]]'));144 }145 var userData;146 async.waterfall([147 function (next) {148 toggleFollow('follow', socket.uid, data.uid, next);149 },150 function (next) {151 user.getUserFields(socket.uid, ['username', 'userslug'], next);152 },153 function (_userData, next) {154 userData = _userData;155 notifications.create({156 type: 'follow',157 bodyShort: '[[notifications:user_started_following_you, ' + userData.username + ']]',158 nid: 'follow:' + data.uid + ':uid:' + socket.uid,159 from: socket.uid,160 path: '/uid/' + data.uid + '/followers',161 mergeId: 'notifications:user_started_following_you',162 }, next);163 },164 function (notification, next) {165 if (!notification) {166 return next();167 }168 notification.user = userData;169 notifications.push(notification, [data.uid], next);170 },171 ], callback);172};173SocketUser.unfollow = function (socket, data, callback) {174 if (!socket.uid || !data) {175 return callback(new Error('[[error:invalid-data]]'));176 }177 toggleFollow('unfollow', socket.uid, data.uid, callback);178};179function toggleFollow(method, uid, theiruid, callback) {180 async.waterfall([181 function (next) {182 user[method](uid, theiruid, next);183 },184 function (next) {185 plugins.fireHook('action:user.' + method, {186 fromUid: uid,187 toUid: theiruid,188 });189 next();190 },191 ], callback);192}193SocketUser.saveSettings = function (socket, data, callback) {194 if (!socket.uid || !data) {195 return callback(new Error('[[error:invalid-data]]'));196 }197 async.waterfall([198 function (next) {199 privileges.users.canEdit(socket.uid, data.uid, next);200 },201 function (allowed, next) {202 if (!allowed) {203 return next(new Error('[[error:no-privileges]]'));204 }205 user.saveSettings(data.uid, data.settings, next);206 },207 ], callback);208};209SocketUser.setTopicSort = function (socket, sort, callback) {210 user.setSetting(socket.uid, 'topicPostSort', sort, callback);211};212SocketUser.setCategorySort = function (socket, sort, callback) {213 user.setSetting(socket.uid, 'categoryTopicSort', sort, callback);214};215SocketUser.getUnreadCount = function (socket, data, callback) {216 if (!socket.uid) {217 return callback(null, 0);218 }219 topics.getTotalUnread(socket.uid, callback);220};221SocketUser.getUnreadChatCount = function (socket, data, callback) {222 if (!socket.uid) {223 return callback(null, 0);224 }225 messaging.getUnreadCount(socket.uid, callback);226};227SocketUser.getUnreadCounts = function (socket, data, callback) {228 if (!socket.uid) {229 return callback(null, {});230 }231 async.parallel({232 unreadTopicCount: async.apply(topics.getTotalUnread, socket.uid),233 unreadNewTopicCount: async.apply(topics.getTotalUnread, socket.uid, 'new'),234 unreadWatchedTopicCount: async.apply(topics.getTotalUnread, socket.uid, 'watched'),235 unreadChatCount: async.apply(messaging.getUnreadCount, socket.uid),236 unreadNotificationCount: async.apply(user.notifications.getUnreadCount, socket.uid),237 }, callback);238};239SocketUser.invite = function (socket, email, callback) {240 if (!email || !socket.uid) {241 return callback(new Error('[[error:invalid-data]]'));242 }243 var registrationType = meta.config.registrationType;244 if (registrationType !== 'invite-only' && registrationType !== 'admin-invite-only') {245 return callback(new Error('[[error:forum-not-invite-only]]'));246 }247 async.waterfall([248 function (next) {249 user.isAdministrator(socket.uid, next);250 },251 function (isAdmin, next) {252 if (registrationType === 'admin-invite-only' && !isAdmin) {253 return next(new Error('[[error:no-privileges]]'));254 }255 var max = parseInt(meta.config.maximumInvites, 10);256 if (!max) {257 return user.sendInvitationEmail(socket.uid, email, callback);258 }259 async.waterfall([260 function (next) {261 user.getInvitesNumber(socket.uid, next);262 },263 function (invites, next) {264 if (!isAdmin && invites >= max) {265 return next(new Error('[[error:invite-maximum-met, ' + invites + ', ' + max + ']]'));266 }267 user.sendInvitationEmail(socket.uid, email, next);268 },269 ], next);270 },271 ], callback);272};273SocketUser.getUserByUID = function (socket, uid, callback) {274 userController.getUserDataByField(socket.uid, 'uid', uid, callback);275};276SocketUser.getUserByUsername = function (socket, username, callback) {277 userController.getUserDataByField(socket.uid, 'username', username, callback);278};279SocketUser.getUserByEmail = function (socket, email, callback) {280 userController.getUserDataByField(socket.uid, 'email', email, callback);281};282SocketUser.setModerationNote = function (socket, data, callback) {283 if (!socket.uid || !data || !data.uid || !data.note) {284 return callback(new Error('[[error:invalid-data]]'));285 }286 async.waterfall([287 function (next) {288 privileges.users.canEdit(socket.uid, data.uid, next);289 },290 function (allowed, next) {291 if (allowed) {292 return setImmediate(next, null, allowed);293 }294 user.isModeratorOfAnyCategory(socket.uid, next);295 },296 function (allowed, next) {297 if (!allowed) {298 return next(new Error('[[error:no-privileges]]'));299 }300 var note = {301 uid: socket.uid,302 note: data.note,303 timestamp: Date.now(),304 };305 db.sortedSetAdd('uid:' + data.uid + ':moderation:notes', note.timestamp, JSON.stringify(note), next);306 },307 ], callback);308};309SocketUser.deleteUpload = function (socket, data, callback) {310 if (!data || !data.name || !data.uid) {311 return callback(new Error('[[error:invalid-data]]'));312 }313 user.deleteUpload(socket.uid, data.uid, data.name, callback);314};315SocketUser.gdpr = {};316SocketUser.gdpr.consent = function (socket, data, callback) {317 user.setUserField(socket.uid, 'gdpr_consent', 1, callback);318};319SocketUser.gdpr.check = function (socket, data, callback) {320 async.waterfall([321 async.apply(user.isAdministrator, socket.uid),322 function (isAdmin, next) {323 if (!isAdmin) {324 data.uid = socket.uid;325 }326 db.getObjectField('user:' + data.uid, 'gdpr_consent', next);327 },328 ], callback);...
socket.py
Source:socket.py
...17 * unix_socket18 * socket. should pass already opened socket here.19 @param host(str) The host to connect to.20 @param port(int) The (TCP) port to connect to.21 @param unix_socket(str) The filename of a unix socket to connect to.22 @param sock(socket) Initialize with opened socket directly.23 If this param used, the host, port and unix_socket params will24 be ignored.25 @param socket_family(str) socket.AF_INET or socket.AF_INET6. only26 take effect when using host/port27 @param socket_timeout socket timeout in ms28 @param connect_timeout connect timeout in ms, only used in29 connection, will be set to socket_timeout if not set.30 """31 if sock:32 self.sock = sock33 elif unix_socket:34 self.unix_socket = unix_socket35 self.host = None36 self.port = None37 self.sock = None38 else:39 self.unix_socket = None40 self.host = host41 self.port = port42 self.sock = None43 self.socket_family = socket_family44 self.socket_timeout = socket_timeout / 1000 if socket_timeout else None45 self.connect_timeout = connect_timeout / 1000 if connect_timeout \46 else self.socket_timeout47 def _init_sock(self):48 if self.unix_socket:49 _sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)50 else:51 _sock = socket.socket(self.socket_family, socket.SOCK_STREAM)52 _sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)53 # socket options54 linger = struct.pack('ii', 0, 0)55 _sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, linger)56 _sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)57 self.sock = _sock58 def set_handle(self, sock):59 self.sock = sock60 def set_timeout(self, ms):61 """Backward compat api, will bind the timeout to both connect_timeout62 and socket_timeout.63 """64 self.socket_timeout = ms / 1000 if (ms and ms > 0) else None65 self.connect_timeout = self.socket_timeout66 if self.sock is not None:67 self.sock.settimeout(self.socket_timeout)68 def is_open(self):69 return bool(self.sock)70 def open(self):71 self._init_sock()72 addr = self.unix_socket or (self.host, self.port)73 try:74 if self.connect_timeout:75 self.sock.settimeout(self.connect_timeout)76 self.sock.connect(addr)77 if self.socket_timeout:78 self.sock.settimeout(self.socket_timeout)79 except (socket.error, OSError):80 raise TTransportException(81 type=TTransportException.NOT_OPEN,82 message="Could not connect to %s" % str(addr))83 def read(self, sz):84 try:85 buff = self.sock.recv(sz)86 except socket.error as e:87 if (e.args[0] == errno.ECONNRESET and88 (sys.platform == 'darwin' or89 sys.platform.startswith('freebsd'))):90 # freebsd and Mach don't follow POSIX semantic of recv91 # and fail with ECONNRESET if peer performed shutdown.92 # See corresponding comment and code in TSocket::read()93 # in lib/cpp/src/transport/TSocket.cpp.94 self.close()95 # Trigger the check to raise the END_OF_FILE exception below.96 buff = ''97 else:98 raise99 if len(buff) == 0:100 raise TTransportException(type=TTransportException.END_OF_FILE,101 message='TSocket read 0 bytes')102 return buff103 def write(self, buff):104 self.sock.sendall(buff)105 def flush(self):106 pass107 def close(self):108 if not self.sock:109 return110 try:111 self.sock.shutdown(socket.SHUT_RDWR)112 self.sock.close()113 self.sock = None114 except (socket.error, OSError):115 pass116class TServerSocket(object):117 """Socket implementation for server side."""118 def __init__(self, host=None, port=None, unix_socket=None,119 socket_family=socket.AF_INET, client_timeout=3000,120 backlog=128):121 """Initialize a TServerSocket122 TSocket can be initialized in 2 ways:123 * host + port. can configure to use AF_INET/AF_INET6124 * unix_socket125 @param host(str) The host to connect to126 @param port(int) The (TCP) port to connect to127 @param unix_socket(str) The filename of a unix socket to connect to128 @param socket_family(str) socket.AF_INET or socket.AF_INET6. only129 take effect when using host/port130 @param client_timeout client socket timeout131 @param backlog backlog for server socket132 """133 if unix_socket:134 self.unix_socket = unix_socket135 self.host = None136 self.port = None137 else:138 self.unix_socket = None139 self.host = host140 self.port = port141 self.socket_family = socket_family142 self.client_timeout = client_timeout / 1000 if client_timeout else None143 self.backlog = backlog144 def _init_sock(self):145 if self.unix_socket:146 # try remove the sock file it already exists147 _sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)148 try:149 _sock.connect(self.unix_socket)150 except (socket.error, OSError) as err:151 if err.args[0] == errno.ECONNREFUSED:152 os.unlink(self.unix_socket)153 else:154 _sock = socket.socket(self.socket_family, socket.SOCK_STREAM)155 _sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)156 if hasattr(socket, "SO_REUSEPORT"):157 _sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)158 _sock.settimeout(None)159 self.sock = _sock160 def listen(self):161 self._init_sock()162 addr = self.unix_socket or (self.host, self.port)163 self.sock.bind(addr)164 self.sock.listen(self.backlog)165 def accept(self):166 client, _ = self.sock.accept()167 if self.client_timeout:168 client.settimeout(self.client_timeout)...
delay-io.js
Source:delay-io.js
1/*2 * @function steal-socket.delay-io delay-io3 * @parent steal-socket.io4 * @type {Function}5 * @hide6 *7 * @description Wrap `socket-io` to delay establishing a connection for testing purposes.8 *9 * @signature `delayIO( io )`10 *11 * This wrapper helps with testing and demoing applications that use `socket.io` for real-time communication.12 * Often some modules that use `socket.io` call it to establish a socket connection immediately. This13 * makes mocking of `socket.io` impossible. The wrapper delays the creation of socket connection till `StealJS`14 * [is done](https://stealjs.github.io/stealjs/docs/steal.done.html) loading all the modules (including ones where we can mock15 * `socket.io` for testing).16 *17 * ```18 * var delayIO = require("steal-socket.io/delay-io");19 * var socketIO = require("socket.io-client/dist/socket.io");20 * var io = delayIO( socketIO );21 *22 * io("localhost");23 * ```24 * @param {module} io The SocketIO client module. Usually, it is `socket.io-client/dist/socket.io`.25 *26 * @body27 *28 * ## How it works29 *30 * The `delay-io` wrapper returns `io`-like function that resolves in a `delayedSocket`. The `delayedSocket` is31 * a replacement for `io.Socket` and acts as a proxy for it.32 *33 * Initially the wrapper records all calls to `io` and its socket into a _FIFO storage_, and then, when `StealJS`34 * is done with loading all modules, it replays the recorded calls against the real `io` and its socket.35 *36 * After replaying the wrapper directly proxies all the subsequent calls.37 *38 * ## Usage39 *40 * Import `steal-socket.io` which includes this wrapper as its part, or directly import `steal-socket.io/delay-io`41 * to use just this wrapper.42 *43 * Lets say we have an application `myApp.js` that uses `socket.io` and tries to establish the connection right during44 * module evaluation. We import `steal-socket.io` in our app instead of `socket.io-client/dist/socket.io`:45 * ```46 * var io = require("steal-socket.io");47 *48 * var messages = [];49 *50 * var socket = io("localhost");51 * io.on("messages", function(m){52 * messages.push(m);53 * });54 *55 * module.exports = {56 * messages: messages57 * };58 * ```59 *60 * We now create a module `myFixtureSocket.js` that mocks `socket.io` server responses, e.g. using `can-fixture-socket`:61 * ```62 * var io = require("socket.io-client/dist/socket.io");63 * var fixtureSocket = require("can-fixture-socket");64 * var mockSocket = new fixtureSocket( io );65 * mockSocket.on("connect", function(){66 * mockSocket.emit("messages", "some messages");67 * });68 * ```69 *70 * And then we can test our application like this:71 * ```72 * require("myFixtureSocket");73 * var myApp = require("my-app.js");74 *75 * QUnit.test(function(){76 * assert.equal(myApp.messages.length, 1, "Contains one message received from socket server.");77 * });78 * ```79 */80var steal = require("@steal");81var ignore = require("./ignore-zone");82module.exports = delayIO;83/*84 * Switch debugging on/off.85 * TODO: http://socket.io/docs/logging-and-debugging/#available-debugging-scopes86 * @type {Boolean}87 */88var DEBUG = false;89/*90 * `fifoSockets` contains FIFO and a placeholder for `realSocket` per URL.91 * A FIFO is a storage for calls to io.Socket to be replayed when steal is done and we can create a real socket.92 * The first element will be io and its arguments so that we could create a real socket later.93 * ```94 * // The following app:95 * var socket = io("localhost");96 * socket.on("messages", function(m){ console.log(m); })97 * socket.emit("hello", {});98 *99 * // will create:100 * fifoSockets = {101 * localhost: {102 * url: "localhost",103 * realSocket: null,104 * fifo: [105 * [io, ["localhost"]],106 * ["on", ["messages", function(m){ console.log(m); }]],107 * ["emit", ["hello", {}]]108 * ]109 * }110 * }111 * ```112 * @type {Object}113 */114/*115 * Delayed socket - a proxy for socket method calls, so that we can record early calls to `fifo` and replay them after.116 * @param io117 * @returns {{on: function, emit: function, ...}}118 */119function delayedSocket(fifoSocket){120 var delayedSocketBase = {121 __delayedSocket: true,122 get connected () {123 var realSocket = this.fifoSocket.realSocket;124 return !!realSocket && realSocket.connected;125 },126 get disconnected () {127 return !this.connected;128 }129 };130 var methods = [131 'on',132 'off',133 'once',134 'emit',135 'removeListener',136 'addListener',137 'open',138 'connect',139 'close',140 'disconnect'141 ];142 var delayedSocket = methods.reduce(function(acc, method){143 acc[method] = function(){144 var realSocket = fifoSocket.realSocket;145 var fifo = fifoSocket.fifo;146 var url = fifoSocket.url;147 if (realSocket){148 debug('delay-io("' + url + '"): realSocket ' + method);149 if (!realSocket[method]){150 console.warn('steal-socket.io: method ' + method + ' is undefined for realSocket');151 } else {152 realSocket[method].apply(realSocket, arguments);153 }154 } else {155 debug('delay-io("' + url + '"): record ' + method + '("' + arguments[0] + '", ...)');156 fifo.push([method, arguments]);157 }158 };159 return acc;160 }, delayedSocketBase);161 delayedSocket.io = {162 uri: fifoSocket.url,163 engine: ['on', 'off'].reduce(function (acc, method) {164 acc[method] = function (event, handler) {165 if (fifoSocket.realSocket) {166 return fifoSocket.realSocket.io.engine[method](event, handler);167 }168 };169 return acc;170 }, {})171 };172 delayedSocket.fifoSocket = fifoSocket;173 return delayedSocket;174}175/*176 * Replays calls that were recorded to `fifo`.177 * @param fifo178 * @returns {Function}179 */180var hasReplayed = false;181function replay(fifoSockets){182 return function(){183 debug('+++++ delay-io: replay!');184 Object.keys(fifoSockets).forEach(function(url){185 replayFifoSocket(fifoSockets[url]);186 });187 hasReplayed = true;188 };189}190function replayFifoSocket(fifoSocket){191 var url = fifoSocket.url,192 io = ignore(fifoSocket.io),193 args = fifoSocket.args,194 realSocket = fifoSocket.realSocket = io.apply(this, args);195 fifoSocket.fifo.forEach(function(pair){196 var method = pair[0],197 args = pair[1];198 debug('delay-io("' + url + '"): replay ' + method + '("' + args[0] + '", ...)');199 realSocket[method].apply(realSocket, args);200 });201}202// TODO: make it to work the same way as socket.io debugging http://socket.io/docs/logging-and-debugging/#available-debugging-scopes203function debug(msg){204 if (DEBUG){205 console.log(msg);206 }207}208var fifoSockets = {};209function delayIO(io){210 steal.done().then(replay(fifoSockets));211 return function (url, options) {212 var urlId = url === '' ? window.location.origin : url;213 var fifoSocket = fifoSockets[urlId];214 if(!fifoSocket || options && options.forceNew){215 fifoSocket = fifoSockets[urlId] = {216 url: url,217 realSocket: hasReplayed ? io.apply(this, arguments) : null,218 io: io,219 args: arguments,220 fifo: []221 };222 }223 return delayedSocket(fifoSocket);224 };...
socket.js
Source:socket.js
1var expect = require('expect.js');2var io = require('../');3describe('socket', function () {4 this.timeout(70000);5 it('should have an accessible socket id equal to the server-side socket id (default namespace)', function (done) {6 var socket = io({ forceNew: true });7 socket.on('connect', function () {8 expect(socket.id).to.be.ok();9 expect(socket.id).to.eql(socket.io.engine.id);10 socket.disconnect();11 done();12 });13 });14 it('should have an accessible socket id equal to the server-side socket id (custom namespace)', function (done) {15 var socket = io('/foo', { forceNew: true });16 socket.on('connect', function () {17 expect(socket.id).to.be.ok();18 expect(socket.id).to.eql('/foo#' + socket.io.engine.id);19 socket.disconnect();20 done();21 });22 });23 it('clears socket.id upon disconnection', function (done) {24 var socket = io({ forceNew: true });25 socket.on('connect', function () {26 socket.on('disconnect', function () {27 expect(socket.id).to.not.be.ok();28 done();29 });30 socket.disconnect();31 });32 });33 it('doesn\'t fire a connect_error if we force disconnect in opening state', function (done) {34 var socket = io({ forceNew: true, timeout: 100 });35 socket.disconnect();36 socket.on('connect_error', function () {37 throw new Error('Unexpected');38 });39 setTimeout(function () {40 done();41 }, 300);42 });43 it('should ping and pong with latency', function (done) {44 var socket = io({ forceNew: true });45 socket.on('connect', function () {46 var pinged;47 socket.once('ping', function () {48 pinged = true;49 });50 socket.once('pong', function (ms) {51 expect(pinged).to.be(true);52 expect(ms).to.be.a('number');53 socket.disconnect();54 done();55 });56 });57 });58 it('should change socket.id upon reconnection', function (done) {59 var socket = io({ forceNew: true });60 socket.on('connect', function () {61 var id = socket.id;62 socket.on('reconnect_attempt', function () {63 expect(socket.id).to.not.be.ok();64 });65 socket.on('reconnect', function () {66 expect(socket.id).to.not.eql(id);67 socket.disconnect();68 done();69 });70 socket.io.engine.close();71 });72 });73 it('should enable compression by default', function (done) {74 var socket = io({ forceNew: true });75 socket.on('connect', function () {76 socket.io.engine.once('packetCreate', function (packet) {77 expect(packet.options.compress).to.be(true);78 socket.disconnect();79 done();80 });81 socket.emit('hi');82 });83 });84 it('should disable compression', function (done) {85 var socket = io({ forceNew: true });86 socket.on('connect', function () {87 socket.io.engine.once('packetCreate', function (packet) {88 expect(packet.options.compress).to.be(false);89 socket.disconnect();90 done();91 });92 socket.compress(false).emit('hi');93 });94 });95 describe('query option', function () {96 it('should accept an object (default namespace)', function (done) {97 var socket = io('/', { forceNew: true, query: { e: 'f' } });98 socket.emit('getHandshake', function (handshake) {99 console.log('getHandhskae', handshake);100 expect(handshake.query.e).to.be('f');101 socket.disconnect();102 done();103 });104 });105 it('should accept a query string (default namespace)', function (done) {106 var socket = io('/?c=d', { forceNew: true });107 socket.emit('getHandshake', function (handshake) {108 console.log('getHandhskae', handshake);109 expect(handshake.query.c).to.be('d');110 socket.disconnect();111 done();112 });113 });114 it('should accept an object', function (done) {115 var socket = io('/abc', {query: {a: 'b'}});116 socket.on('handshake', function (handshake) {117 expect(handshake.query.a).to.be('b');118 socket.disconnect();119 done();120 });121 });122 it('should accept a query string', function (done) {123 var socket = io('/abc?b=c&d=e');124 socket.on('handshake', function (handshake) {125 expect(handshake.query.b).to.be('c');126 expect(handshake.query.d).to.be('e');127 socket.disconnect();128 done();129 });130 });131 it('should properly encode the parameters', function (done) {132 var socket = io('/abc', {query: {'&a': '&=?a'}});133 socket.on('handshake', function (handshake) {134 expect(handshake.query['&a']).to.be('&=?a');135 socket.disconnect();136 done();137 });138 });139 });...
Using AI Code Generation
1const mb = require('mountebank');2const imposter = {3 {4 {5 is: {6 headers: {7 },8 body: JSON.stringify({ message: 'Hello World!' })9 }10 }11 }12};13mb.create(imposter)14 .then(() => {15 console.log('Imposter created');16 return mb.get('/test', 4545);17 })18 .then(response => {19 console.log(response.body);20 })21 .catch(error => {22 console.error(error);23 });24const mb = require('mountebank');25mb.createHttpImposter(4545, [26 {27 {28 is: {29 headers: {30 },31 body: JSON.stringify({ message: 'Hello World!' })32 }33 }34 }35 .then(() => {36 console.log('Imposter created');37 return mb.get('/test', 4545);38 })39 .then(response => {40 console.log(response.body);41 })42 .catch(error => {43 console.error(error);44 });45const mb = require('mountebank');46mb.createHttpsImposter(4545, [47 {48 {49 is: {50 headers: {51 },52 body: JSON.stringify({ message: 'Hello World!' })53 }54 }55 }56 .then(() => {57 console.log('Imposter created');58 return mb.get('/test', 4545);59 })60 .then(response => {61 console.log(response.body);62 })63 .catch(error => {64 console.error(error);65 });66const mb = require('mountebank');67mb.createTcpImposter(4545, [68 {69 {70 is: {71 }
Using AI Code Generation
1var http = require('http');2var fs = require('fs');3var mb = require('mountebank');4mb.create({5}, function (error, server) {6 if (error) {7 console.error(error);8 } else {9 console.log('mb server started');10 }11});12var host = 'localhost';13var port = '2525';14var path = '/imposters';15var options = {16 headers: {17 }18};19var req = http.request(options, function (res) {20 var data = '';21 res.on('data', function (chunk) {22 data += chunk;23 });24 res.on('end', function () {25 console.log(data);26 });27});28req.on('error', function (e) {29 console.log("Got error: " + e.message);30});31var json = {32 "stubs": [{33 "responses": [{34 "is": {35 "headers": {36 },37 "body": {38 }39 }40 }]41 }]42};43req.write(JSON.stringify(json));44req.end();45var http = require('http');46var fs = require('fs');47var mb = require('mountebank');48mb.create({49}, function (error, server) {50 if (error) {51 console.error(error);52 } else {53 console.log('mb server started');54 }55});56var host = 'localhost';57var port = '2525';58var path = '/imposters';59var options = {60 headers: {
Using AI Code Generation
1var mb = require('mountebank');2mb.create({3}, function () {4 console.log('mountebank started');5});6var mb = require('mountebank');7mb.create({8}, function () {9 console.log('mountebank started');10});11var mb = require('mountebank');12mb.create({13}, function () {14 console.log('mountebank started');15});
Using AI Code Generation
1var mb = require('mountebank');2var port = 2525;3var imposters = {4 {5 {6 equals: {7 }8 }9 {10 is: {11 headers: {12 },13 body: {14 }15 }16 }17 }18};19mb.create({port: port, ipWhitelist: ['*']}, function (error, server) {20 server.post('/imposters', imposters, function (error, response) {21 if (error) {22 console.log(error);23 } else {24 console.log('Imposter created');25 }26 });27});28var request = require('request');29var port = 2525;30 console.log(body);31});32{"errors":[{"code":"bad data","message":"Unexpected token < in JSON at position 0"}]}33{34 {35 {36 "equals": {37 }38 }39 {
Using AI Code Generation
1var mb = require('mountebank');2mb.create({port: 2525, pidfile: 'mb.pid', logfile: 'mb.log'}, function (error, server) {3 if (error) {4 console.log('Error starting server: ' + error);5 } else {6 }7});8var imposter = {9 {10 {11 is: {12 headers: {13 },14 body: JSON.stringify({status: 'ok'})15 }16 }17 }18};19mb.post('/imposters', imposter, function (error, response) {20 if (error) {21 console.log('Error creating imposter: ' + error);22 } else {23 }24});25var request = {26 headers: {27 }28};29mb.get('/imposters/3000', function (error, response) {30 if (error) {31 console.log('Error retrieving imposter: ' + error);32 } else {33 console.log('Retrieved imposter: ' + JSON.stringify(response));34 }35});36mb.del('/imposters/3000', function (error, response) {37 if (error) {38 console.log('Error removing imposter: ' + error);39 } else {40 console.log('Removed imposter');41 }42});43mb.del('/imposters', function (error, response) {44 if (error) {45 console.log('Error removing all imposters: ' + error);46 } else {47 console.log('Removed all imposters');48 }49});50mb.del('/', function (error, response) {51 if (error) {52 console.log('Error removing all imposters: ' + error);53 } else {54 console.log('Removed all imposters');55 }56});57mb.del('/imposters/3000', function (error, response) {58 if (error
Using AI Code Generation
1var mb = require('mountebank');2var port = 2525;3var imposters = [{4 stubs: [{5 predicates: [{6 equals: {7 }8 }],9 responses: [{10 is: {11 headers: { 'Content-Type': 'application/json' },12 body: { message: 'hello world' }13 }14 }]15 }]16}];17mb.create(port, imposters, function (error, mbServer) {18 if (error) {19 console.error(error);20 }21 else {22 console.log('mountebank server started on port: ' + port);23 mbServer.on('close', function () {24 console.log('mountebank server closed');25 });26 }27});28var mb = require('mountebank');29var port = 2525;30var imposters = [{31 stubs: [{32 predicates: [{33 equals: {34 }35 }],36 responses: [{37 is: {38 headers: { 'Content-Type': 'application/json' },39 body: { message: 'hello world' }40 }41 }]42 }]43}];44mb.create(port, imposters, function (error, mbServer) {45 if (error) {46 console.error(error);47 }48 else {49 console.log('mountebank server started on port: ' + port);50 mbServer.on('close', function () {51 console.log('mountebank server closed');52 });53 }54});55var mb = require('mountebank');56var port = 2525;57var imposters = [{58 stubs: [{59 predicates: [{60 equals: {61 }62 }],63 responses: [{64 is: {65 headers: { '
Using AI Code Generation
1var mb = require('mountebank'),2 stub = {3 {4 is: {5 headers: {6 },7 body: JSON.stringify({success: true})8 }9 }10 },11 options = {12 headers: {13 }14 };15mb.create(port, function (error) {16 if (error) {17 console.error(error);18 }19 else {20 mb.post(options, JSON.stringify({port: port, protocol: protocol, stubs: [stub]}), function (error, response) {21 if (error) {22 console.error(error);23 }24 else {25 console.log('Created imposters');26 }27 });28 }29});30var mb = require('mountebank'),31 stub = {32 {33 is: {34 headers: {35 },36 body: JSON.stringify({success: true})37 }38 }39 };40mb.create(port, function (error) {41 if (error) {42 console.error(error);43 }44 else {45 mb.postImposter({port: port, protocol: protocol, stubs: [stub]}, function (error, response) {46 if (error) {47 console.error(error);48 }49 else {50 console.log('Created imposter');51 }52 });53 }54});55var mb = require('mountebank'),56 stub = {57 {58 is: {59 headers: {60 },
Using AI Code Generation
1const mb = require('mountebank');2const fs = require('fs');3const path = require('path');4const { promisify } = require('util');5const readFileAsync = promisify(fs.readFile);6const port = 2525;7mb.create({ port: port, pidfile: 'mb.pid', logfile: 'mb.log' }).then(function (imposter) {8 const imposters = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'imposters.json')));9 Promise.all(imposters.map(imposter => imposter.save()))10 .then(() => {11 console.log('Imposters loaded');12 imposter.start()13 .then(() => {14 console.log('Imposter started');15 })16 .catch(err => {17 console.error('Error starting imposter', err);18 });19 })20 .catch(err => {21 console.error('Error loading imposters', err);22 });23});24 {25 {26 {27 "is": {28 "headers": {29 },30 "body": {31 "data": {32 }33 }34 }35 }36 }37 }38const mb = require('mountebank');39const fs = require('fs');40const path = require('path');41const { promisify } = require('util');42const readFileAsync = promisify(fs.readFile);43const port = 2525;44mb.create({ port: port, pidfile: 'mb.pid', logfile: 'mb.log' }).then(function (imposter) {45 const imposters = JSON.parse(fs.readFileSync(path.resolve(__dirname, 'imposters.json')));46 Promise.all(imposters.map(imposter => imposter.save()))47 .then(() => {48 console.log('Imposters loaded');49 imposter.start()50 .then(() => {51 console.log('Imposter started');52 })53 .catch(err =>
Using AI Code Generation
1const mb = require('mountebank');2const port = 2525;3const protocol = 'http';4const imposter = {5 {6 {7 equals: {8 }9 }10 {11 is: {12 headers: {13 },14 }15 }16 }17};18mb.create({ imposters: [imposter] }, function(error) {19 if (error) {20 console.log('Error creating imposters', error);21 } else {22 console.log('Imposters created at %s', mb.url);23 }24});25const http = require('http');26const port = 2525;27const protocol = 'http';28const imposter = {29 {30 {31 equals: {32 }33 }34 {35 is: {36 headers: {37 },38 }39 }40 }41};42const request = {43 headers: { 'Content-Type': 'application/json' },44 body: JSON.stringify({ imposters: [imposter] })45};46http.request(request, function(response) {47 console.log('Imposters created at %s', mb.url);48}).end();49curl -X POST -H 'Content-Type: application/json' -d '{ "imposters": [{ "protocol": "http", "port": 2525, "stubs": [{ "predicates": [{ "equals": { "method": "GET", "path": "/test" } }], "responses": [{ "is": { "statusCode": 200, "headers": { "Content-Type":
Using AI Code Generation
1var mb = require('mountebank');2var socket = mb.createSocket(2525);3socket.create({port: 3000, stubs: [{responses: [{is: {body: 'Hello world'}}]}]});4socket.get('/imposters', function (error, response) {5 console.log(response.body);6});7{8 "scripts": {9 },10 "dependencies": {11 }12}13I have tried this on both Windows 10 and Linux Mint 18.3. I have tried both Node 6.11.3 and 8.9.4. I have tried the latest version of mountebank (1.10.0) and the version that was installed by npm (1.4.1). I have also tried adding a --allowInjection flag to the mb command in package.json. I have tried running the command as administrator on Windows. I have tried running it as root on Linux. Nothing seems to work. I always get the same error:14 throw err;15 at Function.Module._resolveFilename (module.js:538:15)16 at Function.Module._load (module.js:468:25)17 at Module.require (module.js:587:17)18 at require (internal/module.js:11:18)19 at Object.<anonymous> (C:\Users\jacob\Documents\GitHub\test\test.js:2:15)20 at Module._compile (module.js:643:30)21 at Object.Module._extensions..js (module.js:654:10)22 at Module.load (module.js:556:32)23 at tryModuleLoad (module.js:499:12)24 at Function.Module._load (module.js:491:3)
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!