Why body in fetch post response is null [duplicate] - node.js

This question already has answers here:
Handle response - SyntaxError: Unexpected end of input when using mode: 'no-cors'
(5 answers)
Closed 4 years ago.
When trying to resolve a fetch promise with JS is set the mode to 'no-cors' based on this answer. However setting the mode to 'cors' results in having:
Access to fetch at
'{endpoint}'
from origin 'http://localhost:3000' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled.
So I wrote this in my function:
search() {
return fetch(`${baselink}${summonerEndpoint}${summoner}${apikey}`, {mode: 'no-cors'}).then(response => {
return response.json()
}).then(jsonResponse => {
console.log(jsonResponse);
if (!jsonResponse.info) {
return [];
}
return jsonResponse.info.items.map(info => ({
id: info.id,
accountId: info.accountId,
name: info.name,
profileIconId: info.profileIconId,
revisionDate: info.revisionDate,
summonerLevel: info.summonerLevel
}));
});
}
This results in following error Uncaught (in promise) SyntaxError: Unexpected end of input for return response.json(), but with no further message. What am I doing wrong?

If an opaque response serves your needs
It doesn't. You want to see the response. You can't see an opaque response (that is what opaque response means).
no-cors mode means that if the browser has to do anything that requires permission from CORS, it will fail silently instead of throwing an error.
So it is silently failing to get the response, then trying to parse that nothing as JSON (which throws a different error).
You need:
To not use no-cors mode
The server to grant permission using CORS
See this question for more information about CORS in general.

Related

Why is postman showing error message but react app not showing it?

I am developing an API (AWS lambda function using nodejs). here I am checking if the files sent to API via HTTP POST are less than 2 MB. if they are more than that then I am raising an error.
import createError from "http-errors";
if (totalSize > sizeLimitInMB) {
throw new createError.Forbidden(
`Size of all the attachments combined should not exceed ${sizeLimitInMB} MB. The files you have submitted are ${totalSize} MB`
);
}
Now postman shows this error message correctly. But when I try to produce same situation using my react front end. I get this message instead
Access to XMLHttpRequest at 'MY_API_URL' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
an error occurred Error: Network Error
at createError (createError.js:16)
at XMLHttpRequest.handleError (xhr.js:84)
POST 'MY_API_URL' net::ERR_FAILED
I am not sure why CORS error, because it works if my files are less than 2 MB. my code in react component
try {
await submit(id, data);
setSaving(false);
history.replace("/");
} catch (error) {
setSaving(false);
console.error("an error occurred ", error);
}
Why is the frontend not able to console log the same error message as postman? and this is not just for this particular size error. Any other errors I throw such as "Only owner can delete this file" or "Post with this ID not found" are also not displayed in my frontend but work perfectly well in postman
I was able to solve this issue by changing the order of middlewares in common middleware. I had a function common middleware that used to wrap the handler
export const handler = commonMiddleware(myHandler);
Earlier it was
export default (handler) =>
middy(handler).use([
httpJsonBodyParser(),
httpEventNormalizer(),
httpErrorHandler(),
cors(),
]);
After
export default (handler) =>
middy(handler).use([
cors(),
httpJsonBodyParser(),
httpEventNormalizer(),
httpErrorHandler(),
]);
and it worked

Set response header along with a string

I am trying to send the token in the headers of an HTTP request from backend to the frontend along with sending my own defined string. However, I am getting an issue. The token is being printed as null on the client-side. I don't know why:
Here's my code:
Node/Express
if (bcrypt.compareSync(passcode, results[0].password))
{
const token = jwt.sign({id: email}, secret, {expiresIn: 86400 });
console.log(token);
if(results[0].userrights == 'full')
{
res.setHeader('x-access-token', token);
res.send("Full Authorization");
}
//rest of the code
}
Angular
this.http.post('http://localhost:3000/api/login', form.value, {responseType: "text", observe:
'response'})
.subscribe(responseData => {
console.log(responseData);
console.log(responseData.headers.get('x-access-token')); //prints null on the console
I have searched quite a bit and found different examples which is making it very confusing. I don't want to use response status rather my own defined string. I have tried different things to print the variable but it still is throwing as null.
If you are using a browser extension to allow CORS requests then Access-Control-Expose-Headers should be added to the headers on server side. Please try adding the following line: res.setHeader('Access-Control-Expose-Headers', '*')
Angular2 's Http.post is not returning headers in the response of a POST method invocation
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

Angular 8 / NodeJS CORS error: Redirect location disallowed

I am using Angular 8 with a NodeJS backend in a lab environment. I have a button in Angular which sends a value to the backend server using a POST request. When the value is received, the backend reaches out to an API server based on the value from the form which returns a status code in JSON which I need to use for conditionals in the frontend.
The Angular button logic looks like this:
this.form = this.fb.group({
ticket: [''],
})
}
const testTicket = this.form.value.ticket
submitForm() {
this.http.post('http://backend.com:8090/api/backendquery?testTicket='+ testTicket ,{}).subscribe (
(response) => {
console.log(response)
if(response != 'failure') {
this.ticketFound=true
this.ticketNotFound=false
status = 'Success'
} else {
// if(response == null) {
this.ticketNotFound=true
this.ticketFound=false
status = 'Failed'
}
})
}
The backend code reaching out to the API server looks like this:
var cors = require('cors');
app.use(cors());
app.post('/api/backendquery', function(req, res){
res.redirect('https://username:password#myserver.com/ticketquery='+req.query.testTicket);
});
I passed the credentials in the URL since the API server requires authentication.
I obtain the results successfully from Postman using the following URL:
http://backend.com:8090/api/backendquery?testTicket=12345
However, when using the browser by submitting the value, I get the following error on console:
'http://backend.com:8090/api/backendquery?testTicket=12345' from origin 'http://frontend:4200' has been blocked by CORS policy: Redirect location '' contains a username and password, which is disallowed for cross-origin requests.
As you can see in the backend code, the CORS package is already enabled which should take care of CORS errors. I aware that credentials should not be present in URLs, however, what could be take best approach in my situation?
The answer was that instead of redirecting in the backend, the GET request was done using the "required" package and then saved to a variable which was then forwarded back to the frontend.

Reactjs App request.get

I have a react js app which does a simple http get. It does not use webpack and use package.json
var request = require('request');
var options = {
url: 'http://localhost:8181/api/v1/status',
headers: {
'Access-Control-Allow-Origin':'*'
}
}
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
var info = JSON.parse(body);
console.log(info.stargazers_count + " Stars");
console.log(info.forks_count + " Forks");
}
}
request(options, callback);
This code is getting failed and I am getting the following error
localhost/:1 Failed to load http://localhost:8181/api/v1/status: 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:3000' is therefore not allowed access. The response had HTTP status code 405. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
The server which I am trying to access is running python and I am already appending necessary header to make the request.
I am quite new to reactjs
How to fix this issue?
Let's breakdown the error message. The first part:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Means your Python server did not set an Access-Control-Allow-Origin header. You should make sure your python server sets this header in the response. If that didn't work, continue:
The response had HTTP status code 405.
HTTP Status Code 405 means method not allowed. Your python server may also need to set the header: Access-Control-Allow-Methods: <method>, <method>. So in include each one you want to allow, such as GET, POST, OPTIONS.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods

Ajax POST to Node.js through Nginx not getting correct response

I'm trying to send an ajax post request to a node.js microservice through nginx. The requuest is as follows:
$.post('http://localhost:80/api/signup', formData, function( data, status) {
console.log(JSON.stringify(data));
console.log(JSON.stringify(status));
}).done(function(data, status) {
alert( "second success" );
console.log(JSON.stringify(data));
console.log(JSON.stringify(status));
})
.fail(function(data, status) {
console.log('error');
console.log(JSON.stringify(data));
console.log(JSON.stringify(status));
})
.always(function(data, status) {
console.log(JSON.stringify(data));
console.log(JSON.stringify(status));
console.log('fiished');
});
The request reaches the microservice. But the response is as follows (which is always the error function):
"data" is always:
{"readyState":0,"status":0,"statusText":"error"}
And the "status" is always:
error
which is not the expected response at success nor failure.
How can I fix this?
Moreover, "formData" parameters appear as queries on the url once submitted. How can I stop that?
Update*
I have also tried adding event.preventDefault(); but now it gives me the following:
XMLHttpRequest cannot load http://localhost:3000/api/signup. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
{"readyState":0,"status":0,"statusText":"error"}
I have also tried:
$.ajax({
type: "POST",
url: "http://localhost:3000/api/signup",
data: JSON.stringify(formData),
success: function(dataString) {
console.log(JSON.stringify(dataString));
}, error: function(error) {
console.log(JSON.stringify(error));
}
});
But got the same No 'Access-Control-Allow-Origin' header is present on the requested resource as above.
Update
There is a valid and possibly more detailed answer on "No 'Access-Control-Allow-Origin' header is present on the requested resource". However, I find the answer I accepted here more direct and clear.
Are you executing the ajax request from the browser or localhost? If you are executing it from your browser it may be CORS issue. If you want to be able to execute that ajax request from your browser you should modify your server configuration/code to allow cross-origin HTTP requests.
This looks similar to your issue. CORS issue in Jquery Ajax Post

Resources