How to Parse JSON and use axios without express - json

I'm currently making a twitter bot with node.js and I don't want to make a server with express unless I have to.
// imports
var Twit=require('twit');
var bodyParser = require('body-parser');
// config.js has my authentication
var config = require('./config');
var axios = require('axios');
axios.get('https://api.reddit.com/r/worldnews/hot.json?', { params: { sort: 'hot', limit: 1 } })
.then(response => {
var redditdata= response.data;
console.log(redditdata);
console.log(response.status);
})
var T = new Twit(config);
T.post('statuses/update', { status: redditdata.data.children.data.title + " " + redditdata.data.children.data.url }, function(err, data, response) {
console.log(data)
});
How do I input the reddit title and the url in the twitter post request? I know how to do this if with express server but how do I without a express?

Declare a global variable and then assign "redditdata.data.children.data" to that global variable inside your axios function. then you can access the data you want from a global variable. Right now, you are trying to get "redditdata.data.children.data" inside another function and it does not work because of function scope.

Related

Why can't send form-data in postman

Trying to send form-data in postman and sequelize return error:
value cannot be null
But when send raw request with json all ok. Trying body-parser and multer, but nothing working
This is my index.ts
import express from "express";
import fileUpload from "express-fileupload"
...
const app = express()
const PORT = process.env.PORT || 5100
app.use(cors())
app.use(express.json())
app.use('/api', router)
app.use(fileUpload({}))
app.use(errorHandler)
const start = async () => {
try {
await sequelize.authenticate()
await sequelize.sync()
console.log(chalk.cyanBright('Successful conection to data base'));
app.listen(PORT, () => { console.log(chalk.cyanBright(`Server has been started on port ${PORT}`)) })
}
catch (e) {
console.log(e);
}
}
start()
And this is my controller
export const DeviceController = {
async create(req: Request, res: Response, next:nextType) {
try {
const { brandId, typeId, name, price } = req.body
const img = req.files
let filename = 'uuid.v4()' + '.jpg'
img?.mv(path.resolve(__dirname, '..', 'static', filename))
const device = await Models.Device.create({ brandId, typeId, name, price, img: filename })
return res.json(device)
} catch (error: any) {
next(ApiError.badRequest(error.message))
console.log(error);
}
app.use(express.json())
You have body parsing middleware for JSON request bodies.
You don't have body parsing middleware for multipart/form-data request bodies. The documentation for body-parser lists a several middlewares you could use.
Trying body-parser
… which says it doesn't support that format
and multart
… that doesn't appear to exist. Do you mean multiparty? Or maybe multer?
We can't tell you what you did wrong without seeing your attempt.
Re edit:
You said:
const img = req.files
img?.mv(path.resolve(__dirname, '..', 'static', filename))
But the documentation says:
console.log(req.files.foo); // the uploaded file object
The files property contains all the files, indexed by the the names given to them in the multipart request.
You're trying to read that collection of files as if it were a single file.

How can I make multiple API calls with the same key

I'm working on my Project and currently I have one API call to spoonacular's search by recipe GET request. I want to add the search by video GET Request but I seem to having problems getting both to render at once into the DOM. How can I fix this issue?
const apikey = '';
const urls = { search:'https://api.spoonacular.com/recipes/complexSearch',
videos: 'https://api.spoonacular.com/food/videos/search'
};
function queryParams(params) {
const queryItems = Object.keys(params).map(key=>`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
return queryItems.join('&');
}
///render results
function getRecipe(tacos,maxResults){
const params ={
query: tacos,
number: maxResults,
};
const queryString = queryParams(params)
const url = urls+'?'+queryString +'&apiKey='+ apikey;
console.log(url);
fetch(url)
fetch(urls.search)
.then(response =>{
if(response.ok){
return response.json();
}
throw new Error(response.statusText);
})
.then(responseJson => displayResults(responseJson))
.catch(err =>{
$('#js-error-message').text(`Something went wrong: ${err.message}`);
});
}
Your urls is an object containing two strings. You need to treat it as such and make two separate calls.
You should have a fetch(urls.search) and fetch(urls.videos) call, each with their own response chain.
I'm not sure this code is doing what you think it is:
const url = urls+'?'+queryString +'&apiKey='+ apikey;
You'll need to append the queryString and apiKey to each string within urls separately. Something like
const searchUrl = urls.search+'?'+queryString +'&apiKey='+ apikey;
const videosUrl = urls.videos+'?'+queryString +'&apiKey='+ apikey;

Node.js + body-parser object format changes when it reaches backend

I'm trying to send an object inside an another object from React frontend to Node/express backend using jquery ajax. The problem the data is received at the backend, it no longer looks follows the syntax of an object. Instead, it looks something like this:
{ 'data[name]': 'test name',
'data[size][height]': '123',
'data[size][weight]': '50' }
Here is the front end ajax call...
lendItem(){
let id = "5af3348742afc60ab71d7d80"
$.ajax({
url: '/api/items/' + id,
method: 'put',
data: {
'data': {
name: "test name",
size: {
height: 123,
weight: 50
}
}
},
success: (res) => {console.log(res)}
});
}
backend server...
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
// connect to mongodb
mongoose.connect('mongodb://localhost/promedical');
mongoose.Promise = global.Promise;
const app = express();
const port = process.env.PORT || 5000;
// parsing data that was received
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// initialize routes
app.use('/api', require('./routes/api'));
// error handling
app.use((err, req, res, next)=>{
res.status(422).send({error: err.message});
});
app.listen(port, () => {
console.log(`Listening on port ${port}`)
});
...and here is the route I'm interested in.
router.put('/items/:id', (req, res, next)=>{
console.log(req.body);
res.send("success");
});
I think this problem might have something to do with that body-parser. Is is possible to send objects inside an object via jquery ajax and have it keep it's form once it reaches the backend? If not, should I just send all the data inside one object and then parse it at the backend?
It turns out that the object called 'data' becomes a string after the backend has accepted the ajax call. Is there any way to prevent this from happening? I need to store that object into a database as an object, not as a string.

How parse JSON properties from request body in express server?

I've set up a node server that passes requests to a utility class.
So far the POST request is hit but the mapping to the body property values are undefined. Bodyparser is also used in the post method to assist in the Json parse.
I stepped into the request and see that the body is populated and see that the property names are correct as shown in the paste below:
body: { '{\n\t"Email":"brian#gmail.com",\n\t"Dashboard_Name":"my dash 4",\n\t''},
But the below mapping to the values assinged via req.body.propertyname return undefined:
var p_email = req.body.Email;
var p_dashboardName = req.body.Dashboard_Name;
Question:
How can you parse JSON properties from request body in express server?
JSON object posted:
This is the JSON that I post to the server using Postman:
{
"Email":"brian#gmail.com",
"Dashboard_Name":"my dash 4"
}
Gist of the express server and associated utility method SaveUserProfile:
Express server -
var express = require('express');
var UserLDAP = require('./utilities/UserLDAP'); //utility file containing the POST method
var bodyParser = require('body-parser');
const url = require('url');
const app = express();
var sql = require('mssql');
const cors = require('cors');
const path = require('path');
sql.connect("********************************************************************")
.then((connection1) => {
sql.globalConnection = connection1;
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/OOO/SaveUserProfile', UserLDAP.SaveUserProfile)
app.listen(process.env.PORT || 4000 );
logger.info(`listening to port ${process.env.PORT}`);
}).catch((err) => {
res.status(500).send(err.message);
logger.error(err.message);
});
UserLDAP.js -
var sql = require('mssql');
var bodyParser = require('body-parser');
//Save User Profile
exports.SaveUserProfile = function(req, res) {
req.app.use(bodyParser.json());
req.app.use(bodyParser.urlencoded({ extended: true }));
var request = new sql.Request(sql.globalConnection);
console.log(req);
var p_email = req.body.Email;
var p_dashboardName = req.body.Dashboard_Name;
};
Turns out I had incorrect content-type set in Postman on the object being posted. Needed to be set as:
application/json; charset=UTF-8
Currently you have no way of knowing if a parser like body-parser.json has produced an error which seems the obvious place to start given the content is there but the result isn't.
I had a look at body-parser and found an issue that spoke to the problem of detecting a json error which I would expect to be good to know.
The developer suggested the following as one method.
app.use(errorFork(bodyParser.json(),
function (err, req, res, next) {
// do stuff with only body parser errors
}))
// this is an example; you can use any pattern you like.
function errorFork(middleware, errorHandler) {
middleware(req, res, function (err) {
if (err) {
return errorHandler(err, req, res, next)
}else{
return next()
}
})
}
It isn't a fix but it would give you more info. Something is going wrong with the parsing by what you have indicated the questin is what? The other thing I noticed about your pasted body content is that it isn't valid json (ignoring \n\t) you have a few rouge ' in there, worth checking. Try copying what is in body (raw) and put it through a json validator site like jsonlint.com just as a double check and see if body-parser is returning any errors.

Is there a way to set middleware in express (node.js) to have specific values return in every route?

The situation that I am specifically referring to involves the use of json web tokens (jwt). For example how would I automatically add middleware to only return a new json web token if that web token is expired without duplicating code? The sample code below will show what I mean.
var express = require("express");
var jwt = require('jsonwebtoken');
var router = express.Router();
router.use(function(req,res,next){
var token = req.body.token || req.query.token;
if (token) {
jwt.verify(token,"secretTingz",{algorithms:["RS256"]},function(err,decoded){
if (err) {
if (token.expired) {
// HOW DO I GET THIS PIECE OF CODE TO RUN FOR EVERY VALID ROUTE THAT NEEDS A NEW TOKEN WITHOUT DUPLICATING CODE?
var token = jwt.sign({user:"MilnerJenkins"},cert,{algorithm:"RS256",expiresInMinutes:1});
req.token = token;
next();
}else{
return res.json({message:"Failed to authenticate token"});
}
}else{
req.decoded = decoded;
next();
}
})
}else{
return res.status(403).send({
message: "No token!"
});
}
});
apiRoutes.get("/stuff",function(req,res){
var token;
if (req.token) {
token = req.token;
};
res.json({message: "Dope API son!",token:token});
});
apiRoutes.get("/users",function(req,res){
var token;
if (req.token) {
token = req.token;
};
User.find({},function(err,users){
res.json({users: users, token: token});
});
});
As you can see code is being duplicated in both routes with this block:
var token;
if (req.token) {
token = req.token;
};
What can I do with express middleware to prevent this duplication?
The only way you could do this with a "middleware" is by having a handler at the end of your middlware chain that would send the response. That would mean all your handlers would have to pass the request and response down the chain. It would essentially be the last handler before your 404 handler. I do not recommend attempting that. Alternatively you can create a custom response method for your express app.
var app = require('express')();
app.response.myJsonRes = function(obj) {
if (this.req.token) {
obj.token = this.req.token;
}
this.json(obj);
};
app.get('/myRoute', function(req, res) {
// get data somehow
res.myJsonRes(data);
});
You coulld even change the standard json method.
var prevJson = app.response.json;
app.response.json = function(obj) {
if (this.req.token) {
obj.token = this.req.token;
}
prevJson.call(this, obj);
};