I am getting error on initial setup with Hapi and MongoDB and I am getting error after starting my server.
Code:
const Hapi = require('hapi');
var Boom = require("boom");
const dbOptions = {
url: "mongodb://localhost:27017/comparekaro",
settings: {
db: {
native_parser: false
}
}
}
const server = new Hapi.Server();
server.connection({
port : 3001,
router : {
stripTrailingSlash : true,
},
routes : {
cors : true,
}
});
server.route({
method: 'GET',
path: '/',
handler: (request, reply) => {
var db = request.server.plugins['hapi-mongodb'].db;
var ObjectID = request.server.plugins['hapi-mongodb'].ObjectID;
db.collection('catalogs').find((err, result) => {
if (err) return reply(Boom.internal('Internal MongoDB error', err));
reply(result);
});
}
});
server.route({
method: 'GET',
path: '/{name}',
handler: (request, reply) => {
reply(`i am ${request.params.name}`);
}
});
server.register({
register: require('hapi-mongodb'),
options: dbOptions
}, function (err) {
if (err) {
console.error(err);
throw err;
}
});
server.start((err) => {
if (err) {
throw err;
}
console.log(`Server running at: ${server.info.uri}`);
});
Move server.start callback inside the server.register callback, these are async operations that need to be run in a logical order.
Related
I am trying to pre save and hash password with bcrypt in mongoose in my next.js project, but password still unhashed. i tryed every link in stackoverflow and didnt solve it, the password still saved unHashed.
mongoose version: 6.9.1
this is my users.model file:
import {
models,
model,
Schema,
} from 'mongoose';
import bcrypt from 'bcrypt';
const UserSchema: Schema = new Schema({
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
displayName: {
type: String,
required: true,
},
role: {
type: String,
},
});
UserSchema.pre('save', function (next) {
console.log('Pre-Save Hash has fired.');
let user = this;
bcrypt.genSalt(10, (err, salt) => {
if (err) console.error(err);
bcrypt.hash(user.password, salt, (err, hash) => {
user.password = hash;
next();
});
});
});
const UserModel = models.Users || model('Users', UserSchema, 'users');
export default UserModel;
this is my adding function file:
import dbConnect from '#/utils/mongodb';
import UserModel from '#/models/user.model';
import { NextApiRequest, NextApiResponse } from 'next';
import { MongoError } from 'mongodb';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
// const { email, password } = req.query;
try {
dbConnect();
const query = req.body;
const newUser = new UserModel(query);
const addedUser= await newUser.save(function (err: MongoError) {
if (err) {
throw err;
}
});
res.status(200).json(addedUser);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Internal server error' });
}
}
i cant see the 'Pre-Save Hash has fired.' in my console also..
// You need to add user.isModified("password")
userSchema.pre("save", function (next) {
var user = this;
if (user.isModified("password")) {
bcrypt.genSalt(SALT_I, (err, salt) => {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) {
return next(err);
}
user.password = hash;
next();
});
});
} else {
next();
}
});
userSchema.methods.comparePassword = function (candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, (err, isMatch) => {
if (err) return cb(err);
cb(null, isMatch);
});
};
// to make register end point
import mongoose from "mongoose";
import User from "../../../models/User";
const dbConnect = async () => {
mongoose
.connect("mongodb://localhost:27017/test")
.then(() => {
console.log("Connected to mongoDb");
})
.catch((error) => {
console.log(error);
});
};
export default async function handler(req, res) {
try {
await dbConnect();
const query = req.body;
const newUser = new User(query);
await newUser.save(function (err, result) {
if (err) {
throw err;
} else {
res.status(200).json(result);
}
});
} catch (error) {
console.error(error);
res.status(500).json({ message: "Internal server error" });
}
}
thanks to all.
The problem was in my dbconnect file!
I am fetching a big problem with axios in my project. I used axios for fetching data in getServerSideProps. but is it showing 'Request failed with status code 404', in the same time i also used axios in useEffect where it get data from api.
export async function getServerSideProps() {
try {
const ApiUrl = apiBaseUrl + "/api/my-url";
const homeData = await axios
.get(ApiUrl)
.then((response) => {
return response.data;
})
.catch((error) => {
return error.message;
});
return {
props: {
homeData: homeData, // its is return Request failed with status code 404
error: false,
ApiUrl: ApiUrl,
},
};
} catch (e) {
return {
props: {
error: true,
homeData: null,
message: e.message,
},
};
}
}
through i cna not get data from getServerSideProps i used useEffect
useEffect(() => {
if (typeof props.homeData === "string") {
console.log(props); // it is showing error 'Request failed with status code 404'
} else if (props.homeData) {
console.log(props.homeData);
// setData(props.homeData);
} else {
axios
.get(apiBaseUrl + "/api/my-url")
.then((response) => {
seteData(response.data);
})
.catch((error) => {
console.log(error);
});
}
}, [props]);
I am trying to update a field to the document with findByIdAndUpdate. The field I am trying to update is defined in the Bar Model. And I can also assure that req.body.bookId has a valid id.
Here's how my request looks,
app.patch("/foo", async (req, res) => {
try {
await validateId(req.body.bookId);
let doc = await Bar.findByIdAndUpdate(
req.body.bookId,
{ DateT: Date.now() },
{ new: true }
);
res.send(doc);
} catch (err) {
console.log(err);
}
});
Bar schema,
const mongoose = require("mongoose");
const barSchema = mongoose.Schema({
bookId: {
type: String,
unique: true,
},
DateT: {
type: Date,
default: null,
},
});
module.exports = mongoose.model("Bar", barSchema);
use updateOne, when you use async don't use .then() use try/catch
test it:
app.patch("/foo", async (req, res) => {
try {
let doc = await Bar.updateOne(
{ bookId : req.body.bookId },
{ DateT: Date.now() },
{ new: true }
);
res.send(doc);
} catch (error) {
console.log(error);
}
});
app.patch("/foo", async (req, res) => {
await Bar.findByIdAndUpdate(
req.body.bookId,
{ DateT: Date.now()},
(err, docs) => {
if (err) {
console.log(err);
} else {
res.send(docs);
}
}
);
});
I'm trying to figure out how to stub mongoDB in hapi js to allow testing but I have no idea how to do it. I've tried checking out Sinonjs but I have no idea how to apply it in this particular case.
Here's some of the code:
// index.js
'use strict';
const Hapi = require('hapi');
const MongoJS = require('mongojs');
const server = new Hapi.Server();
server.connection({ host: 'localhost', port: 11001 });
server.app.db = MongoJS('crunchbase', ['companies']);
server.register([
{
register: require('./lib/plugins')
},
{
register: require('./lib/modules/companies'),
options: {
baseUrl: '/v1/companies'
}
}
], (err) => {
if (err) {
throw err;
}
server.start((err) => {
if (err) {
throw err;
}
server.log('info', `Server listening on ${server.info.uri}`);
});
});
module.exports = server;
Here's are the routes:
// companies.js
'use strict';
const Boom = require('boom');
const Joi = require('joi');
const error = Joi.object().keys({
statusCode: Joi.number(),
error: Joi.string(),
message: Joi.string()
});
const schema = Joi.object().keys({
_id: Joi.object(),
permalink: Joi.string(),
name: Joi.string(),
homepage_url: Joi.string(),
category_list: Joi.string(),
funding_total_usd: Joi.alternatives().try(Joi.number(), Joi.string()),
status: Joi.string(),
country_code: Joi.string().allow(''),
state_code: Joi.alternatives().try(Joi.string(), Joi.number()).allow(''),
region: Joi.string().allow(''),
city: Joi.string().allow(''),
funding_rounds: Joi.number(),
founded_at: Joi.string().allow(''),
first_funding_at: Joi.string(),
last_funding_at: Joi.string()
});
exports.register = (server, options, next) => {
const db = server.app.db;
const { baseUrl } = options;
server.route([
{
method: 'GET',
path: baseUrl,
config: {
description: 'companies',
notes: 'Get a list of companies from the database',
tags: ['api'],
validate: {
query: {
limit: Joi.number().min(1).max(20).default(5)
}
},
response: {
status: {
200: Joi.array().items(schema),
400: error,
500: error
}
}
},
handler: (request, reply) => {
db.companies.find().limit(request.query.limit, (err, docs) => {
if (err) {
return reply(Boom.wrap(err, 'Internal MongoDB error.'));
}
reply(docs);
});
}
}
]);
return next();
};
exports.register.attributes = {
pkg: require('./package.json')
};
And here's the test suite:
// companies.test.js
'use strict';
const Code = require('code');
const Lab = require('lab');
const lab = exports.lab = Lab.script();
const { describe, it } = lab;
const expect = Code.expect;
const Server = require('../../');
describe('Companies module test suite', () => {
const baseUrl = '/v1/companies';
it('should return array of 5 companies by default', (done) => {
Server.inject({
method: 'GET',
url: baseUrl
}, (response) => {
expect(response.statusCode).to.equal(200);
expect(response.result).to.be.an.array().and.have.length(5);
done();
});
});
it('should return array of 3 companies', (done) => {
Server.inject({
method: 'GET',
url: baseUrl + '?limit=3'
}, (response) => {
expect(response.statusCode).to.equal(200);
expect(response.result).to.be.an.array().and.have.length(3);
done();
});
});
it('should throw an error', (done) => {
Server.inject({
method: 'GET',
url: baseUrl + '?limit=me'
}, (response) => {
expect(response.statusCode).to.equal(400);
expect(response.result.error).to.equal('Bad Request');
done();
});
});
});
It works but only if there's a connection to the db which I want to decouple. Any help would be appreciated.
Here's a solution courtesy of devinivy
One approach I've taken is to place queries in server methods, then
stub out the server methods (server.methods.x = stubX) in my tests.
You could also check out proxyquire as suggested by timcosta
Here's the brief github discussion
If I want to configure the binaryMediaTypes [ 'image/jpg', 'text/html' ] for an API through nodejs. What is the right API to use? It looks like the below is not working.
const config = JSON.stringify({
"swagger": "2.0",
"info": {
"title": this.apiName
},
"x-amazon-apigateway-binary-media-types": [ 'image/jpg', 'text/html' ]
});
return new Promise((resolve, reject) => {
var params = {
restApiId: apiId, /* required */
mode: 'merge',
body: config
};
this.apiGatewaySDK.putRestApi(params, (err, data) => {
if (err) {
reject(err);
}
else {
resolve('binary set successfully');
}
});
});
we end up using updateRestApi(). Pls note the patchOpertions part, it is very unintuitive (sth aws sdk could improve? )
let patchOperationsArray = [];
patchOperationsArray.push(
{
op: 'add',
path: '/binaryMediaTypes/'+ e.replace("/", "~1")
}
);
const params = {
restApiId: apiId, /* required */
patchOperations:patchOperationsArray
};
this.apiGatewaySDK.updateRestApi(params, (err, data) => {
if (err) {
reject(err);
}
else {
this.serverless.cli.log('API Gateway Configuring: Binary support are set correctly');
resolve('binary set successfully');
}
});