I'm building MEAN stack app, so I have at backend node+express server, Angular on front.
Atm I need to reach a remote non-cors server with data by sending a POST request to it. Googled for a day, and understand that I need to establish a proxy middleware. Trying to use this on backend server:
app.use(
"/getPrice",
createProxyMiddleware({
target: someurl,
changeOrigin: true,
logLevel: "debug",
onProxyReq(proxyReq, req, res) {
proxyReq.setHeader("X-DV-Auth-Token", sometoken);
proxyReq.setHeader("Access-Control-Allow-Origin", "*");
proxyReq.setHeader("Content-Type", "application/json");
req.body = JSON.stringify(req.body);
},
})
);
But request didn't return anything.
On other hand trying same url, payload and headers from PostMan, I have response with data exactly I need.
But PostMan offers only request-based solution which I can't adopt for using with express and http-proxy middleware
var request = require('request');
var options = {
'method': 'POST',
'url': someurl,
'headers': {
'X-DV-Auth-Token': sometoken,
'Content-Type': 'application/json',
'Cookie': somecookie
},
body: JSON.stringify({requestBodyObject})
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
Please, point me, where I probably missing a bit, or suggest how to adopt PostMan's code into express & http-proxy solution.
Thanks in advance
Appending req.body in http-proxy should be done using proxyReq.write(JSON.stringify(body)).
So the modified createProxyMiddleware function would be:
app.use(
"/getPrice",
createProxyMiddleware({
target: someurl,
changeOrigin: true,
logLevel: "debug",
onProxyReq(proxyReq, req, res) {
proxyReq.setHeader("X-DV-Auth-Token", sometoken);
proxyReq.setHeader("Access-Control-Allow-Origin", "*");
proxyReq.setHeader("Content-Type", "application/json");
console.log(req.body);
if (req.body) {
let bodyData = JSON.stringify(req.body);
// stream the content
proxyReq.write(bodyData);
}
},
})
);
Also, before you try the above changes, please make sure if you are receiving data in req.body or not.
Related
I have a project where I set a cookie with universal-cookie.
cookies.set('auth-token', data);
I then have a fetch request:
const getMeals = async (date: Date) => {
let res= await fetch("http://127.0.0.1:5000/meals/", {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
date: date
}),
});
const data = await res.json();
console.log(data);
}
And a backend where it gets checked (NodeJs, ExpressJs):
module.exports = function(req, res, next){
const token = req.header('auth-token');
if(!token){
return res.status(401).json('Access denied!');
}
}
I see the cookie in my mozilla:
But I always get "Access denied!" -> that means the auth-token is not there...
I hardcoded the auth-token into the fetch and it worked.
I checked several websites and almost all stackoverflow posts on this theme. I also checked the fetch-api documentation, but I couldnt come up with a solution...
Both the client and the server are running on localhost.
I hope someone can help me with this topic.
UPDATE
Andreas suggested that I should either set the header(frontend) or look for cookie- instead of header-values(backend).
I decided to do the second approach.
Server.js
var cookieParser = require('cookie-parser')
const usersRouter = require('./routes/users'); //where auth.js gets imported
app.use(cors());
app.use(express.json());
app.use(cookieParser());
app.use('/users', usersRouter);
I tried changing the position of app.use(cookieParser()); to above all others - didnt help.
auth.js
module.exports = function(req, res, next){
const cookie = req.cookies['auth-token'];
console.log(cookie);
}
The problem I now have is that the cookie value is undefined even though the cookie gets displayed in FireFox.
I tried to do the steps of this post, but this doesnt work afterwards I went to their official documentation and found nothing.
I also stumbled upon this one, which makes me think that something is wrong in the frontend...
Frontend-File where I set the cookie:
import Cookies from 'universal-cookie';
const cookies = new Cookies();
const login = async () => {
let res= await fetch("http://127.0.0.1:5000/users/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: (e.target as HTMLFormElement).email.value,
password: (e.target as HTMLFormElement).password.value,
}),
});
const data = await res.json()
if(res.status === 200){
cookies.set('auth-token', data);
setUserId((jwt_decode(data) as any)._id);
navigate("/");
}else{
alert(data);
}
}
Does someone have an idea?
I could fix the problem with the help of a friend. I had to add "proxy": "http://localhost:5000/" to my package.json in my React-Project, because the port is important for the cookie so localhost:5000 and localhost:3000 are not the same for it. I could also remove the app.use(cors()) from my NodeJs-Project, because of it.
I would suggest you run your front end on http://127.0.0.1:3000. If you are already doing that then you have to call fetch with credentials options set to include.
This is because unless fetch() is called with the credentials option set to include, fetch():
won't send cookies in cross-origin requests
won't set any cookies sent back in cross-origin responses
As of August 2018, the default credentials policy changed to same-origin. Firefox was also modified in version 61.0b13)
I am trying to make POST request for OTP using Node.Js Express. Below is the code for making post request using request but I want to make post request using Express.
const request = require('request');
const options = {
method: 'POST',
url: 'https://d7-verify.p.rapidapi.com/send',
headers: {
'content-type': 'application/json',
authorization: 'undefined',
'x-rapidapi-key': 'e47df3d7e5msh868bdee0049d425p19',
'x-rapidapi-host': 'd7-verify.p.rapidapi.com',
useQueryString: true
},
body: {
expiry: 900,
message: 'Your otp code is {code}',
mobile: 971562316353,
sender_id: 'SMSInfo'
},
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
How can I make above request in Express framework?
Express, is a back end web application framework for Node.js. To receive such requests using Express.js the following code will be helpful
var express = require('express')
var app = express()
// POST method route
app.post('/sendotp', function (req, res) {
//Generate OTP
var otp=Math.floor(100000 + Math.random() * 900000);
//Get Mobile number from response body
var mobile=req.body.mobile;
//Then send OTP to respective mobile number
// send sucess message to use
res.send('OTP Sent Successfully')
})
As you know we can't fetch a url on a client side due to CORS.
I am trying to create a function, that will fetch the file for me with the right headers as an agent, and will return it to the client.
So, on Firebase Function :
exports.urlToBlob = functions.https.onRequest((request,response) => {
cors(request, response, () => {
var url = "https://..."; //request.query.url;
fetch (
url,
{
method: 'GET',
headers: { 'Accept': '*/*' }
}
)
.then ((res) => {console.log(res);return res;})
.catch((err) => response.status(400).send(err))
});
});
I can see that it will access the url and get a respond on shell simulator, but not on browser, which will return nothing.
The client suppose to access it with :
var url = "https://us-central1-myproject-6xxxx.cloudfunctions.net/urlToBlob";
$.get(
url,
{url :imgurl, platform : 'xxx'},
function(data) {
console.log(data);
}
);
I know i am doing it wrong, but i have to find a way to use the function to solve the CORS.
Have you tried use cors lib from nodejs.
You can make a configuration for cors to allow cors in your instance.
First install cors lib:
npm install cors --save
After that you can configure cors in you main module application.
As an example:
const cors = require('cors')
//cors config
app.use(cors({
origin: ['https://example.com'] //<-- Here you put the domain you want to call your api
methods: "GET, POST, PUT, DELETE",
optionsSuccessStatus:200,
credentials: true
}))
In your code:
.then ((res) => {console.log(res);return res;})
You should change to:
.then ((res) => {
console.log(res);
//return res;
response.status(200).send(res);
})
I have issue with posting data from angular2 frontend api to backend client - nodeJS + mongoose.
On Angular2 client I make console.log using data, which I'am sending, and service display correct values.
On NodeJS backend I try also to console.log posted data, but I got undefined. Please look at code below, and try to figure out what I make wrong. I tried to this also with Promise<> and Observable<>, with same effect.
PS. GET data from NodeJS api via Angular 2 is working well.
PS2. Important fact, Problem exist, because angular2 doesnt make a headers in post or put. Every time, when I make POST Req, NODE Server logs OPTION /login. What that's mean?
Angular2:
signIn(data: Object): Observable<User> {
let bodyString = JSON.stringify(data);
let headers = new Headers({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
let options = new RequestOptions({ headers: headers });
console.log("data: ", data, "\nbodyString: ", bodyString, "\nHeaders: ", headers, "\nOptions: ");
return this.http
.post( this.signInUrl, bodyString, {headers: headers})
.map( (res:Response) => res.json() )
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
}
NodeJS:
[...]
// configure app
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var mongoose = require('mongoose');
var Test = require('./model/test');
var User = require('./model/user.schema');
mongoose.connect('mongodb://localhost:27017/lounge');
app.set('secret', config.secret);
app.get('/', function(req, res) {
res.json({ message: 'hooray! welcome to our api!' });
});
app.post('/login', function (req, res) {
console.log("Recived login request!", req.body);
});
[...]
I think your problem is how you are making the post request by not using the RequestOptions object you created.
signIn(data: Object): Observable<User> {
let bodyString = JSON.stringify(data);
let headers = new Headers({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
let options = new RequestOptions({ headers: headers });
console.log("data: ", data, "\nbodyString: ", bodyString, "\nHeaders: ", headers, "\nOptions: ");
return this.http
.post( this.signInUrl, bodyString, options) // **Change happens here
.map( (res:Response) => res.json() )
.catch((error:any) => Observable.throw(error.json().error || 'Server error'));
}
The only change is using the options (RequestOptions) you declared instead of trying to define "{ headers: headers }" in the post method.
This is my first time post. I hope this helped and this posts correctly.
I think problem is at nodejs and angular cominication. Because they work on different port they can not comminicate. So you should add this code to nodejs as middleware and also ı recommend you to search "cors express" and "cors npm package". I hope this solve your problem.
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
I'm using a combination of Express and Request (installed using npm) to try to send a get request to get some json from the server. However no matter what I do the body that is returned is "undefined".
This is the code in my server.js file. The json isn't actually what I'm sending, it's just an example as I can't post what I'm actually sending.
import express = require("express");
import bodyParser = require("body-parser");
let app = express();
app.use(bodyParser.json());
app.get('/config', function(req, res){
res.json('{name: test}');
})
app.listen(3000);
I've tried both of the following but both of them say that body is undefined.
import request = require("request");
let req = {
url: `http://localhost:3000/config`,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
request(req, function(error, response, body){
this.config = JSON.parse(body);
})
request(`/config`, function(err, res, body) {
this.config = JSON.parse(body);
});
Does anyone know what I'm doing wrong? I've never used express or request before so any tips would be greatly appreciated.
UPDATE
If I change the request code to the following, the inside of the function is never run. Does anyone know why this would be?
let req = {
url: `http://localhost:3000/config`,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
request(req, function(error, response, body){
console.log("response => "+JSON.parse(body));
return JSON.parse(body);
})
Since OP hasn't got it working and I believe the code he got up there is correct. I may as well post my working solution here to help him get started.
Hopefully this will save you hours of debugging...
Client:
"use strict";
let request = require("request");
let req = {
url: `localhost:4444/config`,
proxy: 'http://localhost:4444',
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
request(req, function (err, res, body) {
this.config = JSON.parse(body);
console.log("response => " + this.config);
});
Server:
"use strict";
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
var config = require('config');
app.use(bodyParser.json());
app.get('/config', function(req, res){
res.json('{name: test}');
});
// Start the server
app.set('port', 4444);
app.listen(app.get('port'), "0.0.0.0", function() {
console.log('started');
});
Output:
response => {name: test}
I dont't know if you have posted whole of your server's code, it seems like you missed app.listen(port) so that your server cannot be started up correctly.
Also, if you added if (error) { console.log(error); } at the first line of the callback function of request, you'll find it print an error: [Error: Invalid URI "/config"]
And that's why the body is always undefined: You have to give the full url such like http://localhost:xxxx to request.
In short:
Your server didn't listen to a specific port. app.listen(5678)
Your client didn't know the complete url. request('http://localhost:5678/config', (...)=>{...})