Node Microservices. Transferring a request from one server to another server - node.js

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

Related

Requests with status 400 (Bad request) doesn't pipe the correct body

request 2.83.0
node 8.11
yarn 1.5.1
Operating System: Windows Server 2012 R2
We're using request to power our proxy. It works well for all requests, and we're even transferring big files (400MB), all methods work and etc.
We create our options object like this:
let options = {
method: req.method,
url: url,
headers: proxyHelper.getHeaders(req.headers)
};
// The auth header needed to make the request
options.headers['Authorization'] = `Bearer ${token}`;
And then send it to request.
request(options, (err, responseFromApi, body) => {
logger.log("Body from API")
logger.log(body)
}).pipe(res);
The problem happens on requests that return "Bad Request" in the body, (status code 400).
The logger loggs the correct body, but pipes the wrong body to the client. The client only receives
"Bad Request". Instead of a complete JSON object that contains the reason for the error.
We use iisnode (a plugin for IIS) to run Node. It works locally when we run iisnode, but when we deploy it, it doesn't work.
Any ideas? Is it request? Is it pipe? Is it iisnode?
After a lot of struggling and research and breaking down the the whole node app, it was in the end IIS that took the body and and replaced its content with the statusText...

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

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.

"Fetch failed loading" - fetch works in Postman but fails in Chrome & Safari

Update: Fixed. It looks like the request was coming back as a 503 (as it should), then my app refreshed and displayed the non-error message: "Fetch failed loading". I just wasn't seeing the response because of the refresh.
I am not able to make a fetch request from my locally-hosted Create-React-App to my Heroku-hosted Node server.
My Node server has CORS enabled. If I make a POST request via Postman, I get an appropriate response (503, because currently there is no database hooked up, so the data is not being saved. If I should be sending back a different response, let me know). My Postman request has 'application/json' as the content-type, no authorization, and a body of { "rating": "5", "zipcode": "0" }.
However, when I make a POST request from my React app, I get a message in my console: "Fetch failed loading: OPTIONS "https://shielded-gorge-69158.herokuapp.com/feedback"." There is no associated error, only the message. There is no information about the request in my Network panel.
The fetch request works when I do it locally, from localhost:3000 (my app) to localhost:5000 (my server). It only fails when I try to make the request to the (otherwise identical) server hosted on Heroku.
This is what the fetch request looks like:
return fetch('https://shielded-gorge-69158.herokuapp.com/feedback', {
method: 'POST',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify({ rating: userRating, zipcode: userZip })
}).then(res => {
if (!res.ok) {
throw new Error('Error:', res.statusText);
}
return res;
}).catch(err => console.error(err));
Edit: I'm continuing to research and it seems like Postman shouldn't/doesn't make preflight requests (https://github.com/postmanlabs/postman-app-support/issues/2845). So perhaps that is the issue — but why would the request be working when my server is local, but not when it is hosted on Heroku?
use 'Content-Type' instead of 'Content-type'.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests
https://fetch.spec.whatwg.org/#cors-safelisted-request-header
Explanation: when you use incorrect case then it is considered as a custom header and hence, a preflight request is sent in such cases. Now if OPTIONS request is implemented on server with correct cors spec then next POST will be sent, else it wont be sent and request will fail. More on this in above links.

How to load changes instantly - React Native

Question
How do I load new data every time it is added to the server?
What I would like to have happen
User opens app
User uploads text to server
The app displays the text from the server immediately
What is currently happening
Users uploads text to server
User reloads app
The app displays the text from the server
Server Side
I am using expressJS for the server and then I am saving all of the text that the server gets to an off-site mongoose DB.
More info
I am using a Node JS server
I am using the fetch API to communicate between the server and the
client
The client app is written with React Native
I don't know how your app makes requests. Some code from both server and client would be useful. But i can think two possible solutions for your situation:
Return your text from upload request
Since you need server's response AFTER user uploads text to server, you can use response data within upload request. Here is an example code:
fetch('https://your-server.com/api/upload-text/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
text: 'yourValue',
})
}).then(response => response.json())
.then(responseJson => {
// Here is your text returned from server
let serverText = responseJson.text
// Set your state here with new data
this.setState({
textFromServer: serverText
});
// Now you can display new data in your render method.
})
With this way, users do not need to reload the app to fetch new text data. Your app will be updated after server responds to upload request.
WebSocket
If the data that you need from server is not depends on a client request, you can use websockets. With this way, you can fetch / send any data from server or from other clients any time. React Native supports websockets. More on here

Send Headers from NodeJS to Angular

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!

Resources