Express returns "not found" intermittently - javascript

I've been working with express for years, and I'm a bit rusty on the typescript side - however... I think I have gone blind! Its the first time I encounter this, so I must be doing something wrong...
My problem is this:
I have an endpoint called "/status".
When I call it, it will sometimes return OK;
And other times it will return a 404 Not Found.
This is the SAME endpoint doing this intermittently.
Here is my express app's code:
import bodyParer from "body-parser";
import methodOverride from "method-override";
import helmet from "helmet";
import fileUpload from "express-fileupload";
import cors from "cors";
import { errors } from "celebrate";
import { expressRouter } from "./routes";
import config from "../config/config";
import { ErrorHandlers } from "../middleware";
const expressApp = express();
expressApp.use(bodyParer.json());
expressApp.use(methodOverride());
expressApp.use(helmet());
expressApp.use(fileUpload());
expressApp.use(cors());
expressApp.use(errors());
expressApp.use(config.api.v1Prefix, expressRouter);
const errorHandlers = new ErrorHandlers();
expressApp.use(errorHandlers.notFound);
expressApp.use(errorHandlers.handler);
export { expressApp };
This is what the router looks like:
// import user from "../routes/user";
const expressRouter = Router();
expressRouter.get("/status", (req, res) => res.send("OK"));
// user(expressRouter); // TODO: finish this off when above '/status' works...
export { expressRouter };
I also suspect the error handlers we have, and this is what they look like:
import { inversifyContainer } from "../config/inversify_config";
import { TYPES } from "../config/inversify_types";
import { Logger } from "../loaders/logger";
import httpStatus from "http-status";
export class ErrorHandlers {
loggerDependency = inversifyContainer.get<Logger>(TYPES.LoggerDependency);
notFound(req, res, next) {
const error = new Error("Not Found");
error["status"] = 404;
next(error);
}
public handler(err, req, res, next) {
const response = {
code: err.status,
message: err.message || httpStatus[err.status],
errors: err.errors,
stack: err.stack,
};
if (process.env.NODE_ENV !== "development") {
delete response.stack;
}
res.status(err.status);
res.json(response);
}
}
Has anyone else experienced this before?
Please let me know if there is anything else I can provide for assistance.
Up to now I have not been able to identify the issue. Any help will be greatly appreciated!

So... ehmmm.
We are using cloud foundry (in IBM).
What happened was that, in the past, our continuous deployment got stuck. Then we manually cancelled that deployment, so that the queued-up deployments could run and proceed at the time :)
What I realised today was that the OLD app never got deleted. This was a cloud foundry service that was running on the same domain (url) as the active cloud foundry service, which effectively made it 2 running instances, in other words.
The OLD service obviously did not have this new endpoint and it never would, as it was detached from the deployment.
Once I deleted the old service, this issue completely disappeared.
Thanks for anyone that took the time to read through all this nonense. Cheers!

Related

jwt - vscode - postgresql DB connection/login project

i did so many things to solve this problem, i didn't.
so i am asking some questions related to some error
when i run code server and client side without no error.
but the screen is blank and console display error :
[App.js:24] POST http://localhost:5000/authentication/verify 401 (Unauthorized)
https://github.com/ousecTic/pern-jwt-tutorial << the link
anyway, i just type the code below, but it doens't work.
app.js (client side)
import React, { Fragment, useState, useEffect } from "react";
import "react-toastify/dist/ReactToastify.css";
import {
BrowserRouter as Router,
Route,
Switch,
Redirect
} from "react-router-dom";
import { toast } from "react-toastify";
//components
import Login from "./components/Login";
import Register from "./components/Register";
import Dashboard from "./components/Dashboard";
toast.configure();
function App() {
const checkAuthenticated = async () => {
try {
const res = await fetch("http://localhost:5000/authentication/verify", {
method: "POST",
headers: { jwt_token: localStorage.token }
});
const parseRes = await res.json();
parseRes === true ? setIsAuthenticated(true) : setIsAuthenticated(false);
} catch (err) {
console.error(err.message);
}
};
server.js (server side)
const express = require("express");
const app = express();
const cors = require("cors");
//middleware
app.use(cors());
app.use(express.json());
//routes
app.use("/authentication", require("./routes/jwtAuth"));
app.use("/dashboard", require("./routes/dashboard"));
app.listen(5000, () => {
console.log(`Server is starting on port 5000`);
});
jwtauth (server side)
router.post("/verify", authorize, (req, res) => {
try {
res.json(true);
} catch (err) {
console.error(err.message);
res.status(500).send("Server error");
}
});
module.exports = router;
and i checked already below some things.
i just changed react/react-dorm and others package version in package.json
in the server/client side. cause it has been changed a lot so many errors occured.
so i make the package the same version.
And i checked DB connection / but it seems to work.
and this is my entire code : https://github.com/Ryandongyou/jwt_project_dongyou
thank you :)

Error On Express Router Setup: Router.use() requires middleware function but got a undefined

I will just say first of all that I am aware of almost all the questions asked on this site under this title.
The solutions there were pretty obvious and already done by me (with no success) or only helped for those specific cases and didn’t really work in my case unfortunately.
Now, for the problem:
I'm trying to create a route that will handle a get request and a post request which are sent to the route 'ellipses'.
These requests should receive and send data from and to an SQL database.
The problem is that for some reason the router is not ready to get these functions and gives me the error in the title:
Router.use () requires middleware function but got an undefined
Here is my code:
This code is from the file dat.js. its porpose is just to access the SQL database.
import { Sequelize } from "sequelize";
export const sequelize = new Sequelize('TheDataBaseName', 'TheUser', 'ThePassword', {
host: 'localhost',
dialect: 'mssql'
});
This code is from the file: controller.js. its porpose is to manage the requests and load the data.
import { sequelize } from "../dat";
export const sendEllipses = async (req, res, next) => {
try {
const ellipses = await getEllipsesFromJson();
return res.send(ellipses);
} catch (e) {
console.log(e);
}
};
export const addNewEllipse = async (req, res, next) => {
const { body: obj } = req;
let newEllipse;
try {
if (Object.keys(obj) !== null) {
logger.info(obj);
newEllipse = await sequelize.query(
`INSERT INTO [armageddon].[dbo].[ellipses] (${Object.keys(
obj
).toString()})
values (${Object.values(obj).toString()})`
);
} else {
console.log("the values are null or are empty");
}
return res.send(newEllipse);
} catch (error) {
console.log(error);
}
};
This code is on the file: routers.js.
its porpose is to define the route
import Router from "express";
import { sendEllipses } from "../ellipses.controller";
import { addNewEllipse } from "../ellipses.controller";
const router = Router();
export default router.route("/ellipses").get(sendEllipses).post(addNewEllipse);
This code is from the file: app.js. This is where everything actually happens.
import { router } from "../routers";
import express from "express";
app.use('/api', router);
app.listen(5000, () => {
console.log("server is runing on port 5000")
});
You need to export the router
const router = Router();
router.route("/ellipses").get(sendEllipses).post(addNewEllipse)
export default router
Now import the router:
import routes from "../router.js";
app.use('/api', routes);
Its also mentioned in the docs: https://expressjs.com/de/guide/routing.html#express-router

I'm getting TypeError: res.cookie is not a function while writing what looks to me to be identical syntax to other people; whats wrong?

I am trying to send a cookie in my response object using NestJS and cookie-parser.
My expected result is that a cookie is attached to my response object and sent to the client (or in this case, postman). My actual result is that I get this error:
web-api_1 | [Nest] 152 - 02/26/2022, 1:15:52 AM ERROR [AccountController] res.cookie is not a function
web-api_1 | TypeError: res.cookie is not a function
web-api_1 | at AccountController.<anonymous> (/app/dist/apps/web-api/webpack:/ourRepo/apps/apis/web-api/src/app/account/account.controller.ts:51:13)
web-api_1 | at Generator.next (<anonymous>)
web-api_1 | at fulfilled (/app/node_modules/tslib/tslib.js:114:62)
web-api_1 | at processTicksAndRejections (node:internal/process/task_queues:96:5)
Here is my code:
// at the top
import { Body, Response, Controller, Patch, Post, Request, UseFilters, UseGuards, Put, Get } from '#nestjs/common';
// later...
#UseGuards(LocalAuthGuard)
#Post('account/sign-in')
async login(#Request() req, #Response() res): Promise<any> {
console.log(43, req.user.email, req.user.id)
const jwt = await this.accountClient.signIn({ email: req.user.email, userId: req.user.id });
const refreshToken = await this.accountClient.generateRefreshToken({email: req.user.email, ipAddress: req.ip})
const cookieOptions = {
httpOnly: true,
expires: new Date(Date.now() + 15*60*1000)
}
res.cookie('refreshToken', refreshToken, cookieOptions);
console.log(45, jwt)
return res.send(jwt);
}
I don't understand what I'm doing wrong. Look at this guy's code and you can see that it works correctly for him; the OP and a helper discuss his issue and they discover his code works correctly. I've copied the form of his code as best as I can. I don't see the issue here.
edit: main.ts to show that I import cookieParser correctly
/**
* This is not a production server yet!
* This is only a minimal backend to get started.
*/
import { Logger } from '#nestjs/common';
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { FastifyAdapter, NestFastifyApplication } from '#nestjs/platform-fastify';
import compression from 'fastify-compress';
import multipart from 'fastify-multipart';
import * as cookieParser from 'cookie-parser'; // <----- cookie parser used correctly
import { ClusterService } from '#repo/svc-interfaces';
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter({
maxParamLength: 400
}));
app.enableCors();
app.use(cookieParser()); // <----- cookie parser used correctly
await app.register(multipart);
await app.register(compression);
const port = process.env.PORT || 3333;
await app.listen(port, '0.0.0.0');
Logger.log(
`🚀 Application is running on: http://localhost:${port}`
);
}
if (environment.production) {
ClusterService.clusterize(bootstrap);
} else {
bootstrap();
}
I figured out what was wrong. I realized there's Express NestJS and Fastify NestJS. I figured the code i was copying from that thread was for Express and so I googled, "fastify nestjs send cookie" and got this page:
https://docs.nestjs.com/techniques/cookies
the solution was to npm install fastify-cookie and follow the docs.
I changed to using the setCookie method they describe in the docs.
Everything's swell.

ReferenceError when using MongoDB Collection variable in external resolver file that was imported via mergeResolvers

This is a totally reduced example to better explain the issue! So when I use the resolver Query getAllUsers, the MongoDB Collection Users is not available in the external resolver file user.js. So when I send that query I get:
ReferenceError: Users is not defined
That's a correct behaviour. But I do not want to include all the resolvers in my index.js, because I have a better modularization in this way. So I have all my typedefs and resolvers in external files like this.
Current file structure
index.js
/graphql
/typdef
user.graphql
/resolver
user.js
The user.graphql schema is correctly working. It is just the user.js that is producing the error when I execute the query with the not available Users variable, as already said.
Here the index.js and user.js.
index.js
import express from 'express'
import cors from 'cors'
const app = express()
app.use(cors())
import bodyParser from 'body-parser'
import {graphqlExpress, graphiqlExpress} from 'graphql-server-express'
import {makeExecutableSchema} from 'graphql-tools'
import {fileLoader, mergeTypes, mergeResolvers} from 'merge-graphql-schemas';
import {writeFileSync} from 'fs'
const typeDefs = mergeTypes(fileLoader(`${__dirname}/graphql/typedef/*.graphql`), { all: true })
writeFileSync(`${__dirname}/graphql/typedef.graphql`, typeDefs)
export const start = async () => {
try {
const MONGO_URL = 'mongodb://localhost:27017'
const MongoClient = require('mongodb').MongoClient;
MongoClient.connect(MONGO_URL, function(err, client) {
console.log("Connected successfully to server");
const db = client.db('project');
const Users = db.collection('user')
});
const URL = 'http://localhost'
const homePath = '/graphql'
const PORT = 3001
app.use(
homePath,
bodyParser.json(),
graphqlExpress({schema})
)
app.use(homePath,
graphiqlExpress({
endpointURL: homePath
})
)
app.listen(PORT, () => {
console.log(`Visit ${URL}:${PORT}${homePath}`)
})
} catch (e) {
console.log(e)
}
}
user.js
export default {
Query: {
getAllUsers: async () => {
return (await Users.find({}).toArray()).map(prepare)
}
}
}
What is the best way to pass the MongoDB or the Users collection to the resolver files. Or is there an even better solution for this issue?
First of all, this is NOT a proper solution, because declaring global variables while outsourcing schema is a bad design at all. But it works out and maybe this way someone gets an idea about how to improve this fix.
So to solve the issue all I had to do is changing the variable from local const to global.
So in index.js const Users = db.collection('user') is rewritten by global.Users = db.collection('user').
Same for the user.js. Here return (await Users.find({}).toArray()).map(prepare) is rewritten by return (await global.Users.find({}).toArray()).map(prepare).

Express middleware with async initialization

I am writing some express middleware that needs to access a database. It is going to be released as a package so I want it to be as self contained as possible. I was wondering how I should handle the connection to the database. It is async(of course), but it only needs to happen once when the package is initialized. Where should this happen?
I was thinking something like this. The problems is, the middleware is passed back right away, before the database is ready.
// App
app.use(myMiddleware({
db: "<db connection string>"
});
// Middleware
module.exports = function(db) {
// Open db
return function(req, res, next) {
// Middleware stuff
}
}
I'd recommend against such a singleton, dependency injection is a better solution here, and a connection per app is hardly scalable. A connection pool might be a better idea.
That said, you can do something like:
var db = null; // to keep our instance
var asked = false; // to not make several requests that override each other
function openDb(db,ready){
// if we already have it, we return the instance
if(db !== null) ready(null,db);
// if it was already asked by another instance, keep track of it
// to avoid multiple requests.
if(asked) asked.push(ready);
asked = [];
openDbCode(db,function(err,result){
if(err) {
ready(err,null); // error case
asked.forEach(function(fn){ fn(err,null); }); // notify waiters of failure
}
db = result; // save the reference
asked.forEach(function(fn){ fn(db,null); }); // notify all waiters
})
}
This function effectively waits for a db for the first asker and then calls everyone on the same instance. Note that this function will use the first connection string provided.
module.exports = function(db) {
return function(req, res, next) {
openDb(db,function(err,db){
if(err) handleDbOpenErrorLogicHere();
// middleware stuff, same db available here, call next to continue
});
};
}
use an async function to wrap your create app code and then app.listen after everything is initialized.
// app.js
import express from "express";
export default async () => {
const app = express();
const asyncMiddleware) = await initMWAsync();
app.use(asyncMiddleware);
return app;
}
// entry point of your program
import createApp from "./app";
const server = createApp()
.then(app => app.listen(app.get("port"), () => {
console.log(
" App is running at http://localhost:%d in %s mode",
app.get("port"),
app.get("env")
);
console.log(" Press CTRL-C to stop\n");
}));
export default server;

Categories

Resources