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
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')
})
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.
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
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' )
})
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