Why does Apollo Client ignore the response even though I have 200 status - apollo-client

I'm in the process of duplicating AWS services with LocalStack.
I've got my Lambda and API Gateway running in LocalStack in much the same way as they would in AWS. I've tested using a Rest API tool to verify. However, when I run the same query within a browser using an Apollo Client, the LocalStack version no longer works.
I've tried 3 different browsers for a given GraphQL and only Firefox shows any data when I inspect via the Network tab. Apollo always errors with a JSON decode error at position 1. The request always returns a 200 status code.
Our client setup is:
import { ApolloClient, InMemoryCache, createHttpLink } from '#apollo/client';
import 'cross-fetch/polyfill';
const httpLink = createHttpLink({
uri: 'http://example.com/graphql',
credentials: 'include', // Allow other domains too
fetchOptions: {
mode: 'no-cors',
},
});
export const client = new ApolloClient({
link: httpLink,
credentials: 'include',
cache: new InMemoryCache(),
});
Is it possible to have some CORS issue within Apollo? I'm pretty sure I have the headers set correctly in the gateway, access-control-allow-origin: http://localhost:3000, Content-Type: application/json, and so on.
Has anyone seen anything like these kinds of errors?
Update
I've found that switching from no-cors to cors allows it to work using a known good URL.
It seems to that:
when cors is set, there is a preflight check. This OPTIONS request provides a number of response headers of which the Access-Control-Allow-Origin must be set to the requesting domain.
when no-cors is set there is no preflight check and for whatever reason, the response is then rejected, even though that too contains the correct Access-Control-Allow-Origin. I tested using an URL that worked with the cors option.
In Summary
At this point in time, LocalStack is unable to provide the correct OPTIONS response, see https://github.com/localstack/localstack/issues/4204 and that prevents me from using cors.
Using no-cors fails, even when I use a known good URL.
I've abandoned LocalStack and switched to using API Gateway from AWS directly.
I hope this helps.

Related

CORS policy error with AWS API Gateway in React

I am trying to set up an API Gateway to call another lambda function that will upload an image to S3. The feature works well when I am using an app like POSTMAN, however when I run the browser using React I am getting the following error.
Access to fetch at 'https://.../upload' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
In my API Gateway I have the following configuration for that method
Gateway Responses for UserUpload API: default 4XX (not checked), default 5XX (not checked)
Methods: post (checked), options (checked)
Access-Control-Allow-Methods: options, post
Access-Control-Allow-Headers: '*'
Access-Control-Allow-Origin: '*'
This API uses an authorizer, I am using the one provided by Auth0 and have not edited the code at all.
And the function that my authorizer calls returns the response like the below (eg happy path):
exports.handler = async (event) => {
//do data checks and upload to s3
return {
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Origin": "*",
},
statusCode: 200,
body: JSON.stringify({ message: "success" }),
};
This is my first time setting up both a lambda function, authorisation provider and API Gateway so I might be missing something obvious. I have also tried added mode: no-cors to my fetch POST requests however they still fail in a very similar way.
From what I can tell by looking at the logs of the authorizer and the lambda function that uploads the images, is that they are not even being called. So it appears the CORS error is with the API Gateway.
I have seen in a few tutorials that in their aws template yaml files they add an option AddDefaultAuthorizerToCorsPreflight as False. I can't see this anywhere in the API Gateway console.
Update: I have tested my function with the custom authoriser turned off and it works. So I know that CORS works for the options method, and for the returned request on the lambda function. It is the custom authoriser that is the problem.
The flow is currently:
Method Request - Auth: my-auth-0-authorizer
Integration Request - Type: Lambda_proxy
Lambda function
Integration response - [greyed out Proxy integrations cannot be configured to transform responses]
Method Response: HTTP Status: Proxy (with Access-Control-Allow-Origin in the response headers)
What do I have to do differently or change to allow my authoriser to respect the CORS config?
Update: After leaving my API Gateway for a day, successful responses are now working (using the flow mentioned above). I am not sure if there was a glitch in the system or there was unexpected occurring but it is now working. I am still getting a CORS issue but now only with bad responses.
The custom authoriser fails by return context.fail("Unauthorized"); and when this occurs my browser gets a CORS error. Do I have to set up special gateway responses for 4XX responses?

Cross-Origin Read Blocking (CORB) when get data from Directions API using axios with Nuxt js

In my Nuxt project, I use vue2-google-maps library to create map and axios to get data from Map API.
I want to get distance between 2 location in google map, so i use Directions API: https://maps.googleapis.com/maps/api/directions/json?origin=Disneyland&destination=Universal+Studios+Hollywood&key=API_KEY.
When I use it with Insomnia, I retrieved data normally, like below picture:
But when i use it with nuxt using axios, I get some error like:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://maps.googleapis.com/maps/api/directions/json?origin=Disneyland&destination=Universal+Studios+Hollywood&key=API_KEY with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
But if i use Geocoding API with nuxt, it work normally
I tried adding header Access-Control-Allow-Origin=* but still get errors.
I don’t know why i get these errors.
My code:
axios
.get('https://maps.googleapis.com/maps/api/directions/json?origin=Disneyland&destination=Universal+Studios+Hollywood&key=API_KEY')
.then(res => {
console.log("Res: ");
console.log(res)
})
.catch(err => console.log(err));
Please help me.
Thank you!!!
In nuxt.config.js, you have to put credentials: false to allow CORS wildcard.
Modify config as follows.
axios: {
baseURL: 'https://maps.googleapis.com/maps/api',
proxyHeaders: false,
credentials: false
}
CORS header is not present in the response from Google Maps because it is designed to be utilized for server-side applications. For client-side (Browser), you need to make use of Official Maps library. (Shown in the above image).
Reference: https://github.com/nuxt-community/axios-module#credentials

API Gateway CORS issue, with correct payload

I've been trying to fix this all day.
I got a Lambda function I'm trying to run when I make a POST request to the endpoint (configured with AWS API GATEWAY).
Everything runs fine, my options gets a 200 okay, my post gets a 200 okay and comes back with the data I want.
However when I get it back, it "thinks" it failed. I use JQuery for this project, and it comes back as the "fail" cb.
Looking at the console log the problem is quite clearly the following error:
XMLHttpRequest cannot load
https://xxxxxxxxx.execute-api.us-west-2.amazonaws.com/prod/createCustomer.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access.
a standard CORS issue. But nothing I do seems to work. I enabled CORS on the API gateway (before that the OPTIONS would fail). the 'Access-Control-Allow-Origin': is set to: '*' which should allow access from any origin. I of course deployed the new API.
I also tried not using CORS and instead enabling the AWS proxy thing, and having my response like this { statusCode, headers, body } but when doing that I get no response whatsoever.
I have absolutely no clue where to start attempting to fix this. I even tried a dirty jsonp method. But still same problem. :(
The only bit of data I can find on my request that doesn't seem okay, is this: x-cache:Miss from cloudfront
Here's the full response headers from the POST request:
content-length:2312
content-type:application/json
date:Thu, 23 Mar 2017 22:15:08 GMT
status:200
via:1.1 95a477af435073615179b256d8101334.cloudfront.net (CloudFront)
x-amz-cf-id:Hc6POYFO0HKB1xriSg2iH7O1po7ah926a4dQkgfSNBUZ460RoHRNuw==
x-amzn-requestid:2b5ed745-1016-11e7-b497-cb0a77cd1479
x-amzn-trace-id:Root=1-58d448ea-56717776eaa3f5389083e9ca
x-cache:Miss from cloudfront
Sadly as is quite obvious, the Access control headers aren't there... I assume that's the problem I'm desperately trying to fix. But I have no idea why since I set it to ' * ' during the Enable CORS step of this process.
I was able to get semi-close to a solution by manually creating a POST method (as opposed to "ANY"), then enabling CORS again, then turning on the PROXY on integration response, and set my response to: { statusCode, headers, body } This will come back as a successfull event and run the right callback function in my ajax call. However, using this method I get no data back from Lambda... despite having it in "body", all I receive is an empty object.
I don't really have a preference of using CORS or manually adding headers, that's fine I won't be updating this much. I just really really need to get it functioning :( Any help would be greatly appreciated.
If you got x-cache:Miss from cloudfront from your API, it is fine because API Gateway doesn't enable the edge cache on the cloudfront side. If you want CORS to work with Lambda proxy integration, you can return the status code and the headers, like,
{
"statusCode": 200,
"headers": { "Access-Control-Allow-Origin": "<domains you need>" }
}
Then, it will be like an empty response from the client side.
I have now idea why, but I was able to get it working. Using the following steps:
Enable CORS,
Deploy API, (can probably be skipped...)
Manually add POST method,
Enable Proxy on Integration response,
Deploy API again
change callback response to format: { statusCode: 200, headers: {}, body: {} }
use JSON.parse() to parse your payload.
This is definitely not a perfect answer. For some reason turning on the Proxy modified how my Lambda function received data, so I had to Stringify it to not cause an error. I can't offer an explanation why this happened.
The headers I used were:
"Access-Control-Allow-Methods": "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT",
"Access-Control-Allow-Origin": "*"
A better solution to this would also be a way to do this just using CORS. As you don't have to manually insert headers in all your responses. But I couldn't get that working. So please, if someone knows a better solution to this post it!

POST request to AWS API Gateway access

I have a AWS Lambda function that is triggered via AWS API Gateway. When I test my function on Lambda it is working. When I send a POST request to the API url via ajax, I get a 502 bad gateway error.
XMLHttpRequest cannot load https://xxxxxxxx.execute-api.us-east-1.amazonaws.com/prod/myLambdaFunction. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'mywebsite.com' is therefore not allowed access. The response had HTTP status code 502.
Obviously this was a CORS issue, so I thought I could change the CORS settings in my AWS API Gateway URL which I did, but I am still getting an error for this.
What do I have to change on AWS side or my own to be able to POST to the URL?
Unfortunately there is a known issue with many classes of 4xx and 5xx errors where CORS headers will not be sent, even if you've added CORS support via the console.
As noted in comments, the CORS error is a side effect of the fact that your API is returning a 502. This often occurs if you are using the LAMBDA_PROXY integration type and are returning invalid JSON from your Lambda function.
Please try either using the test invoke functionality from the console or enable logging in your API to debug further.
I solved that exact same problem by outputting the CORS header myself.
See below - and I hope that'll help.
Teebo
Amazon docs
function respond(context, responseData) {
var response = {
statusCode: 200,
body: JSON.stringify(responseData),
headers: {
"Content-Type": "application/json; charset=utf-8",
"Access-Control-Allow-Origin": "*"
}
};
context.succeed(response); }

identity Server - Configuring CORS for bearer options

I am testing the jquery ajax calls to the API server from a different domain. Unfortunately I am getting an OPTIONS error. Here is my request code:
$.ajax({
url: "https://localhost:44356/api/Default/",
headers: {
"Authorization": "Bearer " + user.access_token
},
success: function (res) {
logAjaxResult(res);
},
error: function() {
logAjaxResult('Error');
}
}))
Which gives
XMLHttpRequest cannot load https://localhost:44356/api/Default/. Response for preflight has invalid HTTP status code 405.
Normally this is an easy fix - I install Microsoft.AspNet.WebApi.Cors, set up a provider and allow OPTIONS through always. I can see how I would normally do this on the Identity Server box too as there is a CorsProvider you can register up. My issue however is on the API box I am using IdentityServerBearerTokenAuthenticationOptions and I see no CORs options. When I try to set up the WebAPI.cors provider though I get an error saying there are multiple origins set on the server to allow. This indicates to me (correct me if I'm wrong) that the WebApi box has somehow got the CORs settings from my identity server box that is registered as it's authority. Is this right?
How do I configure to allow pre-flight requests with app.UseIdentityServerBearerTokenAuthentication(options)?
Many thanks
This issue was resolved when I found the documentation uses
Microsoft.Owin.Cors
I was using the package
Microsoft.AspNet.WebApi.Cors

Resources