HTTP Response not sending X-Auth-Token in Header - javascript

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

Related

AxiosError: Request failed with status code 404 shows when trying to get data from MongoDB database

I am trying to use the Get method from the code below. I can use the Post method to post new instances to the database but my Get method is not working. When I tried to use the Get method I encountered the "AxiosError: Request failed with status code 404" error.
This is my code that contains the Get and Post methods:
const express = require('express');
const mongoose = require('mongoose');
const { ObjectId } = require('mongodb');
const { connectToDb, getDb, URI } = require('./db');
const Root = require('../models/Root');
const port = process.env.PORT || 7000;
const URL = 'http://localhost:7000'
const axios = require('axios');
// init & middleware
const app = express();
const router = express.Router();
app.use(express.json());
mongoose.set('strictQuery', false);
mongoose.set('bufferCommands', false);
let db
connectToDb((err) => {
if (!err) {
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});
}
});
mongoose.connect(URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
// POST
app.post('/roots', async (req, res) => {
const { root_id, node_id, name } = req.body;
if (!root_id || !node_id || !name) {
return res
.status(400).send({ error: 'Please provide all required fields' });
}
const root = new Root({ root_id, node_id, name });
try {
const savedRoot = await root.save();
res.send(root);
} catch (err) {
//console.error('Error saving root:', err);
res.status(400).send(err);
}
});
// GET
app.get('/roots/:root_id', async (req, res) => {
try {
const response = await axios.get(
`${URL}/roots?filter={"where":{"root_id":${req.params.root_id}}}`
);
res.status(200).json(response.data);
} catch (err) {
console.error('Error getting root:', err);
res.status(400).send(err);
// res.status(500).json({ error: 'Could not fetch the root' });
}
});
// DELETE
app.delete('/roots/:root_id', async (req, res) => {
try {
await axios.delete(`${URL}/roots/${req.params.root_id}`);
res.status(200).json({ message: 'Root deleted successfully' });
} catch (err) {
console.error('Error getting root:', err);
res.status(400).send(err);
// res.status(500).json({ error: 'Could not delete the root' });
}
// Call to a method to delete all children nodes of the tree in the Node tables
});
// PATCH
app.patch('/roots/:root_id', async (req, res) => {
try {
const response = await axios.patch(
`${URL}/roots/${req.params.root_id}`,
req.body
);
res.status(200).json(response.data);
} catch (err) {
res.status(500).json({ error: 'Could not update the root' });
}
});
I use this code to connect to the database:
// Use this file to connect to database - easy to switch between local and cloud for testing
const{MongoClient} = require('mongodb')
let dbConnection
// Connect to local database
let URI = 'mongodb://127.0.0.1:27017/PM_AI'
module.exports = {
connectToDb: (cb) => {
MongoClient.connect(URI)
// MongoClient.connect(cloudURI)
.then((client) => {
dbConnection = client.db()
return cb()
})
.catch(err => {
console.log(err)
return cb(err)
})
},
getDb: () => dbConnection,
URI
}
ERROR LOG for the error that I encounter:
{
"message": "Request failed with status code 404",
"name": "AxiosError",
"stack": "AxiosError: Request failed with status code 404\n at settle (D:\\CSDS_395_Project\\AI-PM\\node_modules\\axios\\dist\\node\\axios.cjs:1900:12)\n at IncomingMessage.handleStreamEnd (D:\\CSDS_395_Project\\AI-PM\\node_modules\\axios\\dist\\node\\axios.cjs:2944:11)\n at IncomingMessage.emit (node:events:525:35)\n at endReadableNT (node:internal/streams/readable:1359:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:82:21)",
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"adapter": [
"xhr",
"http"
],
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"env": {},
"headers": {
"Accept": "application/json, text/plain, */*",
"User-Agent": "axios/1.3.3",
"Accept-Encoding": "gzip, compress, deflate, br"
},
"method": "get",
"url": "http://localhost:7000/roots?filter={\"where\":{\"root_id\":1}}"
},
"code": "ERR_BAD_REQUEST",
"status": 404
}
The URL that I use to test my method in Postman is http://localhost:7000/roots/1.
Please let me know what am I doing wrong with my code here.
Thank you very much!
In your expressjs server file, the url you are using in mongoose.connect() refers to the expressjs server itself instead of localhost mongodb instance
So in your server.js/app.js or whatever is your main expressjs server file,
const MONGO_URL = 'mongodb://127.0.0.1:27017/PM_AI'
I can also see that you are using both mongo client and mongoose which I don't understand why... You only need one of these libaries to connect to mongodb from your backend
Also your code is pretty messed up so I've made the following changes
No need to use mongoose strict query and other configurations, simply using mongoose.connect() in latest mongoose version is enough. As mongodb connection establishes, you can launch your server
In terminal, write npm install dotenv. It is a package that is used to access variables in .env file, without it your server won't work properly
I've removed mongo client as it is not needed, simply using mongoose is enough
I don't know why you are making axios requests to your own server. This axios thing is what is causing 404 error. You should use axios only when you need to make api calls from frontend, or make api calls from your backend to some other backend server. For your own server, you should always prefer using a controller function for every route otherwise you will get 404 error. By controller function, I mean instead of axios.get, you need to execute mongoModel.delete() instead of axios.delete() or return mongoModel.findById() instead of axios.get()
For mongodb connection, use MONGO_URL and for connecting your own server, use URL
So the final version of your code should look like:
const express = require('express');
const mongoose = require('mongoose');
const { ObjectId } = require('mongodb');
const Root = require('../models/Root');
const MONGO_URL = 'mongodb://127.0.0.1:27017/PM_AI'
const axios = require('axios');
// For environmental variables in .env file
const dotenv = require("dotenv")
dotenv.config()
// init & middleware
const app = express();
const router = express.Router();
app.use(express.json());
const port = process.env.PORT || 7000
const URL = `http://localhost:${port}`
mongoose.connect(MONGO_URL).then(() => {
console.log("Mongodb connected")
app.listen(port,() =>
{console.log("Server started") }
});
// POST
app.post('/roots', async (req, res) => {
const { root_id, node_id, name } = req.body;
if (!root_id || !node_id || !name) {
return res
.status(400).send({ error: 'Please provide all required fields' });
}
const root = new Root({ root_id, node_id, name });
try {
const savedRoot = await root.save();
res.send(root);
} catch (err) {
//console.error('Error saving root:', err);
res.status(400).send(err);
}
});
// GET
app.get('/roots/:root_id', async (req, res) => {
try {
const response = await axios.get(
`${URL}/roots?filter={"where":{"root_id":${req.params.root_id}}}`
);
res.status(200).json(response.data);
} catch (err) {
console.error('Error getting root:', err);
res.status(400).send(err);
// res.status(500).json({ error: 'Could not fetch the root' });
}
});
// DELETE
app.delete('/roots/:root_id', async (req, res) => {
try {
await axios.delete(`${URL}/roots/${req.params.root_id}`);
res.status(200).json({ message: 'Root deleted successfully' });
} catch (err) {
console.error('Error getting root:', err);
res.status(400).send(err);
// res.status(500).json({ error: 'Could not delete the root' });
}
// Call to a method to delete all children nodes of the tree in the Node tables
});
// PATCH
app.patch('/roots/:root_id', async (req, res) => {
try {
const response = await axios.patch(
`${URL}/roots/${req.params.root_id}`,
req.body
);
res.status(200).json(response.data);
} catch (err) {
res.status(500).json({ error: 'Could not update the root' });
}
});

Data not Found as POST request returns `JSON.stringify(value); TypeError: Converting circular structure to JSON`

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}`);
});

Axios call returns net::ERR_EMPTY_RESPONSE and I can't figure out why

Whenever I make an axios call to an the '/login' endpoint, I keep getting the following error printed in my browser console. I've included the server.js file and the file from where I'm making the call for your reference.
Dependencies installed in the client folder: axios, react, react-dom, react-router-dom
Dependencies installed in the server folder: cors, express, node, spotify-web-api-node
GET http://localhost:3001/login net::ERR_EMPTY_RESPONSE
index.js file
import axios from 'axios'
const Profile = () => {
const login = () => {
console.log("testing login function - client")
axios.get("http://localhost:3001/login")
.then(() => {
console.log("success")
})
.catch(() => {
console.log("error")
})
}
return (
<div className="profile">
.
.
.
<div className="button">
<button onClick={() => login()} className="btn">Log In</button>
</div>
</div>
</div>
)
}
export default Profile
server.js file
const SpotifyWebAPINode = require('spotify-web-api-node')
const express = require('express')
const cors = require("cors")
const app = express()
app.use(cors)
// This file is copied from: https://github.com/thelinmichael/spotify-web-api-node/blob/master/examples/tutorial/00-get-access-token.js
const scopes = [
'user-top-read',
'user-library-read',
'playlist-read-private',
'playlist-read-collaborative',
'playlist-modify-public',
'playlist-modify-private',
]
// credentials are optional
var spotifyApi = new SpotifyWebAPINode({
clientId: 'XXX',
clientSecret: 'XXX',
redirectUri: 'http://localhost:3001/callback',
})
app.get('/login', (req, res) => {
console.log("testing login endpoint - server")
res.redirect(spotifyApi.createAuthorizeURL(scopes))
})
app.get('/callback', (req, res) => {
const error = req.query.error
const code = req.query.code
const state = req.query.state
if (error) {
console.error('Callback Error:', error)
res.send(`Callback Error: ${error}`)
return
}
spotifyApi
.authorizationCodeGrant(code)
.then((data) => {
const access_token = data.body['access_token']
const refresh_token = data.body['refresh_token']
const expires_in = data.body['expires_in']
spotifyApi.setAccessToken(access_token)
spotifyApi.setRefreshToken(refresh_token)
console.log('access_token:', access_token)
console.log('refresh_token:', refresh_token)
console.log(
`Sucessfully retreived access token. Expires in ${expires_in} s.`,
)
res.send('Success! You can now close the window.')
setInterval(async () => {
const data = await spotifyApi.refreshAccessToken()
const access_token = data.body['access_token']
console.log('The access token has been refreshed!')
console.log('access_token:', access_token)
spotifyApi.setAccessToken(access_token)
}, (expires_in / 2) * 1000)
})
.catch((error) => {
console.error('Error getting Tokens:', error)
res.send(`Error getting Tokens: ${error}`)
})
})
app.listen(3001, () => {
console.log('Server live on port 3001')
})

Passing token to another request in Node.js

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;
}
}

Google Drive OAuth 2.0 Invalid grant_type

Following the example from OAuth2WebServer from google I'm trying to set up an authentication flow from an express app using the HTTP/REST method they have but with every request I am returned with an error
I went through Google OAuth “invalid_grant” nightmare — and how to fix it but unfortunately it did not help.
{
error: "unsupported_grant_type",
error_description: "Invalid grant_type: "
}
This is a shortened version of the error I am receiving. If you need to see more of the error let me know and I can post it.
Server
const express = require('express');
const axios = require('axios');
const { web } = require('./src/client_id.json');
const app = express();
const { client_id, client_secret } = web;
let count = 0;
app.use(express.json());
/*************************
** REDIRECT USER TO GOOGLE AUTH **
*************************/
app.get('/', (req, res) => {
const redirect_uri = 'http://localhost:5000/auth';
const scope = 'https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly';
const access_type = 'offline';
res.redirect(`https://accounts.google.com/o/oauth2/v2/auth?scope=${ scope }&access_type=${ access_type }&redirect_uri=${ redirect_uri }&response_type=code&client_id=${ client_id }`);
});
/*************************
** ON AUTH WE EXCHANGE ACCESS TOKEN FOR REFRESH TOKEN **
*************************/
app.get('/auth', (req, res) => {
count++;
if (count >= 2) {
return res.redirect('http://localhost:3000');
}
const { code } = req.query;
const redirect_uri = 'http://localhost:5000/auth';
const grant_type = 'authorization_code';
axios.post('https://www.googleapis.com/oauth2/v4/token', {
code,
client_id,
client_secret,
redirect_uri,
grant_type
}, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(data => {
console.log(data)
res.redirect('http://localhost:3000');
})
// ALWAYS HITS THE CATCH "Invalid grant_type"
.catch(err => {
console.log(err);
console.log('ERROR')
});
});
app.listen(5000, console.log('Server listening on port 5000'));

Categories

Resources