Im using a Express server and trying to implement Socket.io for the first time, and I keep getting this whenever I open it:
GET /socket.io/?EIO=4&transport=polling&t=OKgNATB 404 0.526 ms - 149
GET /socket.io/?EIO=4&transport=polling&t=OKgNBww 404 0.332 ms - 149
GET /socket.io/?EIO=4&transport=polling&t=OKgNDOV 404 0.411 ms - 149
app.ts:
import express from 'express';
import morgan from 'morgan';
import favicon from 'serve-favicon';
import path from 'path';
import cors from 'cors';
import { errorManager } from './middlewares/errors_middleware.js';
import { ordersRouter } from './routers/OrdersRouter.js';
import { usersRouter } from './routers/UsersRouter.js';
import { createServer } from 'http';
import { Server } from 'socket.io';
export const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, {
cors: {
origin: '*',
},
});
io.on('connection', (socket) => {
console.log('HELLO');
});
app.use(favicon(path.join('.', 'public', 'favicon.ico')));
app.use(cors());
app.use(morgan('dev'));
app.use(express.json());
app.get('/', (_req, res, next) => {
res.send('H');
next();
});
Routers
app.use('/orders', ordersRouter);
app.use('/users', usersRouter);
app.use(errorManager);
index.ts:
import http from 'http';
import createDebug from 'debug';
import { app } from './app.js';
import { dbConnect } from './dbconnect/dbconnect.js';
const debug = createDebug('StoryLine:INDEX');
const port = 3300;
const server = http.createServer(app);
server.on('listening', () => {
const addr = server.address();
if (addr === null) return;
let bind: string;
if (typeof addr === 'string') {
bind = 'pipe ' + addr;
else {
bind =
addr.address === '::'
? `http://localhost:${addr?.port}`
: `port ${addr?.port}`;
}
debug(`SERVER: Listening on: ${bind}`);
});
server.on('error', (error: Error, response: http.ServerResponse) => {
response.write(error.message);
response.end();
});
dbConnect()
.then((mongoose) => {
debug(
'Database connection -> SUCCESSFUL: ',
mongoose.connection.db.databaseName
);
server.listen(port);
})
.catch((error) => {
debug('Database connection -> COULD NOT CONNECT');
server.emit(error);
});
I simply want to get a console.log telling me that a user is connecting. I have tried following the Socket.io docs for express but its not working for me.
Related
I have set up custom koa.js server and every time I make a request to api for example
/api/login
It always ends up in being 404 not found.
I have tried looking for a solution but, could not really find it.
Below is my server.js file
import '#babel/polyfill';
import dotenv from 'dotenv';
import 'isomorphic-fetch';
import next from 'next';
import Koa from 'koa';
import Router from 'koa-router';
import UserRouter from './routes/user';
import cors from '#koa/cors';
dotenv.config();
const compression = require('compression');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
server.use(
cors({
origin: '*',
})
);
router.get('*', async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
});
server.use(UserRouter.routes()).use(UserRouter.allowedMethods());
server.use(router.allowedMethods());
server.use(router.routes());
server.listen(port, (err) => {
if (err) throw err;
console.log(`Server ready on ${port}`);
});
});
I am creating a node.js app with a react client and an express/socketio backend and passport authentication. I'm trying to emit a socketio event from the client and then have the backend respond but it seems that the request is getting lost somewhere between when it's emitted to when the backend processes it.
Below are all the files I thought relevant to the problem at hand.
Backend is on localhost:5000 and client is on localhost:3000
As I said, everything goes well until the line marked in Organization.js. But at/after that line, the event is presumably sent but none of the corresponding routes in socket.js are hit.
Backend start file - app.js
'use strict';
import express from 'express'
import { createServer } from 'http'
import path from 'path'
import { fileURLToPath } from 'url';
import logger from 'morgan'
import cookieParser from 'cookie-parser'
import index from './routes/index.js'
import session from 'express-session'
import passport from './src/auth.js'
import { Server } from 'socket.io'
import { CrashCollector } from 'crashcollector'
new CrashCollector('crash_logs', (err, exit) => {
console.log('Cleaning up...')
console.log('Saving some stuff...')
// Calls callback funtion executing process.exit()
// You can also just write process.exit() here
exit()
})
const app = express();
const server = createServer(app)
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const io = new Server(server, {
cookie: { maxAge: 24 * 60 * 60 * 1000 },
cors: {
origin: 'http://localhost:3000',
credentials: true
}
})
const sessionMiddleware = session({
secret: "changeit", resave: false,
saveUninitialized: false
});
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(sessionMiddleware)
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', index);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
let err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
console.log('dev error handler')
res.status(err.status || 500);
res.end()
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
console.log('prod error handler')
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.set('port', process.env.PORT || 3000); //process.env.PORT = 5000
server.listen(app.get('port'), _ => {
console.log(`Server listening on port ${app.get('port')}`)
})
export {
io,
sessionMiddleware
}
Backend - socket.js
import { io, sessionMiddleware } from '../app.js'
import passport from '../src/auth.js'
import { getSequel } from '../src/database.js'
const wrap = middleware => (socket, next) =>
middleware(socket.request, {}, next);
io.use((_, next) => {
console.log('connection attempt')
next()
})
io.use(wrap(sessionMiddleware));
io.use(wrap(passport.initialize()));
io.use(wrap(passport.session()));
io.use((con, next) => {
console.log('socket check', !!con.request.user)
if (con.request.user) {
next()
} else {
next(new Error('unauthorized'))
}
});
io.on('connection', (con) => {
console.log(`new connection ${con.id}`);
con.on('confirm', cb => {
cb(con.request.user.name);
});
con.on('eventTable', _ => {
console.log('eventTable')
con.emit(con.request?.user?.getEvents()?.map(e => e.toJSON()))
})
});
Client start file - index.js
import React from 'react'
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import './index.css';
import App from './App/App';
import { io } from 'socket.io-client'
import configs from '../package.json'
const container = document.getElementById('root');
const root = createRoot(container);
export const socket = io.connect(configs.proxy, { //configs.proxy = http://localhost:5000
withCredentials: true
})
socket.on('connect', _ => {
console.log('socket connect', socket.id)
})
socket.on('connect_error', _ => {
console.log('socket connect_error')
})
socket.on('disconnect', _ => {
console.log('socket disconnect')
})
socket.prependAny((eventName, ...args) => {
console.log(eventName, args)
})
root.render((
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
));
Client - App.js
import React from 'react'
import { Route, Routes } from 'react-router-dom'
import './App.css'
import Login from './pages/Login'
import Home from './pages/Home'
import LoginCheck from './helper/LoginCheck'
const App = () => {
console.log('app')
return (
<Routes>
<Route exact path="/" element={<LoginCheck />} >
<Route index element={<Home />} />
</Route>
<Route path="/login" element={<Login />} />
</Routes>
)
}
export default App;
Client - Home.js
import React, { useState } from 'react';
import Org from './Organization'
const Home = () => {
console.log('home')
return localStorage.getItem('isOrg') ? (
<Org />
) : (
'Employee'
)
}
export default Home;
Client - Organization.js
import React, { createElement, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom'
import Countdown from 'ds-countdown'
import { socket } from '../../index'
const Org = () => {
console.log('org')
const setTable = (raffles) => {
console.log('cb eventTable')
JSON.parse(raffles).forEach(raffle => {
const row = createElement('tr')
const name = createElement('td')
name.append(raffle.name)
const num = createElement('td')
num.append(raffle.num)
const started = Date.parse(raffle.start) >= Date.now()
const countdown =
<><td>
<p style={{ color: started ? 'red' : 'green' }}>
{started ? 'Starts' : 'Ends'} in:
<div id={`timer${raffle.id}`} />
</p>
</td></>
const action = createElement('td')
const edit = createElement('button')
edit.addEventListener('click', e => {
//goto edit at raffle.id
alert('edit')
})
const end = createElement('button')
end.addEventListener('click', e => {
//set timer to 0
alert('start/end')
})
action.append(edit)
action.append(end)
row.append(name)
row.append(num)
row.append(countdown)
row.append(action)
document.getElementById('eventTable').append(row)
new Countdown({
id: `timer${raffle.id}`,
targetTime: started ?
raffle.end : raffle.start
})
})
}
useEffect(() => {
console.log('useEffect')
**socket.emit('eventTable')** //THIS IS WHERE IT BREAKS
socket.on('eventTable', setTable)
return () => {
socket.off('eventTable', setTable)
}
})
return (<>
<h1 style={{ textAlign: 'center' }}>
{localStorage.getItem('name')}
</h1>
<table style={{ marginLeft: 'auto', marginRight: 'auto' }}
border="1"><caption>
<h3>Scheduled Raffles</h3>
</caption>
<tbody id="eventTable">
<tr>
<th>Name</th>
<th>Num Participants</th>
<th>Countdown</th>
<th>Action</th>
</tr>
<tr>
<td>Test</td>
<td>10</td>
<td>10:10:04</td>
<td><button> Edit </button> <button> End Now </button> <button> Stop </button></td>
</tr>
</tbody>
</table>
</>);
}
export default Org;
I get no errors on the front end. In fact, the client says that a connection has been established, thanks to the socket.on('connect') in index.js. None of the console.logs in the socket.js file are getting activated, so I have reason to believe that the route isn't getting hit. I also activated Debugging on socket but the logs there don't help me very much:
Server listening on port 5000
socket.io:server incoming connection with id 1wpATq-xiQ1jHttwAAAA +2s
socket.io-parser decoded 0 as {"type":0,"nsp":"/"} +0ms
socket.io:client connecting to namespace / +0ms
socket.io:namespace adding socket to nsp / +0ms
socket.io:socket socket connected - writing packet +0ms
socket.io:socket join room f6lna-kbntjuwffpAAAB +3ms
socket.io-parser encoding packet {"type":0,"data":{"sid":"f6lna-kbntjuwffpAAAB"},"nsp":"/"} +7ms
socket.io-parser encoded {"type":0,"data":{"sid":"f6lna-kbntjuwffpAAAB"},"nsp":"/"} as 0{"sid":"f6lna-kbntjuwffpAAAB"} +1ms
POST /login 200 653.887 ms - 37
socket.io-parser decoded 2["eventTable"] as {"type":2,"nsp":"/","data":["eventTable"]} +3s
socket.io:socket got packet {"type":2,"nsp":"/","data":["eventTable"]} +3s
socket.io:socket emitting event ["eventTable"] +0ms
socket.io:socket dispatching an event ["eventTable"] +1ms
socket.io-parser decoded 2["eventTable"] as {"type":2,"nsp":"/","data":["eventTable"]} +15ms
socket.io:socket got packet {"type":2,"nsp":"/","data":["eventTable"]} +2ms
socket.io:socket emitting event ["eventTable"] +0ms
socket.io:socket dispatching an event ["eventTable"] +1ms
The server side socket.emit call should have an event name as the first argument.
con.emit('eventTable', con.request?.user?.getEvents()?.map(e => e.toJSON()))
The problem was I was starting the server before initializing the sockets.js routes. I had to do some reconfiguring on the backend, but basically the way I fixed it was making an express router in sockets.js, importing said router to app.js, then doing app.use('/socket', sockets), BEFORE calling server.listen(PORT). Below is the final state of my backend:
new Backend file - init.js:
import express from 'express'
import { createServer } from 'http'
import session from 'express-session'
import { Server } from 'socket.io'
import { CrashCollector } from 'crashcollector'
new CrashCollector('crash_logs', (err, exit) => {
console.log('Cleaning up...')
console.log('Saving some stuff...')
// Calls callback funtion executing process.exit()
// You can also just write process.exit() here
exit()
})
const app = express();
const server = createServer(app)
const io = new Server(server, {
cookie: { maxAge: 24 * 60 * 60 * 1000 },
cors: {
origin: 'http://localhost:3000',
credentials: true
}
})
const sessionMiddleware = session({
secret: "changeit", resave: false,
saveUninitialized: false
});
export {
server,
app,
io,
sessionMiddleware
}
app.js:
'use strict';
import express from 'express'
import path from 'path'
import { fileURLToPath } from 'url';
import logger from 'morgan'
import cookieParser from 'cookie-parser'
import index from './routes/index.js'
import passport from './src/auth.js'
import { server, app, sessionMiddleware } from './init.js'
import sockets from './routes/sockets.js'
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(sessionMiddleware)
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', index);
*app.use('/sockets', sockets)* //This is the bit I was missing
// catch 404 and forward to error handler
app.use(function (req, res, next) {
let err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
console.log('dev error handler')
res.status(err.status || 500);
res.end()
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
console.log('prod error handler')
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.set('port', process.env.PORT || 3000);
server.listen(app.get('port'), _ => {
console.log(`Server listening on port ${app.get('port')}`)
})
sockets.js:
import { io, sessionMiddleware } from '../init.js'
import passport from '../src/auth.js'
import { getSequel } from '../src/database.js'
import { Router } from 'express'
const router = Router()
const wrap = middleware => (socket, next) =>
middleware(socket.request, {}, next);
io.use((_, next) => {
console.log('connection attempt')
next()
})
io.use(wrap(sessionMiddleware));
io.use(wrap(passport.initialize()));
io.use(wrap(passport.session()));
io.use((con, next) => {
console.log('socket check', !!con.request.user)
if (con.request.user) {
next()
} else {
next(new Error('unauthorized'))
}
});
io.on('connection', (con) => {
console.log(`new connection ${con.id}`);
con.on('confirm', cb => {
cb(con.request.user.name);
});
con.on('eventTable', cb => {
con.request.user.getEvents()
.then(events => events.map(e => e.JSON()))
//I switched to a callback here, rather than emitting a new event
.then(mappedArray => cb(mappedArray))
})
});
export default router
I have a test which is failing on Jest 27.5.1 (with babel-jest at the same version) with this error
I dont get this error when using Jest 26.6.3 (with babel-jest also at 26.6.3)
My test file
import supertest from 'supertest';
import {
buildAccount,
buildAuthenticationType,
createAccount,
createAuthenticationType,
} from './factories';
import {
startDatabase,
ENDPOINT_PREFIX,
clearDatabase,
doLogin,
} from './utils';
import { Account, AuthenticationType } from 'data/models';
import { app } from 'server/app';
const agent = supertest.agent(app);
const ENDPOINT = `${ENDPOINT_PREFIX}/account`;
describe('Account tests', () => {
beforeEach(async () => {
await startDatabase();
await doLogin(agent);
});
afterAll(async () => {
await clearDatabase();
console.log(typeof app.close, app.close);
await app.close();
});
test('/POST - Response with a new created account', async () => {
const relAuthenticationTypeIdDict = await buildAuthenticationType({});
const relFakeAuthenticationTypeId = await createAuthenticationType(
relAuthenticationTypeIdDict
);
const fakeAccount = await buildAccount({
authenticationTypeId: relFakeAuthenticationTypeId.authenticationTypeId,
});
const response = await agent.post(ENDPOINT).send(fakeAccount);
expect(response.status).toBe(201);
expect(response.statusCode).toBe(201);
const responseAccount = response.body.data;
const account = await Account.findByPk(responseAccount.accountId);
expect(account.email).toBe(fakeAccount.email);
expect(account.emailVerified).toBe(fakeAccount.emailVerified);
expect(account.isPrimary).toBe(fakeAccount.isPrimary);
expect(account.username).toBe(fakeAccount.username);
expect(account.password).toBe(undefined);
expect(account.pictureUrl).toBe(fakeAccount.pictureUrl);
expect(account.socialAccountId).toBe(fakeAccount.socialAccountId);
expect(account.authenticationTypeId).toBe(fakeAccount.authenticationTypeId);
});
});
My app.js file
import express from 'express';
import path from 'path';
import logger from 'morgan';
import passport from 'passport';
import swaggerUi from 'swagger-ui-express';
import { adminbroRouter } from './routes/adminbro.route';
import { router } from './routes';
import { sessionParser } from './session';
import { swaggerDocument } from './swagger';
import {
errorHandler,
responseHandler,
pageNotFoundHandler,
initResLocalsHandler,
} from './middlewares';
import { refreshFeedItemTagsQueue } from 'jobs/refresh-feed-item-tags';
import { ACCEPTED, NOT_FOUND, OK } from 'http-status';
import './passport';
const app = express();
// Swagger
app.use(
'/swagger',
swaggerUi.serveFiles(swaggerDocument),
swaggerUi.setup(swaggerDocument)
);
// Middlewares
app.use(logger('dev'));
app.use('/admin', adminbroRouter);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(sessionParser);
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
app.use(initResLocalsHandler);
app.use(process.env.BASE_PATH, router);
// Use custom response handler
app.use(responseHandler);
// Use custom error handler
app.use(errorHandler);
// Page not found
app.use(pageNotFoundHandler);
export { app };
My server.js file
// eslint-disable-next-line import/first
import http from 'http';
import { app } from './app';
import { sessionParser } from './session';
import { websocketServer } from './ws';
import 'jobs/repeatable';
const server = http.createServer(app);
server.on('upgrade', (request, socket, head) => {
sessionParser(request, {}, () => {
websocketServer.handleUpgrade(request, socket, head, (ws) => {
websocketServer.emit('connection', ws, request);
});
});
});
/* istanbul ignore next */
const PORT = process.env.PORT || 8000;
/* istanbul ignore next */
server.listen(PORT, () => {
// eslint-disable-next-line no-console
console.log(`Express server listening on port ${PORT}`);
});
How is it possible that the older version of jest does not give this error while the newer one does?
app created by express() doesn't have a close method. But const server = http.createServer(app);, the server has a close method.
You can start the server and listen to the connections in beforeAll and call server.close in afterAll. To achieve this, you need to export server so that the test file can get the server.
The statement inside the if (require.main === module) block will only be executed when running this script by node server.js.
E.g.
app.ts
import express from 'express';
const app = express();
app.get('/heartbeat', (req, res) => {
res.sendStatus(200);
});
export { app };
server.ts:
import http from 'http';
import { app } from './app';
const server = http.createServer(app);
const PORT = process.env.PORT || 8000;
if (require.main === module) {
server.listen(PORT, () => {
console.log(`Express server listening on port ${PORT}`);
});
}
export { server };
server.test.ts:
import supertest from 'supertest';
import { app } from './app';
import { server } from './server';
const agent = supertest.agent(app);
describe('server', () => {
before((done) => {
server.listen(7890, () => {
console.log('Test server listening on port: 7890');
done();
});
});
after((done) => {
server.close(done);
});
it('should pass', () => {
return agent.get('/heartbeat').expect(200);
});
});
Test result:
server
Test server listening on port: 7890
✓ should pass
1 passing (20ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 84.62 | 75 | 50 | 84.62 |
app.ts | 100 | 100 | 100 | 100 |
server.ts | 75 | 75 | 0 | 75 | 9-10
-----------|---------|----------|---------|---------|-------------------
server/src/index.js
import './env';
import fs from 'fs';
import cors from 'cors';
import path from 'path';
import helmet from 'helmet';
import morgan from 'morgan';
import express from 'express';
import favicon from 'serve-favicon';
import bodyParser from 'body-parser';
import compression from 'compression';
import * as Sentry from '#sentry/node';
import routes from './api/routes';
import json from './api/middlewares/json';
import logger, { logStream } from './utils/logger';
import * as errorHandler from './api/middlewares/errorHandler';
import initMongo from './config/mongo';
// Init MongoDB
initMongo();
// Initialize Sentry
// https://docs.sentry.io/platforms/node/express/
Sentry.init({ dsn: process.env.SENTRY_DSN });
// Initialize Express
const app = express();
const APP_PORT =
(process.env.NODE_ENV === 'test' ? process.env.TEST_APP_PORT : process.env.APP_PORT) || process.env.PORT || '3000';
const APP_HOST = process.env.APP_HOST || '0.0.0.0';
const pathToSwaggerUi = require('swagger-ui-dist').absolutePath();
app.set('port', APP_PORT);
app.set('host', APP_HOST);
app.locals.title = process.env.APP_NAME;
app.locals.version = process.env.APP_VERSION;
// This request handler must be the first middleware on the app
app.use(Sentry.Handlers.requestHandler());
app.use(express.static(path.join(__dirname, './public')));
app.use(cors());
app.use(helmet());
app.use(compression());
app.use(morgan('tiny', { stream: logStream }));
app.use(bodyParser.json());
app.use(errorHandler.bodyParser);
app.use(json);
// API Routes
app.use('/api', routes);
// Swagger UI
// Workaround for changing the default URL in swagger.json
// https://github.com/swagger-api/swagger-ui/issues/4624
const swaggerIndexContent = fs
.readFileSync(`${pathToSwaggerUi}/index.html`)
.toString()
.replace('https://petstore.swagger.io/v2/swagger.json', '/api/swagger.json');
app.get('/', (req, resp) => resp.sendFile(path.resolve(path.join(__dirname, './public', 'index.html'))));
app.get('/api-docs/index.html', (req, res) => res.send(swaggerIndexContent));
app.get('/api-docs', (req, res) => res.redirect('/api-docs/index.html'));
app.use('/api-docs', express.static(pathToSwaggerUi));
// This error handler must be before any other error middleware
app.use(Sentry.Handlers.errorHandler());
// Error Middlewares
app.use(errorHandler.genericErrorHandler);
app.use(errorHandler.methodNotAllowed);
app.listen(app.get('port'), app.get('host'), () => {
logger.info(`Server started at http://${app.get('host')}:${app.get('port')}/api`);
});
// Catch unhandled rejections
process.on('unhandledRejection', err => {
logger.error('Unhandled rejection', err);
try {
Sentry.captureException(err);
} catch (err) {
logger.error('Raven error', err);
} finally {
process.exit(1);
}
});
// Catch uncaught exceptions
process.on('uncaughtException', err => {
logger.error('Uncaught exception', err);
try {
Sentry.captureException(err); } catch (err) {
logger.error('Raven error', err);
} finally {
process.exit(1);
}
});
export default app;
server/src/api/routes/quizz.js
import express from 'express';
import passport from'passport';
import * as quizzController from '../controllers/quizz';
const router = express.Router();
const requireAuth = passport.authenticate('jwt', {
session: false,
});
/**
* GET /api/quizz
*/
router.get('/all', quizzController.fetchAll);
export default router;
server/src/api/routes/index.js
import express from 'express';
import fs from 'fs';
import { removeExtensionFromFile } from '../middlewares/utils';
import swaggerSpec from "../../utils/swagger";
import * as utils from '../middlewares/utils';
const router = express.Router();
const routesPath = `${__dirname}/`;
const isDynamicImport = routeFile =>
routeFile !== 'index' && routeFile !== 'auth';
/*
* Load routes statically and/or dynamically
*/
/**
* GET /api/swagger.json
*/
router.get('/swagger.json', (req, res) => {
res.json(swaggerSpec);
});
// Load Auth route
router.use('/', require('./auth'));
// Loop routes path and loads every file as a route except this file and Auth route
fs.readdirSync(routesPath).filter(file => {
// Take filename and remove last part (extension)
const routeFile = removeExtensionFromFile(file);
// Prevents loading of this file and auth file
return isDynamicImport(routeFile)
? router.use(`/${routeFile}`, require(`./${routeFile}`))
: '';
});
router.get('/', (req, res) => {
res.json({
app: req.app.locals.title,
apiVersion: req.app.locals.version
});
});
/*
* Handle 404 error
*/
router.use('*', (req, res) => {
utils.handleError(res, {
code: 404,
message: 'URL_NOT_FOUND',
});
});
export default router;
I am trying to get a list of all the quizzes but it returns this error
"throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))"
If someone has been in the same situation please help me please
You should check all your JavaScript files. It seems that this line is missing in any JS file:
module.exports = router
I followed the angular server-side rendering tutorial and created an express server.
How can I add SSL support?
I found how to add SSL in server.js but I don't know how to add it in Typescript.
server.ts
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import { renderModuleFactory } from '#angular/platform-server';
import { enableProdMode } from '#angular/core';
import * as express from 'express';
import { join } from 'path';
import { readFileSync } from 'fs';
enableProdMode();
const app = express();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist');
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');
const { provideModuleMap } = require('#nguniversal/module-map-ngfactory-loader');
app.engine('html', (_, options, callback) => {
renderModuleFactory(AppServerModuleNgFactory, {
document: template,
url: options.req.url,
extraProviders: [
provideModuleMap(LAZY_MODULE_MAP)
]
}).then(html => {
callback(null, html);
});
});
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
app.get('*.*', express.static(join(DIST_FOLDER, 'browser')));
app.get('*', (req, res) => {
res.render(join(DIST_FOLDER, 'browser', 'index.html'), { req });
});
app.listen(PORT, () => {
console.log(`Node server listening on http://localhost:${PORT}`);
});
——————
I used a Reverse Proxy instead
import the fs and https module
import { readFileSync } from 'fs';
import * as https from 'https';
Now create an object to set the key and certificate paths.
const options = {
key: readFileSync('./ssl/privatekey.pem'),
cert: readFileSync('./ssl/certificate.pem'),
};
https.createServer(options, app).listen(PORT , function(){
console.log("Express server listening on port " + PORT);
});