I have a Node server running a single-page Angular web app. The requests to my server come in from a reverse proxy that attaches a set of headers for authentication. On certain events, the Angular app sends requests to another server, and those requests need to have the same authentication headerset that the Node server received from the reverse proxy. Is there a mechanism by which I can send the headers from Node to the client-side Javascript so that I can then pass them through in the requests made by my Angular web app?
You can use ExpressJS for NodeJs. There's a headers object present into request and response objects you can read/write. You can send it to client through a parameter (maybe) It depends what your client receive.
Example in coffee
# JSON response width previously req.headers
app.get /hello, (req, res) ->
res.json { status: 'OK', data: { headers: req.headers }
# Or you can use setHeader to set a special param in header
app.get /hello, (req, res) ->
res.setHeaders "foo", "bar"
res.json { status: 'OK' }
Hope this helps!
Related
I have 2 node microservices and an event bus (which links all the microservices) running for my web app . one is basically a storage server and the other is the admin server . when a user signup the request (its content type is ['Content-Type', 'application/x-www-form-urlencoded' ] ) is first received by my event bus and if the request contains a profile photo as multipart/form-data the request is redirected to my storage server
but when storage server recives the request it is getting the body part as binary
and its content type is different
my storage server is working perfectly fine when I use postman and its content type will be this when I send it from postman
I am using AXIOS to redirect the request from one server to another is that is the problem ?
I think you shouldn't define content-type twice in axios.post() method. Check for example this:
axios.post('https://httpbin.org/post', { hello: 'world' }, {
headers: {
'content-type': 'text/json'
}
});
from https://masteringjs.io/tutorials/axios/post-headers
There are a few questions similar to this on Stack Overflow, and none of the proposed solutions worked, so I'll walk through the case and what I've tried.
I have a server application hosted on Cloud Run, which can only be accessed with the appropriate Bearer token in the request Authorization header. I've tried accessing it via Postman and an Axios request from a local Nodejs server, with the Authorization header, and it worked fine. With React (create-react-app specifically), I get the following error: Access to XMLHttpRequest at 'https://myserver-lhp5a9xp5a-ue.a.run.app/api/rules' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
On the server side, I get the 403 error that Cloud Run gives when the incorrect Authorization token is passed. Also, when I allow unauthenticated access from the Cloud Run side (so remove the need for an Authorization header), the request works fine, so it looks like this is indeed an issue with the Authorization header and not CORS.
In addition, I'm handling CORS on the server side. Here's my server-side code:
var express = require('express');
var router = express.Router();
const cors = require('cors');
router.options('/api/rules', cors());
router.get('/api/rules', cors(), (req, res, next) => {
res.status(200).send()
});
Here's my React code:
const axiosInstance = axios.create({
baseURL: process.env.REACT_APP_API_BASE_URL
});
const buttonClickHandler = async (event) => {
const resp = await axiosInstance.get('/api/rules'
, {
headers: {
'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsImtpZ...' // I used this token within the same minute when trying the request via Postman or from my Nodejs app, so a token expiry isn't the issue.
}
}
)
console.log(resp.data)
}
Here's what I tried so far:
Using fetch instead of axios - same error
Using the same token, within the same 5 seconds, to send the request from Postman or a Nodejs server - it worked fine.
Using an axios interceptor to set the Authorization - same error
Removing the single quotes around Authorization - same error
Sending the request to my Nodejs server instead and doing a console.log of the header to make sure the Authorization token is being passed correctly (it is)
Not using an an axios instance but spelling out the full URL in the request - same error
Trying a different endpoint on my Cloud Run server - same error
Deploying my React app to be served from a https endpoint and sending the request from there - same error
Adding Accept: '*/*' to the headers
Adding 'Accept': '*/*' to the headers
Adding 'Content-Type': 'application/json' to the headers
All combinations of the three above points
I found the answer after some digging, thanks #aniket-kolekar for pointing me in the right direction.
When Postman or a Nodejs server query an endpoint like GET, POST, PUT, DELETE, they send the call without checking the OPTIONS first. Create-React-App does.
The service I was querying is hosted on Cloud Run and doesn't allow unauthenticated invocations. So while I was including the authorization header to make my GET call, it wasn't being included in the pre-flight OPTIONS call. In fact, CORS prevents auth headers from being included in an OPTIONS call.
A Cloud Run PM replied in this post that this is a known issue with Cloud Run. The way I'll get around it for now is to host two services on Cloud Run - one that doesn't require authentication, and effectively acts as a proxy server to route calls from the client service to the shielded server service.
TLDR;
CORS is a mechanism built into the web browser. It’s not a UI code issue.
To fix CORS problems, you need to make changes on the API (server) side.
Here is the behind the scenes working:
Browser: Sends OPTIONS call to check the server type and getting the headers before sending any new request to the API endpoint. Where it checks for Access-Control-Allow-Origin. Taking this into account Access-Control-Allow-Origin header just specifies which all CROSS ORIGINS are allowed, although by default browser will only allow the same origin.
Postman: Sends direct GET, POST, PUT, DELETE etc. request without checking what type of server is and getting the header Access-Control-Allow-Origin by using OPTIONS call to the server.
You will have to configure Access-Control-Allow-Origin header in your server to resolve the CORS issue.
My Node.js server is not able to send the data it receives back to the browser. It is able to send self-made data like this
app.post('/login', (req,res) =>{
console.log(req.body);
res.setHeader('Content-Type', 'application/json');
res.json({test: "test info",test2: "still testing"});//works
//res.json(req.body);//does not work
})
In the fetch POST request, I have set the header 'Content-Type': 'application/json'.
In the firefox debugger, I can see that the information is sent via POST.
I have tried stuff like
res.json(req.body);
res.json(req.body.pass);
res.json({pass:+req.body.pass});//response in browser -> {"pass":null}
res.json("{pass:"+req.body.pass+"}");//response in browser -> "{pass:undefined}"
Could someone tell me why the Node.js server doesn't receive the JSON data?
Have you installed the body-parser
? Otherwise express wont convert the body of the POST request to a JSON object that you can access with req.body.pass
I am trying to fetch nodejs API request details like request header, response details, response time etc using nodejs script
request
.post('http://localhost:3000/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
I have tried with the packages like node-monitor- https://github.com/shunanya/Node.js-monitoring but it returns request details of all requests and need to pass server details and options
I was trying to use native node js functions and modules to get request and response details of API request for any request made using express, hapi, request, http
Basically I am trying to trigger one notification script when any http API request occurs from node application
I am using nodejs server, express framework and fetch library to send request to another server which is in different domain. For one of my endpoint consider (localhost:8080/login) i am rendering ejs file when the user clicks login button i am sending a fetch request to an api (https:otherserver.com/login) different server which is in other domain. i am not able to send this request. I am getting this error :
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 404. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I am not sure how to handle this issue. please suggest some ideas or links which can solve this issue.
You can use cors middleware on your server.
Simplest way to use it is to add :
app.use(cors())
before all of your route handlers.
I found the solution for my problem. I am trying to explain what i understood as i am a beginner in server side and web development.
This was the problem i faced :
For one of my endpoint in my nodejs server, consider (localhost:8080/login) i am rendering ejs file when the user clicks login button in that ejs file, i am sending a fetch request to an api (https:otherserver.com/signin) of different server which is in other domain. i am not able to send this request. I was getting cors problem.
Cors problem was occuring because the server domain(my nodejs server) which rendered the ejs file and the other domain(https:otherserver.com/signin) to which i was making fetch request after clicking login button was different.
so solution was :
I need to make the fetch request first to the same domain(my nodejs server localhost:8080/api/signin). And then from this server i should call the api of other domain(https:otherserver.com/signin). By doing this we wont get any cors issue. Because the client side ejs file is requesting to the same server which has rendered the file. And then the server is bypassing the request to the other server.
code from client side javascript file. /api/signin is an endpoint in my local nodejs server and u can add the options:
options ={
method : 'POST',
headers : {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
body : JSON.stringify({
email_address : emailId,
password : pwd
})
};
fetch("/api/signin",options)
.then(function(res) {
console.log(res);
}).catch(function(error) {
console.log(error);
});
code from local nodejs server side:
express.use('/api/', function (req, res, next) {
var options = {
method : req.method,
headers :req.headers,
body : JSON.stringify(req.body)
};
fetch('https://otherserver.com'+req.path,options)
.then(response => {
return response.json();
}, error => { console.error(error)})
.then(function(json){
res.send(json);
})
.catch(function(error) {
res.send(error);
});
})
Hope this may help someone who is beginner in server development.