I can't get body of request for the POST http://127.0.0.1:3001/users?name=Slava.
Server responce 'name is required'. Method getUsers work correctly. RethinkDB works good, server.js works too. I searched for similar answers here, but there is nothing suitable. There are very old answers, but they are not relevant.
This is request: http://127.0.0.1:3001/users?name=bob (I use Postman for POST)
Why bodyParser don't work in my code? I have no idea why this happens.
const Koa = require('koa')
const logger = require('koa-morgan')
const bodyParser = require('koa-bodyparser')
const Router = require('koa-router')
const r = require('rethinkdb')
const server = new Koa()
const router = new Router()
const db = async() => {
const connection = await r.connect({
host: 'localhost',
port: '28015',
db: 'getteamDB'
})
return connection;
}
server.use(bodyParser());
const insertUser = async(ctx, next) => {
await next()
// Get the db connection.
const connection = await db()
// Throw the error if the table does not exist.
var exists = await r.tableList().contains('users').run(connection)
if (exists === false) {
ctx.throw(500, 'users table does not exist')
}
let body = ctx.request.body || {}
console.log(body);
// Throw the error if no name.
if (body.name === undefined) {
ctx.throw(400, 'name is required')
}
// Throw the error if no email.
if (body.email === undefined) {
ctx.throw(400, 'email is required')
}
let document = {
name: body.name,
email: body.email
}
var result = await r.table('users')
.insert(document, {returnChanges: true})
.run(connection)
ctx.body = result
}
router
.post('/users', insertUser)
server
.use(router.routes())
.use(router.allowedMethods())
.use(logger('tiny')).listen(3001)
Body parser is used to parse POST requests (for POST body), here you have to use req.query instead of req.body, follow up this question.
Related
i need to cache a query with redis and node js , the database is aws s3 ,the problem here as a noob ,i will recive the query as a string, i need to encode the keys in the body request so when i will later try to fetsch the data i will use one of those keys(they need to be seperated with '/') can anyone help me with that and bunch of thanks.
here is what i' tried to do:
const { default: axios } = require('axios');
const express = require('express');
const redisClient = require('./helper/Client')
const app = express();
const port = process.env.PORT || 3000
app.use(express.json());
async function fetchApi(species){
const apiResponse = await axios.get(`https://www.fishwatch.gov/api/species/${species}`)
console.log('request sent successfully');
return apiResponse.data
}
async function getSpeciesData(req, res) {
const species = req.body;
const keys = Object.keys(species);
const encodedParams = {};
for (const key of keys) {
const encodedKey = Buffer.from(key).toString('base64');
encodedParams[encodedKey] = species[key];
}
const key = JSON.stringify(encodedParams);
let resultat;
let isCached = false;
const cachedResponse = await redisClient.get(key);
if (cachedResponse) {
isCached = true;
const decodedResponse = Buffer.from(cachedResponse, 'base64').toString('utf-8');
resultat = JSON.parse(decodedResponse);
res.send({
fromCache: isCached,
data: resultat
});
console.log(cachedResponse);
} else {
const responseData = await fetchApi(keys.join('/'));
const encodedResponseData = Buffer.from(JSON.stringify(responseData)).toString('base64');
redisClient.SETEX(key, 3600, encodedResponseData);
res.send(responseData);
}
}
app.post("/fish", getSpeciesData);
app.listen(port, () => {
console.log(`Listening on ${port}`);
});
my code in github, but I didn't upload the latest version:
https://github.com/godzillalogan/markdownblog
I use node.js and express.js framework. Database use mongoDB.
I am using the package Imgur and dotenv, try to upload image to imgur.
But I encounter some bug:
bug:
App is running on http://localhost:3000
mongodb connected!
TypeError: Cannot read property 'then' of undefined
at Promise (D:\Github\markdownblog\helpers\file-helpers.js:26:7)
at new Promise (<anonymous>)
at imgurFileHandler (D:\Github\markdownblog\helpers\file-helpers.js:23:10)
at router.put (D:\Github\markdownblog\routes\modules\admin.js:115:26)
at process._tickCallback (internal/process/next_tick.js:68:7)
D:\Github\markdownblog\node_modules\imgur-node-api\lib\imgur.js:34
_cb(null, body);
^
TypeError: _cb is not a function
at Request._callback (D:\Github\markdownblog\node_modules\imgur-node-api\lib\imgur.js:34:9)
at Request.self.callback (D:\Github\markdownblog\node_modules\request\index.js:142:22)
at Request.emit (events.js:182:13)
at Request.<anonymous> (D:\Github\markdownblog\node_modules\request\index.js:856:14)
at Request.emit (events.js:187:15)
at IncomingMessage.<anonymous> (D:\Github\markdownblog\node_modules\request\index.js:808:12)
at IncomingMessage.emit (events.js:187:15)
at endReadableNT (_stream_readable.js:1094:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
[nodemon] app crashed - waiting for file changes before starting...
Here is my code:
app.js:
const path = require('path') // 引入 path 套件
const express = require('express')
const session = require('express-session')
const bodyParser = require('body-parser') //新版express以內建body-parser
const { engine } = require('express-handlebars');
const flash = require('connect-flash')
if (process.env.NODE_ENV !== 'production') { //要放在const routes = require('./routes')前面
require('dotenv').config()
}
const routes = require('./routes')
const app = express()
const PORT = process.env.PORT || 3000
const methodOverride = require('method-override') // 載入 method-override
//others code............
helpers/file-helpers.js:
const fs = require('fs') // 引入 fs 模組, fs 模組是 Node.js 提供專門來處理檔案的原生模組
//載入 imgur 套件
const imgur = require('imgur-node-api')
const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID
console.log('IMGUR_CLIENT_ID:',IMGUR_CLIENT_ID)
imgur.setClientID(IMGUR_CLIENT_ID)
const localFileHandler = file => { // file 是 multer 處理完的檔案
return new Promise((resolve, reject) => {
if (!file) return resolve(null)
const fileName = `upload/${file.originalname}`
return fs.promises.readFile(file.path)
.then(data => fs.promises.writeFile(fileName, data))
.then(() => resolve(`/${fileName}`))
.catch(err => reject(err))
})
}
const imgurFileHandler = file => {
return new Promise((resolve, reject) => {
if (!file) return resolve(null)
return imgur.upload(file.path)
.then(img => {
// resolve(img?.link || null) // 檢查 img 是否存在
resolve(img ? img.link : null)
})
.catch(err => reject(err))
})
}
module.exports = {
localFileHandler,
imgurFileHandler //img
}
routes/modules/admin:
const express = require('express')
const router = express.Router()
const Article = require('../../models/article');
const Category = require('../../models/category');
const User = require('../../models/user');
const Contact = require('../../models/contact');
const upload = require('../../middleware/multer') // 載入 multer
const { imgurFileHandler } = require('../../helpers/file-helpers') // 將 file-helper 載進來
////others code....
//edit user
router.put('/users/:id', upload.single('avatar'), async (req, res)=>{
try{
console.log('有到edit user嗎')
const _id = req.params.id
const { name,avatar,introduction } = req.body
const { file } = req // 把檔案取出來
const user = await User.findOne({ _id})
const filePath = await imgurFileHandler(file) // 把檔案傳到 file-helper 處理
user.name = name
// user.cover = filePath || user.cover
user.avatar = filePath || user.avatar
user.introduction = introduction
await user.save()
res.redirect('/about')
}catch(e){
console.log(e)
res.redirect(`/admin/users`)
}
// const {title,description,markdown} = req.body //和new一樣才能將markdown轉成html
// Article.create({...req.body})
// res.redirect('/')
////others code....
})
What I have try:
I think it is about promise problem, and localFileHandler in helpers/file-helpers.js is work successful , but why imgurFileHandler in helpers/file-helpers.js is not work .
Thank you for your help.
It's probably because imgur.upload() dosent support promises and you should pass a callback as a second argument to the function like this :
imgur.upload(file.path, (err, response) => {
if(err) {
return null
}
return response.data.link
})
I move it from helpers/file-helpers.js to routes/modules/admin.js. And the way
is success.
But I think there would have another better way.
routes/modules/admin.js
I add Imgur to the route in create article,edit article and edit user.
routes/modules/admin.js
//Create
router.post('/articles', upload.single('image'), async (req,res)=>{
// console.log(req.body)
// const article = new Article({
// title: req.body.title,
// description: req.body.description,
// markdown: req.body.markdown
// });
try{
const {title,category,description,markdown} = req.body
const{file} = req
console.log('file:',file)
if (file){
imgur.setClientID(IMGUR_CLIENT_ID)
imgur.upload(file.path,(err, img) =>{
Article.create({...req.body, image: file ? img.data.link: null})
})
}else{
Article.create({...req.body})
}
res.redirect('/admin/articles')
} catch(e){
console.log(e)
res.render('admin/articles',{ article })
}
})
////Update
//到edit頁
router.get('/articles/edit/:id', async (req, res) => {
// const _id = req.params.id
// return Article.findOne({ _id})
// .lean()
// .then((article) => res.render('edit', { article}))
// .catch(error => console.log(error))
try{
const _id = req.params.id
const article = await Article.findOne({ _id}).lean()
const categories = await Category.find().lean().sort({createdAt:'desc'})
res.render('edit', { article,categories})
}catch{
console.log(e)
res.redirect(`/articles/edit/:id`)
}
})
//edit article
router.put('/articles/:id', upload.single('image'), async (req, res)=>{
try{
const _id = req.params.id
const { title,description,markdown,category } = req.body
const { file } = req // 把檔案取出來
const article = await Article.findOne({ _id})
if (file){
// const filePath = await imgurFileHandler(file) // 把檔案傳到 file-helper 處理
imgur.setClientID(IMGUR_CLIENT_ID)
imgur.upload(file.path,async (err, img) =>{
// Article.update({...req.body, image: file ? img.data.link: article.image})
article.title = title
article.description = description
article.markdown = markdown
article.category = category
article.image = img.data.link
await article.save()
})
}else{
article.title = title
article.description = description
article.markdown = markdown
article.category = category
await article.save()
}
res.redirect('/admin/articles')
}catch(e){
console.log(e)
res.redirect(`/admin/articles`)
}
// const {title,description,markdown} = req.body //和new一樣才能將markdown轉成html
// Article.create({...req.body})
// res.redirect('/')
})
I'm using node.js and mongodb I need to know how to request the reading of a certain collection via API
(day_07-07-2021 is the collection to search)
in the Node.js route I wanted to query the collection day07072021, I wanted to know how I change the collection (on the fly) to query the route using the "req.param" received via URL.
so after setting the collection I'll do find();
Each day will have a collection.
http://localhost:3000/registry/windows2021/1101/day07072021
My actual code is (updated after: Selva Mary), but still not working.
logs.js
const express = require('express')
const router = express.Router()
const logs = require('../models/registry')
router.get('/:device/:rule/:bydate', async (req, res) => {
try {
let byDate = req.params.bydate +"info"
const logues = await db.collection(byDate).find({
'agent.name': req.params.device,
'rule.id': req.params.rule
}).sort({ 'id': -1 }).limit(15);
res.json(logues)
}
catch (err) {
res.status(500).json({ message: err.message })
}
})
server.js
require('dotenv').config()
const express = require('express')
const app = express()
const mongoose = require('mongoose')
const log = mongoose.set('debug', true)
mongoose.connect('mongodb://db:27017/datainfo', { useNewUrlParser: true,useUnifiedTopology: true })
const db = mongoose.connection
const registryRouter = require('./routes/registry')
app.use('/registry', registryRouter)
I hope its clear.
I get the message:
{"message":"db is not defined"}
Try this
router.get('/:device/:rule/:bydate', async (req, res) => {
try {
let byDate = req.params.bydate +"" // this makes the bydate as string. Collection name need to be in string
const logues = await logs.collection(byDate).find({
'agent.name': req.params.device,
'rule.id': req.params.rule
}).sort({ 'id': -1 }).limit(15);
res.json(logues)
}
catch (err) {
res.status(500).json({ message: err.message })
}
})
Im having problem following the documentation on image4io.
I just tried stuff. So the problem is that the image4io only returns Promise {}
here is my code
module.exports = function(app,db){
const Image4ioAPI = require('#image4io/image4ionodejssdk');
app.post('/addImage',(req,res)=>{
var apiKey = 'api key';
var apiSecret = 'api secret';
var api = new Image4ioAPI.Image4ioClient(apiKey, apiSecret);
let response=api.GetSubscription();
console.log(response)
})
}
It returns a promise you must use then or catch to access the response after the promise is fulfilled.
Ideal use case:
api.GetSubscription()
.then(response => {
// Response returns a JSON object, which can be accessed here
}).catch(error => {
throw error;
})
You can await a promise to show its result.
module.exports = function(app,db){
const Image4ioAPI = require('#image4io/image4ionodejssdk');
app.post('/addImage', async (req,res)=>{
var apiKey = 'api key';
var apiSecret = 'api secret';
var api = new Image4ioAPI.Image4ioClient(apiKey, apiSecret);
let response= await api.GetSubscription();
console.log(response)
})
}
I have followed this tutorial to upload files into IPFS using Node.js, but I had a problem which doesn't appear in the tutorial!
It is related to with Async and await function, I can't make this statement
const fileHash = fileAdded[0].hash;
I tried with await
const fileAdded = await ipfs.add({path: Name, content: file});
but unfortunately, I got an error which is (hash undefined).
I tried with a callback function, but I'm not sure about my way because (fileAdded) variable didn't give me any answer and also it was undefined,
this is a full code:
const ipfsClient = require('ipfs-http-client');
const express = require('express');
const bodyParser = require('body-parser');
const fileUpload = require('express-fileupload');
const fs= require('fs');
const ipfs = new ipfsClient({host: 'localhost', port: '5001', protocol: 'http'});
const app= express();
var hash = require('hash');
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended:true}));
app.use(fileUpload());
app.get('/',(req,res)=>{
res.render('home');
});
app.post('/upload',(req,res)=>{
const f= req.files.file;
const Name = req.files.file.name;
const filePath ="files/"+ Name;
f.mv(filePath,async(err)=>{
if(err){
console.log("error failed to download a file");
return res.status(500).send(err);
}
const fileh = await addFile(Name,filePath);
fs.unlink(filePath, (err)=>{
if(err) console.log("error");
});
res.render('upload',{Name,fileh});
});
});
const addFile= async(Name,filePath)=> {
const file=fs.readFileSync(filePath);
const fileAdded = await ipfs.add({path: Name, content: file});
const fileHash = fileAdded[0].hash;
return fileHash;
};
app.listen(3000,()=>{
console.log("server is listen");
});
this is the error appears:
i write a callback function like that :
const addFile= async(Name,filePath)=> {
const file=fs.readFileSync(filePath);
const fileAdded = await ipfs.add({path: Name, content: file},(err,res)=>{
if(err)
console.log(err);
const fileHash = fileAdded[0].hash;
return fileHash;});};
but the value of fileAdded and fileHash was undefined.
after i use this code from #Always Learning :
const addFile= async(Name,filePath)=> {
const file=fs.readFileSync(filePath);
const hashes = [];
const filesAdded = ipfs.add({path: Name, content: file});
for await (const result of filesAdded) {
hashes.push(result.hash);
console.log(result.hash);
console.log(result);
}
return hashes; // if you know it's just one for example
};
It gave me an information of a file, but hash does not work as it gave me undefined, I want extract just a hash like this "QmRndAYkvH3D2qhmYfaAZvWT6MDi4NiJPbzJor3EL87rrb"
Since ipfs.add() returns an async-iterable object, you need to use for async to go through it like this:
const addFile= async(Name,filePath)=> {
const file=fs.readFileSync(filePath);
const hashes = [];
const filesAdded = ipfs.add({path: Name, content: file});
for await (const result of filesAdded) {
if (result.hash) {
hashes.push(result.hash);
} else if (result.cid) {
hashes.push(result.cid.multihash); // guessing here - might be another part of the cid object
} else {
console.log("No hash found in",result);
}
}
return hashes[0]; // if you know it's just one for example
};
You have to change this:
const fileHash = fileAdded[0].hash;
into this:
const fileHash = fileAdded.hash;
(so remove [0]).
This worked for me: it has to do with the libraries.