In first request I'm asking external server to provide a token. And I'm getting it. Then I would like to use it in another request. All is done in express.js. What is the best solution to provide it to the another request?
It looks like this:
const express = require('express');
const axios = require('axios');
const config = require('./config');
const app = express();
axios.post('URL1', {
email: config.email,
password: config.password,
})
.then(function(response) {
console.log(response.data.token); //here I' getting the token
})
.catch(function(error) {
console.log(error);
});
const headers = { headers: { 'Authorization': 'Token ' + token } }; //here I would like to use (for the use of a second request)
axios.get('URL2', headers)
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
const PORT = process.env.PORT || 5000;
app.listen(PORT);
Of course I cannot just assign it to the variable. Thank you for helping!
You can call it in another function just as shown below.
const express = require('express');
const axios = require('axios');
const config = require('./config');
const app = express();
axios.post('URL1', {
email: config.email,
password: config.password,
}).then((response) => {
// calling function here
return handleToken(response.data.token);
console.log(response.data.token); //here I' getting the token
}).catch((error) => {
console.log(error);
});
//second request will be handled here
const handleToken = (token) => {
const headers = { headers: { 'Authorization': 'Token ' + token } };
//here I would like to use (for the use of a second request)
axios.get('URL2', headers)
.then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
}
const PORT = process.env.PORT || 5000;
app.listen(PORT);
It's preferable if you write a separate function to avoid callback hell.
EDIT - ROUTE WITH ASYNC/AWAIT
app.get('/', async (req, res)=>{
try {
let result = await axios.post('URL1', { email: config.email, password: config.password });
let final = await handleToken(response.data.token);
// other operations here
console.log(result);
} catch (err) {
//handle error here
console.error(err);
}
})
//second request will be handled here
const handleToken = async (token) => {
try {
const headers = { headers: { 'Authorization': 'Token ' + token } };
let response = await axios.get('URL2', headers);
return response;
} catch (err) {
throw err;
}
}
Related
I´m trying to make a post request to a third party API.
In this request I have to send my username and password on the header, and It will return a response header with the X-Auth_token. The problem is that I´m not getting the X-Auth-Token in the header if I make the posto from a client to my server and then to the API. If I make the request from Postman directly to the API url, it works fine.
This is the code:
SERVER
app.post("/signin", async (req, res) => {
console.log("BODY", await req.body);
try {
const xToken = await axios.post(loginUrl, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-Username": req.body.username,
"X-Password": req.body.password,
},
});
console.log(xToken.headers);
//res.send(xToken);
} catch (error) {
console.log("SERVER Error: ", error.message);
}
});
CLIENT
const signin = async () => {
try {
const TOKEN = await axios.post("http://localhost:3000/signin", {
username: "AGU",
password: "MIOTTI",
});
console.log("TOKEN", TOKEN);
return TOKEN;
} catch (error) {
console.log("CLIENT Error: ", error.message);
}
};
signin();
What can be the problem?
some data of postman:
This is the response header when you try to make the post with postman directly to https://api.remarkets.primary.com.ar/auth/getToken:
and this is the response header when you make the reques to the serven on express:
The Server side as server.js file
const express = require("express")
const axios = require('axios')
const cors = require("cors")
const bodyParser = require('body-parser')
const corsOptions = {
exposedHeaders: 'Authorization',
};
const app = express()
app.use(cors(corsOptions))
app.use(bodyParser())
const loginUrl = 'https://api.remarkets.primary.com.ar/auth/getToken'
app.post("/signin", async (req, res) => {
console.log("BODY", await req.body);
const response = await axios.post(
url = loginUrl,
'',
config = {
headers: {
"X-Username": req.body.username,
"X-Password": req.body.password,
}
})
return res.send(response.headers["x-auth-token"])
});
app.listen(3000, () => { console.log("Listening on :3000") })
The Cliet side as client.js file
const axios = require('axios')
const signin = async () => {
try {
const response = await axios.post("http://localhost:3000/signin", {
username: "<your id>",
password: "<your password>",
});
return Promise.resolve(response.data);
} catch (error) {
return Promise.reject(error);
}
};
signin()
.then(token => {
console.log('token is : ' + token);
})
.catch(error => {
console.log(error.message);
});
Install dependencies
npm install express axios cors body-parser
Confirmed dependencies
$ npm ls --depth=0
# D:\temp\working
├── axios#1.3.2
├── body-parser#1.20.1
├── cors#2.8.5
└── express#4.18.2
Run Server first
node server.js
Run client later
node client.js
Result in client
References
Axios get access to response header fields
Unable to access JSON property with "-" dash
like the title says, here is my server file, I have tried every solution I could find on google yet I am still getting CORS errors. specifically XHROPTIONShttps://slug-panel-api.onrender.com/login
server.js:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser')
const mongoose = require('mongoose')
const userSchema = require('../../SlugAPI/Schemas/SlugSchemas')
const divisionSchema = require('../src/SlugSchemas/DivisionSchemas/DivisionSchema')
const subDivisionSchema = require('../src/SlugSchemas/DivisionSchemas/SubDivisionSchema')
const teamSchema = require('../src/SlugSchemas/DivisionSchemas/TeamSchema')
const divisionMemberSchema = require('../src/SlugSchemas/DivisionSchemas/DivisionMemberSchema')
let CryptoJS = require('crypto-js')
const PORT = process.env.PORT || 8080;
const app = express();
app.use(cors({
origin: "https://slug-panel.onrender.com",
headers: {
"Access-Control-Allow-Origin": "https://slug-panel.onrender.com",
"Access-Control-Allow-Credentials": true
},
}));
mongoose.set("debug")
const usar_db = mongoose.createConnection("mongodb:/<username>:<password>#slug-db:27017/usarAdmin?authSource=admin");
const User = usar_db.model('User', userSchema)
const Division = usar_db.model('Division', divisionSchema)
const SubDivision = usar_db.model('SubDivision', subDivisionSchema)
const Team = usar_db.model('Team', teamSchema)
const DivisionMember = usar_db.model('Division_Member', divisionMemberSchema)
function generateUserRegistrationKey(username, discord_id, rank, authentication_level) {
let key = username + '/' + discord_id.toString() + '/' + rank + '/' + authentication_level
const ciphertext = CryptoJS.AES.encrypt(key, 'secret').toString()
return ciphertext
}
function decryptUserRegistrationKey(key) {
const bytes = CryptoJS.AES.decrypt(key, 'secret')
const originalText = bytes.toString(CryptoJS.enc.Utf8)
return originalText
}
app.post('/login', bodyParser.json(), async (req, res, next) => {
const user = req.body.username
let pw = req.body.password
pw = CryptoJS.SHA256(pw)
let exists = await User.findOne({username: user})
if (exists) {
if (pw.toString() === exists['password']) {
res.send({
token: 'test123'
})
} else {
res.send({
error: 'passwordNotFound'
})
}
} else {
res.send({
error: 'userNotFound'
})
}
});
app.post('/generate', bodyParser.json(), async function (req, res, next) {
let username = req.body.username
let discord_id = req.body.discord_id
let rank = req.body.rank
let authentication_level = req.body.authentication_level
let exists = await User.exists({discord_id: discord_id})
let regKey = generateUserRegistrationKey(username, discord_id, rank, authentication_level)
const newUser = User({
username: username,
discord_id: discord_id,
rank: rank,
regKey: regKey,
authentication_level: authentication_level,
})
if (!exists) {
newUser.save()
.then(r => console.log("User " + username + " added to db"))
res.send({regKey: regKey})
}
})
app.post('/register', bodyParser.json(), async function (req, res, next) {
let key = req.body.regKey
let pw = CryptoJS.SHA256(req.body.password).toString()
let decryptedKey = decryptUserRegistrationKey(key).split('/')
let exists = await User.find({regKey: key}, function(err, docs) {
if (err) {
console.log(err)
} else {
console.log('Result: ', docs)
console.log(pw)
}
}).clone()
if (!exists) {
res.send({user: null})
} else {
res.send(JSON.stringify(exists))
}
await User.findOneAndUpdate({regKey: key}, { is_registered: true, password: pw, authentication_level: decryptedKey[decryptedKey.length - 1]})
})
app.post('/createDivision', bodyParser.json(), async function (req, res, next) {
let div_name = req.body.division_name
let div_id = req.body.division_id
let exists = await Division.findOne({division_name: div_name}, function (err, docs) {
if (err) {
console.log(err)
} else {
console.log(docs)
}
}).clone()
let idexists = await Division.findOne({division_id: div_id}, function (err, docs) {
if (err) {
console.log(err)
} else {
console.log(docs)
}
}).clone()
if (!exists || !idexists) {
const newDivision = new Division({
division_name: div_name,
division_id: div_id
})
newDivision.save()
.then(() => console.log('Division ' + div_name + ' has been added to the db'))
res.send(JSON.stringify(newDivision))
} else {
res.send({errorcode: 420})
}
})
app.post('/createSubDivision/:divid', bodyParser.json(), async function (req, res, next) {
const division = req.params['divid']
const sub_name = req.body.subdivision_name
const sub_id = req.body.subdivision_id
let exists = await Division.findOne({division_id: division}, function (err, docs) {
if (err) {
console.log(err)
} else {
console.log(docs)
}
}).clone()
if (exists) {
let subdivid_exists = await Division.findOne({
division_id: division,
subdivisions: {
$elemMatch: {subdivision_id: sub_id}
}
})
let subdiv_exists = await Division.findOne({
division_id: division,
subdivisions: {
$elemMatch: {subdivision_name: sub_name}
}
})
if (!subdivid_exists || !subdiv_exists) {
const subDiv = new SubDivision({
subdivision_name: sub_name,
subdivision_id: sub_id,
})
await Division.findOneAndUpdate({division_id: division}, { $push: {subdivisions: subDiv}})
console.log('subdivision ' + sub_name + ' added to: ' + exists.division_name)
res.send(JSON.stringify(subDiv))
} else {
res.send({division:'exists'})
}
}
})
app.listen(PORT, () => console.log('API is running on ' + PORT));
Tried every solution I could find both on random google websites and on stackoverflow. as stated previously it worked fine on the development server hosted locally.
for reference, here is how I am using fetch throughout the frontend
async function loginUser(credentials) {
return fetch('https://slugga-api.onrender.com/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'true'
},
body: JSON.stringify(credentials)
})
.then(data => data.json())
}
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://slugga-api.onrender.com/login. (Reason: CORS request did not succeed). Status code: (null).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://slugga-api.onrender.com/login. (Reason: CORS request did not succeed). Status code: (null).
Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource. asyncToGenerator.js:6:4
Babel 6
c Login.js:20
React 11
bind_applyFunctionN self-hosted:1683
Wt self-hosted:1640
React 3
forEach self-hosted:4909
React 2
<anonymous> index.js:7
<anonymous> index.js:17
<anonymous> index.js:17
You're misusing those CORS headers, both on the client side and on the server side. You should familiarise better with CORS and with the API of Express.js's CORS middleware.
Client side
The Access-Control-Allow-Origin header is a response header; including it in a request makes no sense.
async function loginUser(credentials) {
return fetch('https://slugga-api.onrender.com/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'true' // incorrect
},
body: JSON.stringify(credentials)
})
.then(data => data.json())
}
Server side
The headers property of your CORS config corresponds to request headers that you wish to allow, but what you've listed are response headers.
app.use(cors({
origin: "https://slug-panel.onrender.com",
headers: {
"Access-Control-Allow-Origin": "https://slug-panel.onrender.com", // incorrect
"Access-Control-Allow-Credentials": true // incorrect
},
}));
Instead, you most likely want something like
app.use(cors({
origin: "https://slug-panel.onrender.com",
headers: ["Content-Type"],
credentials: true,
}));
Fixed the issue by changing the CORS initialization in server.js
const app = express();
app.use(cors({
origin: "https://slug-panel.onrender.com"
}
))
app.options('*', cors())
I have two functions in functions.js - postData and startProcess. I am calling both functions in a function in server.js called sendData. sendData is then called in the app.post route.
In sendData, getData is called first and returns an id. This id is passed to startProcess and after it is run, a message that says 'success` should be printed. If it fails, a message that says 'failed to complete process should be returned'.
It seems like postData runs successfully, but startProcess is unable to pick or use its response as id.
When I run just the postData function in SendData, I get this error message:
JSON.stringify(value);
TypeError: Converting circular structure to JSON
What am I missing and how can I properly implement this?
functions.js
const axios = require("axios");
const BASE_URL = "http://localhost:1770";
const startProcess = async (id) => {
const headers = {
"Content-type": "application/json",
};
try {
return axios.post(`${BASE_URL}/start/${id}`, { headers });
} catch (error) {
console.error(error);
}
};
const postData = async (body) => {
const headers = {
"Content-type": "application/json",
};
try {
return axios.post(`${BASE_URL}/data`, body, { headers });
} catch (error) {
console.error(error);
}
};
server.js
const express = require("express");
const process = require("./functions.js");
const payload = require("./payload.json");
const res = require("express/lib/response");
// Create Express Server
const app = express();
app.use(cors());
// Configuration-api
const PORT = 5203;
app.use(express.json());
const sendData = async (req, res, next) => {
const body = payload;
try {
const response = await process.postData(body);
if ((response.status = 200)) {
let id = response.data;
const processResult = await process.startProcess(id);
if ((processResult.status = 200)) {
res.send("successfully started process");
}
}
} catch (error) {
console.error(error);
}
};
app.post("/data", sendData);
app.listen(PORT, () => {
console.log(`Running this application on the PORT ${PORT}`);
});
I am trying to make requests on behalf of users so for that I have successfully generated oauth_access_token and oauth_access_token_secret but whenever I make call to tweets https://api.twitter.com/2/tweets
it gives following error message: post daata {"errors":[{"parameters":{},"message":"Requests with bodies must have content-type of application/json."}],"title":"Invalid Request","detail":"One or more parameters to your request was invalid.","type":"https://api.twitter.com/2/problems/invalid-request"}
code:
oauth.js:
const OAuth = require('oauth');
module.exports = (oauthCallback) => {
const TWITTER_CONSUMER_KEY = process.env.TWITTER_CONSUMER_KEY;
const TWITTER_CONSUMER_SECRET = process.env.TWITTER_CONSUMER_SECRET;
const twitter_request_token_url = 'https://api.twitter.com/oauth/request_token';
const twitter_access_token_url = 'https://api.twitter.com/oauth/access_token';
const _oauth = new OAuth.OAuth(
twitter_request_token_url,
twitter_access_token_url,
TWITTER_CONSUMER_KEY, // consumer key
TWITTER_CONSUMER_SECRET, // consumer secret
"1.0",
oauthCallback,
"HMAC-SHA1"
);
const oauth = {
post: (url, oauth_access_token, oauth_access_token_secret, post_body, post_content_type) => {
return new Promise((resolve, reject) => {
_oauth.post(url, oauth_access_token, oauth_access_token_secret, post_body, post_content_type,
(error, data, response) => {
console.log("post daata", data)
console.log("post response", response)
if (error) {
reject(error);
} else {
resolve({ data, response });
}
}
);
});
}
};
return oauth;
};
route.js:
router.post('/twitter/tweet', async (req, res) => {
try {
const { response } = await oauth.post('https://api.twitter.com/2/tweets', oauth_access_token, oauth_access_token_secret, { "text": "Hello World!" }, 'application/json')
console.log("response backend data", response.data);
res.status(201).send({ message: "Tweet successful" });
} catch (error) {
res.status(403).json({ message: "Missing, invalid, or expired tokens" });
}
});
I thought there is some problem with node-oauth package (FYR: https://github.com/ciaranj/node-oauth/issues/364#issue-1076029771) so I switched to oauth1a but then I am getting 400 bad request for request token endpoint
code:
const crypto = require('crypto');
const OAuth = require('oauth-1.0a');
const axios = require('axios');
router.post('/twitter/oauth/request_token', async (req, res) => {
try {
const oauth = OAuth({
consumer: {
key: process.env.TWITTER_CONSUMER_KEY,
secret: process.env.TWITTER_CONSUMER_SECRET
},
signature_method: 'HMAC-SHA1',
hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
});
const authHeader = oauth.toHeader(oauth.authorize({
url: `https://api.twitter.com/oauth/request_token?oauth_callback=http://localhost:3000`,
method: 'POST'
}));
console.log("authHeader", authHeader)
const response = await axios.post(`https://api.twitter.com/oauth/request_token?oauth_callback=http://localhost:3000`, {
headers: {
Authorization: authHeader["Authorization"]
}
});
console.log("response", response)
res.status(200).send({ status: "ok" });
} catch (error) {
console.log("error", error)
res.status(404).json({
message: "Twitter request token failed",
});
}
});
Not sure if this issue is specific to node-oauth but using axios I was able to tweet using twitter v2 APIs. Working code snippet added for reference:
const express = require('express');
const router = express.Router();
const OAuth = require('oauth-1.0a');
const axios = require('axios');
router.post('/twitter/tweet', async (req, res) => {
try {
const oauth = OAuth({
consumer: {
key: process.env.TWITTER_CONSUMER_KEY,
secret: process.env.TWITTER_CONSUMER_SECRET
},
signature_method: 'HMAC-SHA1',
hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
});
const token = {
key: '',
secret: ''
};
const authHeader = oauth.toHeader(oauth.authorize({
url: 'https://api.twitter.com/2/tweets',
method: 'POST'
}, token));
const data = { "text": "Hello world!!" };
await axios.post('https://api.twitter.com/2/tweets',
data,
{
headers: {
Authorization: authHeader["Authorization"],
'user-agent': "v2CreateTweetJS",
'content-type': "application/json",
'accept': "application/json"
}
}
);
res.status(201).send({ message: "Tweet successful" });
} catch (error) {
console.log("error", error)
res.status(403).send({ message: "Missing, invalid, or expired tokens" });
}
});
I saw a similar question posted Here, but they are using MEAN-Stack.
I am currently just using a 'setTimeout' function to wait a few seconds before requesting new data from the server using a fetch api to give it time to update but this doesnt feel like the right way to do it. Is there a simple way for the front-end to update only after the database is updated in Express? I am new to Node please forgive me.
app.js:
const express = require('express');
const app = express();
const mysql = require('mysql');
let viewData = {
//html data
}
var pool = mysql.createPool({
connectionLimit : 10,
host: "localhost",
port: 3306,
database: 'testing',
user: "root",
password: "pass"
});
function sql(type) {
if(type == 'select') {
//Select query here
}
if(request == 'addRow') {
//Insert query here
}
}
app.get(`/`, function (req, res) {
res.sendFile('./views/index.html', {root: __dirname});
})
app.post('/api/add', function(req, res){
res.setHeader('Content-Type', 'application/json');
sql('addRow')
});
app.get('/api/viewData', function (req, res) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(viewData));
})
index.js:
function loadData() {
fetch('/api/viewData')
.then(z => z.json())
.then(a => {
//update html
})
}
function postData(a) {
fetch('/api/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
//data to send to app.js
})
}).then(setTimeout(function(){loadData();}, 3000))
}
You should use async and await function
Example: After async/await
async function fun1(req, res){
let response = await request.get('http://localhost:3000');
if (response.err) { console.log('error');}
else { console.log('fetched response');
}
The complete code of our example is shown below:
npm install express jsonschema body-parser promise-mysql
var express = require('express');
var bodyParser = require('body-parser')
var app = express();
var validate = require('./validate')
var mysqlConnection = require('./connectionShare');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const addItem = function(item, connection){
console.log("Adding Item");
return new Promise(function(resolve, reject){
connection.query("INSERT INTO product SET ?", item)
.then(function(result){
resolve(item.seller);
}).catch(function(error){
reject(error);
});
})
}
const findOrCreateUser = function(user,connection){
console.log("Finding User");
return new Promise(function(resolve,reject){
connection.query("SELECT * FROM user WHERE email=" + connection.escape(user.email))
.then(function(results){
if(results.length == 1){
resolve(results[0].id)
} else {
connection.query("INSERT INTO user SET ?", user)
.then(function(results){
resolve(results.insertId);
});
}
}).catch(function(error){
reject(error);
})
})
}
const selectUserItems = function(userID,connection){
console.log("Selecting Items " + userID);
return new Promise(function(resolve,reject){
connection.query("SELECT * FROM product WHERE seller = " + connection.escape(userID))
.then(function(results){
resolve(results);
}).catch(function(error){
reject(error);return;
});
})
}
app.post('/add/product', validate.JsonValidation, mysqlConnection.getConnection, async function(req,res){
var connection = req.connection;
var item = {
name: req.body.name,
price: req.body.price,
width: req.body.width,
height: req.body.height,
added: req.body.added,
image: req.body.image
};
var user = {
username: req.body.seller.username,
email: req.body.seller.email,
votes: req.body.seller.votes
};
try {
item.seller = await findOrCreateUser(user,connection);
var user_id = await addItem(item,connection);
var items = await selectUserItems(user_id, connection);
connection.connection.release();
res.status(200).json(result);
} catch(error) {
res.status(500).end(error);
}
});
process.on('uncaughtException', error => console.error('Uncaught exception: ', error));
process.on('unhandledRejection', error => {console.error('Unhandled rejection: ', error));
app.listen(8000, function () {
console.log('App listening on port 8000')
});