How to resolve KOA- next() is not a function error? - koa

I have built a simple koa framework application.After adding routes am trying to hit the /health GET route. It throws the below error:
TypeError: next is not a function
at cookieParser (c:\Userxxs\x\gimt\dp-my-app\node_modules\cookie-parser\index.js:46:14)
at dispatch (c:\Users\B748806a\gimt\dp-my-app\node_modules\koa-compose\index.js:42:32)
at bodyParser (c:\Users\B748806a\gimt\dp-my-app\node_modules\koa-bodyparser\index.js:95:11)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
Below are the files and their order of execution:
server.js
const app = require("./app.js");
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on port: ${PORT}`));
app.js
"use strict";
const koa = require('koa');
const koaRouter = require('koa-router');
const app = new koa();
const router = new koaRouter();
const middleware = require("./src/main/middlewares/middlewares");
const routes = require("./src/main/middlewares/route-path");
const init = async () => {
try {
/**
* Step 2: load endpoint routes for the application
*/
routes(router)
} catch (err) {
logger.error({
err
});
}
};
/**
* Step 1: load middleware setup - cors,helmet from KP Spring cloud service
*/
middleware(app);
init();
module.exports = app
middleware.js
const koa = require("koa");
const koaRouter = require('koa-router');
const router = new koaRouter();
const cors = require("koa-cors");
const compression = require("koa-compress");
const helmet = require("koa-helmet");
const cookieParser = require("cookie-parser");
const bodyParser = require('koa-bodyparser')
const ActuatorRouter = require('pm-js-actuator').koa //internal library
const ACTUATOR_OPTIONS = {
health: {
enabled: true
},
livenessprobe: {
enabled: true
},
env: {
enabled: false
},
info: {
enabled: true,
secure: false
}
}
function middleware(app) {
// Use the CORS for the time being.
app.use(cors())
// Let's don the security helmet
app.use(helmet())
app.use(helmet.frameguard())
app.use(helmet.ieNoOpen())
app.use(helmet.frameguard({
action: 'sameorigin'
}))
app.use(helmet.noSniff())
app.use(helmet.referrerPolicy({
policy: 'same-origin'
}))
app.use(helmet.xssFilter())
//app.disable('x-powered-by')
app.use(ActuatorRouter.getRouter(ACTUATOR_OPTIONS).routes())
app.use(bodyParser())
app.use(cookieParser());
// Set up compression
app.use(compression());
}
module.exports = middleware;
route-path.js
const RootHeathController = require("../controller/root-health-controller")
const routes = (router) => {
router.get("/health", RootHeathController.handler)
};
module.exports = routes
root-health-controller.js
const handler = async (ctx, next) => {
ctx.body="Hi";
}
module.exports = {
handler
};
The application is started successfully on port 3000. But when i hit, /health from postman, it throws the mentioned error. Any solution?

The problem here is, that cookie-parser seems to be an express - thing (see also repo url: https://github.com/expressjs/cookie-parser). So to test this I created a minimal version of your code:
const koa = require('koa');
const koaRouter = require('koa-router');
const bodyParser = require('koa-bodyparser');
const cookieParser = require("cookie-parser");
const app = new koa();
app.use(bodyParser());
app.use(cookieParser()); // <-- comment this line
const router = new koaRouter();
router.get("/health", async (ctx, next) => {
ctx.body = 'hi';
});
app.use(router.routes());
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on port: ${PORT}`));
Calling the localist:3000/health endpoint throws the same error. But if you comment the app.use(cookie-parser()) line all works fine.
The question is, why you would need this library? You should be able to set and get cookies in koa with ctx.cookies.get and ctx.cookies.set

Related

Upload image to server using expo-file-system

In a react native app, I am following the documentation of expo-file-system to upload an image from the gallery of my phone and send it to a node.js server that uses multer to process the file. Unfortunately, I am having the following error when I send the http request:
Possible Unhandled Promise Rejection (id: 1):
Error: Failed to connect to localhost/127.0.0.1:3000
I know that the server is working because I have tested it with the same client but using axios and fetch to send the request and it reached the server.
This is the code that I am using in the client side:
//.env
URL = 'http://localhost:3000/api/upload'
//uploadImage.js
import React, { useState } from "react";
import { View, Button, Image, StyleSheet } from "react-native";
import * as ImagePicker from 'expo-image-picker'
import * as FileSystem from 'expo-file-system';
import {URL} from "#env"
const ImageUpload = ()=>{
const [image, setImage] = useState('')
const [name, setName] = useState('')
const [type, setType] = useState('')
const openImageLibrary = async()=>{
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log('this is the result',result);
if (!result.canceled) {
const uri = result.assets[0].uri
const filename = uri.split('/').pop();
const match = /\.(\w+)$/.exec(filename);
const imageType = match ? `image/${match[1]}` : `image`;
setImage(uri);
setName(filename)
setType(imageType)
}
}
const sendPictureToServer = async()=>{
const response = await FileSystem.uploadAsync(URL ,image,{
fieldName: 'photo',
httpMethod: 'POST',
uploadType: FileSystem.FileSystemUploadType.BINARY_CONTENT,
})
}
return(
<View>
<Button title = 'select' onPress={openImageLibrary}/>
<Button title='send' onPress={sendPictureToServer}/>
</View>
)
}
This is the node.js server
//index.js
const Express = require('express')
const multer = require('multer')
const bodyParser = require('body-parser')
const app = Express()
app.use(bodyParser.json())
const upload = multer({ dest: 'uploads/' } )
app.get('/', (req, res) => {
res.status(200).send('You can post to /api/upload.')
})
app.post('/api/upload', upload.single('photo'), (req, res) => {
console.log('file', req.file)
console.log('body', req.body)
res.status(200).json({
message: 'success!',
})
})
app.listen(3000, () => {
console.log('App running on http://localhost:3000')
})

koa js backend is showing error - DB not connected -how to fix this issue

I am also trying different network connections it returns the same error. Please help I am stuck last 15 days in this error. Oh! last one thing my laptop IP is dynamically changing so what can I do know.
this is my mongoose connecter
const mongoose = require('mongoose')
const connection = () =>{
const str = 'mongodb://localhost:27017/524'
mongoose.connect(str , () =>{
console.log("Connection is successfull")
} )
}
module.exports = {connection }
this is server js
const koa = require('koa')
const cors = require('koa-cors')
const bodyParser = require('koa-parser')
const json = require('koa-json')
const {connection} = require('./dal')
const userRouter = require('./Router/userRouter')
const app = new koa()
const PORT = 8000
app.use(cors())
app.use(bodyParser())
app.use(json())
app.use(userRouter.routes()).use(userRouter.allowedMethods())
app.listen(PORT, ()=>{
console.log(`Server is running on port ${PORT}`)
connection();
})
this is modle class
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const UserSchema = new Schema ({
name:{
type:String,
required:true
},
email:{
type:String,
required:true,
unique:true
},
password:{
type:String,
required:true
},
role:{
type: Number,
default: 0
}
},{
timestamps:true
})
const User = mongoose.model('User', UserSchema)
module.exports = User
this is login route
const KoaRouter = require('koa-router')
const { register, login ,getAll } = require('../API/userAPI')
const userRouter = new KoaRouter({prefix: '/user'})
userRouter.post('/register', register)
userRouter.post('/login', login)
userRouter.get ('/get' , getAll)
module.exports = userRouter;
this is my contraller
const UserModel = require('../models/user.model')
const bcrypt = require('bcrypt')
const register = async (ctx) => {
try{
const user = ctx.request.body
const {name, email, password, role} = user
if (!name || !email || !password){
return (ctx.body = { message: "fill" });
}
else{
const exist = await UserModel.findOne({email})
if(exist){
return (ctx.body = { message: "User already exists" });
}else{
const salt = await bcrypt.genSalt();
const hashpassword = await bcrypt.hash(password, salt)
const newUser = new UserModel({
name,
email,
password : hashpassword,
role
})
await newUser.save()
return (ctx.body = { message: "User Registered" });
}
}
}catch(err){
console.log(err.message)
return (ctx.body = { message: err.message });
}
}
const login = async (ctx) => {
try{
const {email, password} = ctx.request.body
const user = await UserModel.findOne({email})
if (!user){
return ( ctx.body = {message:"User does not exist"})
}
else {
const isMatch = await bcrypt.compare(password, user.password)
if (!isMatch) {
return (ctx.body = { message:"Wrong Password"})
}else{
return (ctx.body = { user})
}
}
}catch(err){
return (ctx.body= {err})
}
}
const getAll = async (ctx) => {
try{
const users = await UserModel.find()
return (ctx.body = users)
}catch(err){
return (ctx.body= {err})
}
}
module.exports = {register, login ,getAll}
.
how to fix this.any ideas.Can any body guide me with this scenario.

Heroku Error: ENOENT: no such file or directory, stat '/app/build/index.html'

I am getting this error in my heroku logs.
Same Question
All the solutions provided here did not address the issue.
I tried the different variations of the get method:
app.use(express.static('build'));
app.get('*', function (req, res) {
res.sendFile('index.html');
});
What else could I try or am I missing from here?
App.js
const configuration = require('#feathersjs/configuration');
const feathers = require('#feathersjs/feathers');
const express = require('#feathersjs/express');
const socketio = require('#feathersjs/socketio');
const moment = require('moment');
class IdeaService {
constructor() {
this.ideas = [];
}
async find() {
return this.ideas;
}
async create(data) {
const idea = {
id: this.ideas.length,
text: data.text,
tech: data.tech,
viewer: data.viewer
};
idea.time = moment().format('h:mm:ss a');
this.ideas.push(idea);
return idea;
}
}
const app = express(feathers());
app.feathers().configure(configuration());
app.use(express.static('build'));
app.get('*', function (req, res) {
res.sendFile('index.html');
});
// Parse JSON
app.use(express.json());
// Configure SocketIO realtime API
app.configure(socketio());
// Enable REST services
app.configure(express.rest());
// Register services
app.use('/ideas', new IdeaService());
// Connect new streams
app.on('connection', conn => app.channel('stream').join(conn));
// Publish events to stream
app.publish(data => app.channel('stream'));
const PORT = process.env.PORT || 3030;
app.listen(PORT).on('listening', () => console.log(`Server running on port ${PORT}`));
app.service('ideas').create({
text: 'Build a cool app',
tech: 'Node.js',
viewer: 'John Doe'
});
export default IdeaService;
package.json

koa, sessions, redis: how to make it work?

I am trying to implement Firebase authentication with server-side sessions using koa, koa-session, koa-redis.
I just can't grasp it. When reading the koa-session readme, this is particularly cryptic to me (link):
You can store the session content in external stores (Redis, MongoDB or other DBs) by passing options.store with three methods (these need to be async functions):
get(key, maxAge, { rolling }): get session object by key
set(key, sess, maxAge, { rolling, changed }): set session object for key, with a maxAge (in ms)
destroy(key): destroy session for key
After asking around, I did this:
// middleware/installSession.js
const session = require('koa-session');
const RedisStore = require('koa-redis');
const ONE_DAY = 1000 * 60 * 60 * 24;
module.exports = function installSession(app) {
app.keys = [process.env.SECRET];
app.use(session({
store: new RedisStore({
url: process.env.REDIS_URL,
key: process.env.REDIS_STORE_KEY,
async get(key) {
const res = await redis.get(key);
if (!res) return null;
return JSON.parse(res);
},
async set(key, value, maxAge) {
maxAge = typeof maxAge === 'number' ? maxAge : ONE_DAY;
value = JSON.stringify(value);
await redis.set(key, value, 'PX', maxAge);
},
async destroy(key) {
await redis.del(key);
},
})
}, app));
};
Then in my main server.js file:
// server.js
...
const middleware = require('./middleware');
const app = new Koa();
const server = http.createServer(app.callback());
// session middleware
middleware.installSession(app);
// other middleware, which also get app as a parameter
middleware.installFirebaseAuth(app);
...
const PORT = parseInt(process.env.PORT, 10) || 3000;
server.listen(PORT);
console.log(`Listening on port ${PORT}`);
But then how do I access the session and its methods from inside other middlewares? Like in the installFirebaseAuth middleware, I want to finally get/set session values:
// installFirebaseAuth.js
...
module.exports = function installFirebaseAuth(app) {
...
const verifyAccessToken = async (ctx, next) => {
...
// trying to access the session, none work
console.log('ctx.session', ctx.session);
console.log('ctx.session.get():'
ctx.session.get(process.env.REDIS_STORE_KEY));
console.log('ctx.req.session', ctx.req.session);
const redisValue = await ctx.req.session.get(process.env.REDIS_STORE_KEY);
...
}
}
ctx.session returns {}
ctx.session.get() returns ctx.session.get is not a function
ctx.req.session returns undefined
Any clues?
Thanks!!
It works in my case, hope it helps you
const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')
const router = new Router()
const static = require('koa-static')
const session = require('koa-session')
// const ioredis = require('ioredis')
// const redisStore = new ioredis()
const redisStore = require('koa-redis')
const bodyparser = require('koa-bodyparser')
app.use(static('.'))
app.use(bodyparser())
app.keys = ['ohkeydoekey']
app.use(session({
key: 'yokiijay:sess',
maxAge: 1000*20,
store: redisStore()
}, app))
app.use(router.routes(), router.allowedMethods())
router.post('/login', async ctx=>{
const {username} = ctx.request.body
if(username == 'yokiijay'){
ctx.session.user = username
const count = ctx.session.count || 0
ctx.session.code = count
ctx.body = `wellcome ${username} logged in`
}else {
ctx.body = `sorry, you can't login`
}
})
router.get('/iflogin', async ctx=>{
if(ctx.session.user){
ctx.body = ctx.session
}else {
ctx.body = 'you need login'
}
})
app.listen(3000, ()=>{
console.log( 'app running' )
})

Nunjucks setup for koa v2

I have a Koa v2 app with koa-views#next as a renderer and nunjucks templating engine. Here is my working setup, which don't have any problem, I just confused with the double declaration of the views folder:
const Koa = require('koa');
const nunjucks = require('nunjucks');
const path = require('path');
const router = require('koa-router')();
const views = require('koa-views');
const app = new Koa();
const index = require('./routes/index');
app.use(views(path.join(__dirname, 'views'), {
extension: 'njk',
map: { njk: 'nunjucks' },
}));
nunjucks.configure(path.join(__dirname, 'views'), {
autoescape: true,
});
router.use('/', index.routes(), index.allowedMethods());
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(3000);
But if I don't do this, the rendering doesn't work. If I uncommenting the nunjucks.configure block, I'm getting the following error:
Template render error: (unknown path)
Error: template not found: layout.njk
Is there any problem with my setup?
I come up a solution to use nunjucks without any other renderer library in koa v2:
/*
USAGE:
import njk from './nunjucks';
// Templating - Must be used before any router
app.use(njk(path.join(__dirname, 'views'), {
extname: '.njk',
noCache: process.env.NODE_ENV !== 'production',
throwOnUndefined: true,
filters: {
json: function (str) {
return JSON.stringify(str, null, 2);
},
upperCase: str => str.toUpperCase(),
},
globals: {
version: 'v3.0.0',
},
}));
*/
// Inspired by:
// https://github.com/ohomer/koa-nunjucks-render/blob/master/index.js
// https://github.com/beliefgp/koa-nunjucks-next/blob/master/index.js
const Promise = require('bluebird');
const nunjucks = require('nunjucks');
function njk(path, opts) {
const env = nunjucks.configure(path, opts);
const extname = opts.extname || '';
const filters = opts.filters || {};
//console.time('benchmark');
const f = Object.keys(filters).length;
let i = 0;
while (i < f) {
env.addFilter(Object.keys(filters)[i], Object.values(filters)[i]);
i += 1;
}
//console.timeEnd('benchmark');
const globals = opts.globals || {};
const g = Object.keys(globals).length;
let j = 0;
while (j < g) {
env.addFilter(Object.keys(globals)[j], Object.values(globals)[j]);
j += 1;
}
return (ctx, next) => {
ctx.render = (view, context = {}) => {
context = Object.assign({}, ctx.state, context);
return new Promise((resolve, reject) => {
env.render(`${view}${extname}`, context, (err, res) => {
if (err) {
return reject(err);
}
ctx.body = res;
return resolve();
});
});
};
return next();
};
}
module.exports = njk;
Gist

Resources