Node Mocha & Supertest: Error: ECONNREFUSED: Connection refused - node.js

I have built an api and i want to test some of the endpoints.
I have a number of tests that are similar to the ones below. They are all all failing because of Error: ECONNREFUSED: Connection refused
tests
import { assert, expect } from "chai";
import request from "supertest";
import app from "./../src/index";
describe("Authentication", () => {
it("should respond with 200 product_id is authorised", async () => {
const result = await request(app).post("/api/auth")
.send({
product_id: "123",
origin: "localhost:3000",
})
.expect("Content-Type", /json/)
.expect(200);
});
it("should respond with session token", async () => {
const result = await request(app).post("/api/auth")
.send({
product_id: "123",
origin: "localhost:3000",
});
expect(result.body.data).to.have.property("token");
});
});
package.json
"test": "mocha -r ts-node/register --project tsconfig.json test/*.test.ts --exit"
errors:
> mocha -r ts-node/register --project tsconfig.json test/*.test.ts --exit
Server Running On: runner-sefsf-project-41-concurrent-0gdrs7:3000
Authentication
MongoDB Successfully Connected On: mongodb://localhost:27017/p
1) should respond with 200 product_id is authorised
2) should respond with p session token
Server
3) should be up
4) should throw 404 for unrecognized routes
Transaction
5) should respond with a new transction
0 passing (40ms)
5 failing
1) Authentication
should respond with 200 product_id is authorised:
Error: ECONNREFUSED: Connection refused
at Test.assert (node_modules/supertest/lib/test.js:165:15)
at assert (node_modules/supertest/lib/test.js:131:12)
at /eng/p-server/node_modules/supertest/lib/test.js:128:5
at Test.Request.callback (node_modules/superagent/lib/node/index.js:718:3)
at ClientRequest.req.once.err (node_modules/superagent/lib/node/index.js:646:10)
at Socket.socketErrorListener (_http_client.js:382:9)
at emitErrorNT (internal/streams/destroy.js:82:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
at process._tickCallback (internal/process/next_tick.js:63:19)
2) Authentication
should respond with p session token:
Error: ECONNREFUSED: Connection refused
at Test.assert (node_modules/supertest/lib/test.js:165:15)
at assert (node_modules/supertest/lib/test.js:131:12)
at /eng/p-server/node_modules/supertest/lib/test.js:128:5
at Test.Request.callback (node_modules/superagent/lib/node/index.js:718:3)
at ClientRequest.req.once.err (node_modules/superagent/lib/node/index.js:646:10)
at Socket.socketErrorListener (_http_client.js:382:9)
at emitErrorNT (internal/streams/destroy.js:82:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
at process._tickCallback (internal/process/next_tick.js:63:19)
Apparently the connection is being refused? But i'm not sure what it means by this specifically because you can see the server in the error log is connected and so is the mongo service.
index.ts
import Server from "./server";
export default new Server().server;
server.ts
import App from "./app";
class Server {
public server: any;
private instance: any;
private app: any;
private config: any;
constructor() {
this.instance = new App();
this.app = this.instance.app;
this.config = this.instance.config;
this.server = this.app.listen(this.config.port, this.config.hostname);
console.log("Server Running On: " + this.config.hostname + ":" + this.config.port);
}
}
export default Server;

Make sure your server is stopped before you run the test case using supertest as supertest run the api in that same port. So, you need to make that port free for use by supertest.
Since you are using this in your test file,
import request from "supertest";
import app from "./../src/index";
The app contains the domain URL like http://localhost:3135 and when you call the api like, request(app).post where request refers to the supertest module, you always need to make sure that the app is free. Which means, request('http://localhost:3135').post works when there is no process running on port 3135.
You can check the node running processes using pidof node (in linux)and kill every process to make sure the port is available or kill process for that specific port.

I encountered the same error and spend a couple of hours trying to figure out what was up. I was using the pg library and so it happens it needs to pick db options from the environment variables. My problem was I was calling dotenv.config() at the wrong place.

Related

express - mongodb connection issue

I setup a cluster in my mongodb atlas database and to my best of knowledge i did everything right and copied the right to my application using sample_mflix database
in my .env file
MOVIEREVIEWS_DB_URI=mongodb+srv://driiisdev:password123#cluster1.ektx7.mongodb.net/sample_mflix?retryWrites=true&w=majority
PORT=5000 //starting port of server
in my index.js file
import app from "./server.js"
import mongodb from "mongodb"
import dotenv from "dotenv"
dotenv.config();
const uri = process.env.MOVIEREVIEWS_DB_URI;
const client = new mongodb.MongoClient(uri);
const port = process.env.PORT||8000;
(async ()=>{
try{
//Connect to the MongoDB cluster
await client.connect();
app.listen(port, ()=>{
console.log("server is running on port:" +port);
})
}catch(e){
console.error(e);
process.exit(1)
}
})().catch(console.error);
in my server.js
import express from 'express'
import cors from 'cors'
import movies from './api/movies.route.js'
const app = express()
app.use(cors())
app.use(express.json())
app.use("/api/v1/movies", movies)
app.use('*', (req,res)=>{
res.status(404).json({error:"not found"})
})
export default app
on running nodemon server , the error i get
Error: querySrv ECONNREFUSED _mongodb._tcp.cluster1.ektx7.mongodb.net
at QueryReqWrap.onresolve [as oncomplete] (node:dns:213:19) {
errno: undefined,
code: 'ECONNREFUSED',
syscall: 'querySrv',
hostname: '_mongodb._tcp.cluster1.ektx7.mongodb.net'
}
The error indicates a possible SRV lookup failure.
Could you try using the connection string from the connection modal that specifies all 3 hostnames instead of the SRV record? To get this, please head to the Atlas UI within the Clusters section and follow the below steps:
Click Connect on the cluster you wish to connect to
Select Connect your application
Choose Node.JS for the Driver option
Choose the *Version 2.2.12 or later for the version option
Copy and use the connection string which should begin with the following format:
mongodb://:....
Replace the original connection string you used with the version 2.2.12 or later node.js connection string copied from the above steps and then restart your application.
//also in the .env file
// remove the comment after the PORT is assigned, as .env reads comment and will return error
PORT=5000

Mongoose, Supertest: Jest did not exit one second after the test run has completed

I'm trying to use jest and supertest to test my node.js + express application. However,
I keep getting the error message "Jest did not exit one second after the test run has completed."
If I remove mongoose.connect(...) from app.js everything's working fine, but I need the database...
Here's my code:
app.js
const express = require('express');
const mongoose = require('mongoose');
const keys = require('./config/keys');
mongoose.connect(keys.MONGO_URI,
{ useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true });
const app = express();
app.get('/user', (req, res) => {
res.send("success");
})
//...
module.exports = app;
app.test.js
const mongoose = require('mongoose');
const app = require('../src/app');
const request = require('supertest');
describe('GET /user', function () {
afterAll(() => mongoose.disconnect());
it('has respononse status code 200', function (done) {
request(app)
.get('/user')
.expect(200, done);
});
});
error message:
> jest
PASS tests/app.test.js (6.798 s)
GET /user
√ has respononse status code 200 (22 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 6.875 s, estimated 7 s
Ran all test suites.
Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.
ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.
at BufferList.Readable (node_modules/readable-stream/lib/_stream_readable.js:179:22)
at BufferList.Duplex (node_modules/readable-stream/lib/_stream_duplex.js:67:12)
at new BufferList (node_modules/bl/bl.js:33:16)
at new MessageStream (node_modules/mongodb/lib/cmap/message_stream.js:35:21)
at new Connection (node_modules/mongodb/lib/cmap/connection.js:54:28)
C:\Users\XXX\server\node_modules\readable-stream\lib\_stream_readable.js:111
var isDuplex = stream instanceof Duplex;
^
TypeError: Right-hand side of 'instanceof' is not callable
at new ReadableState (C:\Users\XXX\server\node_modules\readable-stream\lib\_stream_readable.js:111:25)
at BufferList.Readable (C:\Users\XXX\server\node_modules\readable-stream\lib\_stream_readable.js:183:25)
at BufferList.Duplex (C:\Users\XXX\server\node_modules\readable-stream\lib\_stream_duplex.js:67:12)
at new BufferList (C:\Users\XXX\server\node_modules\bl\bl.js:33:16)
at new MessageStream (C:\Users\XXX\server\node_modules\mongodb\lib\cmap\message_stream.js:35:21)
at new Connection (C:\Users\XXX\server\node_modules\mongodb\lib\cmap\connection.js:54:28)
at C:\Users\XXX\server\node_modules\mongodb\lib\core\connection\connect.js:36:29
at callback (C:\Users\XXX\server\node_modules\mongodb\lib\core\connection\connect.js:280:5)
at TLSSocket.connectHandler (C:\Users\XXX\server\node_modules\mongodb\lib\core\connection\connect.js:325:5)
at Object.onceWrapper (node:events:433:28)
at TLSSocket.emit (node:events:327:20)
at TLSSocket.onConnectSecure (node:_tls_wrap:1527:10)
at TLSSocket.emit (node:events:327:20)
at TLSSocket._finishInit (node:_tls_wrap:932:8)
at TLSWrap.ssl.onhandshakedone (node:_tls_wrap:706:12)
npm ERR! code 1
Things I've tried:
I ran Jest with '--detectOpenHandles', but it didn't give me any additional information.
There's no app.listen(PORT) (I have a separate server.js file for that)
I've added the following to the package.json:
package.json
"jest": {
"testEnvironment": "node"
}
Apparently, mongoose hadn't established a connection when I called mongoose.disconnect(); and this cause all the errors, so I added this to my code:
beforeAll((done) => {
if(!mongoose.connection.db){
mongoose.connection.on('connected', done)
} else {
done();
}
}, 20000);

Nest Js: Webscoket Reverse proxy

I created a graphql subscription server which runs on port 7777 with the path /subscriptions/graphql for both HTTP, WebSocket protocol which is absolutely working fine when I directly used the URL with other services.
HTTP : http://localhost:7777/subscriptions/graphql
websocket: ws://localhost:7777/subscriptions/graphql
Subscription server is a microservices just like the other services we have. Now my aim is to do a reverse proxy in the gateway. I wanted to do a reverse proxy for both HTTP, WebSocket based connections.
For this, I wrote two middleware one for HTTP and one for Websocket. Http based middleware is working fine. Whereas the WebSocket is not working as expected.
Websocket based Middileware
import { NestMiddleware, Logger, Injectable } from '#nestjs/common';
import { createProxyMiddleware } from 'http-proxy-middleware';
#Injectable()
export class SubscriptionServiceWebSocketReverseProxyMiddleware
implements NestMiddleware {
/*
jscpd:ignore-start
*/
constructor(private readonly logger: Logger) { }
private proxy = createProxyMiddleware({
target: 'ws://localhost:7777/subscriptions/graphql',
secure: false,
changeOrigin: true,
ws: true,
onProxyReq: (proxyReq, req, res) => {
this.logger.debug(
`[SubscriptionServiceWebSocketReverseProxyMiddleware]: Proxying ${req.method} request originally made to '${req.originalUrl}'...`,
);
},
});
use(req: any, res: any, next: () => void) {
this.proxy(req, res, next);
}
/*
jscpd:ignore-end
*/
}
When the websocket request made from UI, I am getting below error
[Nest] 43743 - 08/24/2020, 3:20:20 PM [SubscriptionServiceWebSocketReverseProxyMiddleware]: Proxying GET request originally made to '/subscriptions/ws/graphql'...
[HPM] Upgrading to WebSocket
events.js:200
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at TCP.onStreamRead (internal/stream_base_commons.js:200:27)
Emitted 'error' event on Socket instance at:
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:81:21) {
errno: 'ECONNRESET',
code: 'ECONNRESET',
syscall: 'read'
}
Note: I was able to see the log message inside the middleware which means there is no issue with middleware. I also see the subscription service alone is working as well.

Proxied websocket connection is immediately closed

I have a create-react-app dev server proxying backend connections (as one does). Suddenly websocket proxying stopped working.
My setupProxy.js looks like this:
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
const port = process.env.BACKEND_PORT || '8080';
const target = `http://localhost:${port}`;
app.use(proxy(['/path/to/socket'], {
target,
ws: true,
onProxyReqWs: function(proxyReq, req, socket) {
socket.on('error', err => console.log(err));
console.log('socket is destroyed', socket.destroyed)
},
logLevel: 'debug',
}));
app.use(proxy(shouldProxy, {
target,
logLevel: 'debug',
}));
(where shouldProxy is a function, since my logic for when to proxy is... non-trivial).
When the browser (Firefox 71 or Chrome 79) creates a websocket connection, I can see that the backend gets the request and responds normally, but the browser gets a 400 Bad request and the dev-server console has this:
[HPM] GET /path/to/socket -> http://localhost:8080
socket is destroyed true
[HPM] Upgrading to WebSocket
Error [ERR_STREAM_DESTROYED]: Cannot call write after a stream was destroyed
at Socket.Writable.write (_stream_writable.js:321:17)
at ClientRequest.<anonymous> ([...]/node_modules/http-proxy/lib/http-proxy/passes/ws-incoming.js:143:14)
at ClientRequest.emit (events.js:305:20)
at Socket.socketOnData (_http_client.js:508:11)
at Socket.emit (events.js:305:20)
at addChunk (_stream_readable.js:341:12)
at readableAddChunk (_stream_readable.js:316:11)
at Socket.Readable.push (_stream_readable.js:250:10)
at TCP.onStreamRead (internal/stream_base_commons.js:186:23) {
code: 'ERR_STREAM_DESTROYED'
}
[HPM] Client disconnected
So something seems to be destroying the socket very early in the proxying process, but I cannot fathom what.
I currently run with node 13.5.0, http-proxy 1.18.0 and http-proxy-middleware 0.20.0; I've tried downgrading node to 12.14.0 and HPM to 0.19.1, to no avail.
This was an issue with create-react-app 3.3.0, caused by this bug in webpack-dev-server. Adding "webpack-dev-server": "3.10.1" to the resolutions section of package.json and SKIP_PREFLIGHT_CHECK=true to .env fixed it.

Node.js app fails to connect using socket.io-client

Background
I have a Node.js server using socket.io that accepts connections from clients via HTTPS.
I know this server works as I am able to connect to it via browser.
Problem
The problem is that I can't create a node app to connect to this server as a client.
I am using the following code:
const io = require("socket.io-client");
const socket = io.connect("https://my.website.com:3002", { secure: true, reconnect: true });
socket.on("connect", function(){
console.log("connected");
});
socket.on("disconnect", function(){
console.log("disconnected");
});
socket.on("error", console.error);
The server registers no connections, and this app logs no errors. It would seem that I am connecting to the wrong server, but this same URL works just fine when I use a browser.
Research
I have searched github and the official docs for an answer. Even similar questions from stackoverflow seem to not work:
Node.js client for a socket.io server
https://www.npmjs.com/package/socket.io-client
https://github.com/socketio/socket.io-client/issues/828
Question
What am I doing wrong ?
Answer
After realising, that not all errors feed into the "error" event ( special thanks to #RolandStarke ) I found that I was having a consistent XHR pool request:
{ Error: xhr poll error
at XHR.Transport.onError (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transport.js:64:13)
at Request.<anonymous> (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transports/polling-xhr.js:128:10)
at Request.Emitter.emit (/Users/pedro/Workspace/backend-stresser/node_modules/component-emitter/index.js:133:20)
at Request.onError (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transports/polling-xhr.js:310:8)
at Timeout._onTimeout (/Users/pedro/Workspace/backend-stresser/node_modules/engine.io-client/lib/transports/polling-xhr.js:257:18)
at ontimeout (timers.js:469:11)
at tryOnTimeout (timers.js:304:5)
at Timer.listOnTimeout (timers.js:264:5) type: 'TransportError', description: 503 }
Once I had this information, I made a quick search and found a solution to this issue, which seems to be a bug:
https://github.com/socketio/socket.io-client/issues/1097
The code I am now using is:
const socket = io.connect("https://my.website.com:3002", { secure: true, reconnection: true, rejectUnauthorized: false });
And it works as expected.
I have used this code in my client side and it worked:
import io from "socket.io-client"
const SERVER = "http://localhost:5000"
const socket = io(SERVER, { transports: ["websocket"] })

Resources