Swagger is clobbering my ability to make Postman requests - express

I integrated Swagger to my backend API in Express and I cannot make any Postman requests to it unless I comment out the Swagger integration with the exception of the swagger.json. file.
This is what the configuration looks like in the router/ folder,
import express from 'express';
import swaggerUi from 'swagger-ui-express';
import swaggerDocument from '../swagger/swagger.json';
const router = express.Router();
router.get('/api-docs', swaggerUi.setup(swaggerDocument));
export { router as swaggerRouter }
And this is how it's integrated in the root app.ts file:
app.get('/', (req, res) => {
res.send('Howdy!');
});
app.use(swaggerRouter, swaggerUi.serve, auth.verifyAuth);
app.use(pingRouter);
app.use(async (req, res, next) => {
const result = await auth.verifyAuth(req).catch((err) => {
return err;
});
if (result.httpCode == 200) {
res.locals.authResult = result
next()
} else {
res.send(result)
}
});
Where I can look to get the bottom of this?

Related

Express: how to render static files from a specific route

app.js
import express from "express";
import { getTokenData } from "./src/services/dbServices";
const app = express();
app.get("/api/token/:token_id", (req, res) => {
const tokenId = req.params.token_id;
const worldMetadata = getTokenData(tokenId).metadata;
res.send(worldMetadata);
});
app.use(express.static("public"));
app.get("/api/animation/:token_id", (req, res) => {});
app.listen(5000, () => {
console.log("App running on port 5000");
});
Im trying to render static files from my server to display a p5.j script. right now the public directory is being rendered from the "/" route of my server thanks to the express.static. I'd like to render the public directory only when the url matches /api/animation/:token_id. I've been trying for hours to make this work

How to pass parameter in Express API with NuxtJs project?

I building project NuxtJs + ExpressJs(SSR type) with options as below
In file server/index.js i import API route
const express = require('express')
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
const app = express()
const fs = require('fs')
const api = require("./routes/routes.js")(app, fs);
// Import API route
app.use('/api', api);
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
config.dev = process.env.NODE_ENV !== 'production'
async function start () {
// Init Nuxt.js
const nuxt = new Nuxt(config)
const { host, port } = nuxt.options.server
await nuxt.ready()
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
}
// Give nuxt middleware to express
app.use(nuxt.render)
// Listen the server
app.listen(port, host)
consola.ready({
message: `Server listening on http://${host}:${port}`,
badge: true
})
}
start()
In routes/routes.js
// import other routes
const productRoutes = require("./product/products.js");
const appRouter = (app, fs) => {
// default route
app.get("/", (req, res) => {
res.send("welcome to the development api-server");
});
// // other routes
productRoutes(app, fs);
};
module.exports = appRouter;
And in product/products.js
const productRoutes = (app, fs) => {
app.get("/products", (req, res) => {});
app.post("/products", (req, res) => {});
app.put("/products/:id", (req, res) => {});
app.delete("/products/:id", (req, res) => {});
};
module.exports = productRoutes;
However, i have error TypeError: app.use() requires a middleware function. Maybe i cannot pass parameter (app, fs) when using app.use('/api', api) and need to handle Middleware.
I'm newbie with ExpressJs and Middleware. I don't know what i'm missing. I hope someone please give me a solution. Thanks very much.

Trying to use express middleware to serve third party API requests

Sorry if I posted this incorretly, it is my first question on Stack Overflow. I am currently trying to use express to serve third party API requests to my React front-end. This is because the steam api I use throws me a CORS error when requesting in the client-side. I tried to route the requests to my controller which makes the axios call, but I have had no luck. Not sure if I am doing something completely incorrect.
here is my server.js
const app = require('./app.js');
const PORT = process.env.PORT || 3005;
app.listen(PORT, () => console.log(`Listening on port: ${PORT}`))
and here is my app.js
const express = require('express');
const cors = require('cors')
const app = express();
app.use(cors())
module.exports = app
my routes:
const { Router } = require('express')
const controllers = require('../controllers')
const router = Router()
router.get('/', (req, res) => res.send('This is root!'))
router.get('/applist', controllers.getAllSteamGames)
router.get('/game/:id', controllers.getSingleGameSteam )
router.get('/gameSpy/:id', controllers.getSingleGameSpy)
module.exports = router
and lastly my controller:
const axios = require('axios');
const getAllSteamGames = async () => {
try {
const resp = await axios.get('https://api.steampowered.com/ISteamApps/GetAppList/v2?applist')
return resp.data
} catch (error) {
console.log(error)
throw error
}
}
Thank you for your help and time.
You aren't doing anything to send a response back to the client. If we look at the /applist route:
router.get('/applist', controllers.getAllSteamGames)
const axios = require('axios');
const getAllSteamGames = async () => {
try {
const resp = await axios.get('https://api.steampowered.com/ISteamApps/GetAppList/v2?applist');
return resp.data
} catch (error) {
console.log(error)
throw error
}
}
All, your getAllSteamGames() function does is return a promise that resolves to a value (remember all async functions return a promise). It doesn't send a response back to the client.
Then, if you look at the actual route handler, it doesn't send a response back to the client either. So, you get the request and never send a response. The client never gets a response.
What I would suggest is that you just send a response in your controller. It's already passed (req, res) as arguments to the function so you can use them.
router.get('/applist', controllers.getAllSteamGames)
const axios = require('axios');
const getAllSteamGames = async (req, res) => {
try {
const resp = await axios.get('https://api.steampowered.com/ISteamApps/GetAppList/v2?applist');
res.json(resp.data);
} catch (error) {
// send error status upon error
console.log(error);
res.sendStatus(500);
}
}

REST API router forward to Apollo GraphQL endpoinr

I have a node/express/Apollo application to provide GraphQL service to the frontend application. I also have the REST API endpoing in the application to provide service for legacy applications. I want to forward the REST API calls to the GraphQL endpoint. For example:
From
GET /api/roles
to
POST /graphql
{ *body* }
I tried like this:
// app.js
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import routes from './routes';
const port = process.env.PORT || 8088;
const app = express();
app.use('/api/roles', routes.role);
const server = new ApolloServer({
......
},
});
server.applyMiddleware({ app, path: '/graphql' });
app.listen({ port: port }, () => {
console.log(`Apollo Server on http://localhost:${port}/graphql`);
});
// routes/role.js
import { Router } from 'express';
const router = Router();
router.get('/', (req, res, next) => {
req.url = '/graphql';
req.originalUrl = '/graphql';
req.method = 'POST';
req.body = `
{
findRoles {
data {
roleId
name
}
}
}`;
return router.handle(req, res, next);
});
It doesn't work and gives the error "Cannot POST /graphql". Any idea how to do it?

Express: unable to access route from browser due to accept:application/javascript header missing

I'm new to express. I have a Vue application running on express. I have some API routes that I'm able to access using axios through the browser. To access those routes using postman I have to have the header:
accept: application/javascript
for it to return the result of the actual API. If I don't use this header, I get the generated index.html from webpack. I need to reuse one of these routes to return excel/pdf, based on a parameter and have it accessible via a link on the page.
Here's my server.js - based on https://github.com/southerncross/vue-express-dev-boilerplate
import express from 'express'
import path from 'path'
import favicon from 'serve-favicon'
import logger from 'morgan'
import cookieParser from 'cookie-parser'
import bodyParser from 'body-parser'
import webpack from 'webpack'
const argon2 = require('argon2');
const passport = require('passport')
const LocalStrategy = require ('passport-local')
const session = require('express-session')
import history from 'connect-history-api-fallback'
// Formal(Prod) environment, the following two modules do not need to be introduced
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import config from '../../build/webpack.dev.conf'
const app = express()
app.set('trust proxy', true)
app.set("view engine", "pug")
app.set('views', path.join(__dirname, 'views'))
app.use ('/', require('./routes'))
app.use(session({
secret: process.env.SESSION_SECRET || 'secretsauce',
resave: false,
saveUninitialized: true
}))
app.use(history())
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))
app.use(logger('dev'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: false
}))
app.use(cookieParser())
app.use(express.static(path.join(__dirname, 'public')))
const compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
stats: {
colors: true
}
}))
app.use(webpackHotMiddleware(compiler))
////////// PASSPORT ///////////////////////
app.use (passport.initialize ());
app.use (passport.session ());
async function authenticateUser (username, password) {
//...
}
passport.use (
new LocalStrategy (async (username, password, done) => {
const user = await authenticateUser (username, password)
if (!user) {
return done (null, false, {
message: 'Username and password combination is wrong',
});
}
delete user.password;
return done (null, user)
})
);
// Serialize user in session
passport.serializeUser ((user, done) => {
done (null, user);
});
passport.deserializeUser (function(user, done) {
if(user === undefined || !user || Object.keys(user).length === 0)
return done(null, false)
else
done (null, user);
});
//////////// passport end ///////////////
app.set("view engine", "pug")
app.use(express.static(path.join(__dirname, 'views')))
app.get('/', function (req, res) {
res.sendFile('./views/index.html')
})
app.get('/success', function (req, res) {
res.render('./views/success')
})
app.use ('/api', require('./api'))
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found')
err.status = 404
next(err)
})
app.use(function (err, req, res) {
res.status(err.status || 500)
res.send(err.message)
})
let server = app.listen(80)
export default app
And here's a bit of api.js
const {Router} = require ('express')
const router = Router()
router.get('/whome', function(req, res){
logger.info('whome', req.user)
return res.json(req.user)
})
router.get ('/hello', auth.isAuthenticated, async (req, res) => {
res.json ({text:'hello'})
})
module.exports = router
I can call http://localhost/api/hello from postman with the accept:application/javascript header and I get:
{
"text": "hello"
}
as expected. But if I call the same URL from the browser (and it's not sending that header), I get the created bundle index.html. How can I access these routes from the browser?
You have two options.
First one, try to add this in your server:
app.options('*', cors())
before to: app.set("view engine", "pug")
If that doesnt work, try to install this addon in your Google Chrome browser to test.
Allow-Control-Allow-Origin: *
And enable it. (The icon should be green instead of red).
Why this happens?
The request that's being made is called a preflight request.
Preflight requests are made by the browser, as CORS is a browser security restriction only - This is why it works in Postman, which is, of course, not a browser.
Reference: Preflight request