I'm trying to make api calls locally in a react app using axios.
I've already added django-cors-headers and followed the documentation, but it does not seem to be working.
I always get the error:
localhost/:1 Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/todos/' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
my base.py:
INSTALLED_APPS = [
# ...
"corsheaders",
"rest_framework",
"todo",
"api",
]
MIDDLEWARE = [
# ...
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
# ...
]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = False
In my react app:
const [todos, setTodos] = useState({})
useEffect(
() => {
axios.get(
api_url, {
headers: {
"Access-Control-Allow-Origin": "*",
}
}
).then(
res => {
setTodos(res.data);
console.log(res.data)
}
).catch(
err => {
console.log(err)
}
)
}, []
)
Note, even without configuring a whitelist and reverting the CORS settings to:
CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
I still manage to get the data in a get call using httpie, just running http + url.
Note 2: When the axios tries to get the data, I get this on the terminal running the Django app:
[04/Jun/2019 18:15:29] "OPTIONS /api/todos/ HTTP/1.1" 200 0
IMPORTANT EDIT:
The problem does not seem to be with my server, I used fetch instead of Axios and everything occurred normally. With Axios, my server was getting an OPTIONS method, and, I do not know why, I was giving this problem with CORS.
Related
I get the following message in the Chrome dev tools console when submitting a contact form (making a POST request) on the /about.html section my portfolio web site:
Access to XMLHttpRequest at 'https://123abc.execute-api.us-east-1.amazonaws.com/prod/contact' from origin 'https://example.net' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://example.net/' that is not equal to the supplied origin.
I don't know how to troubleshoot this properly, any help is appreciated.Essentially, this is happening (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSAllowOriginNotMatchingOrigin) and I don't know where within my AWS assets to fix it. This person had same problem, but i'm unsure of how to apply their fix (CORS header 'Access-Control-Allow-Origin' does not match... but it does‼)
Here is a description of the AWS stack:
Context, I am using an S3 bucket as static website using CloudFront and Route 53, this stuff works fine, has for years. When I added the form, I did the following to allow the HTTP POST request:
Cloudfront, On the site's distribution I added a behavior with all settings default except:
Path pattern: /contact (I am using this bc this is the API Gateway resource path ending)
Origin and origin groups: S3-Website-example.net.s3-website... (Selected correct origin)
Viewer protocol policy: HTTP and HTTPS
Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
Cache HTTP methods GET and HEAD methods are cached by default: Checked OPTIONS box
Origin request policy - optional: CORS-S3Origin
Response headers policy - optional: CORS-With-Preflight
API Gateway, Created a REST API with all default settings except:
Created a resource: /contact
Created a method: POST
For /contact, Resource Actions > Enable CORS:
Methods: OPTIONS and POST both checked
Access-Control-Allow-Origin: 'https://example.net' (no ending slash)
Clicked "Enable CORS and Replace existing headers"
Results are all checked green:
✔ Add Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin Method Response Headers to OPTIONS method
✔ Add Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin Integration Response Header Mappings to OPTIONS method
✔ Add Access-Control-Allow-Origin Method Response Header to POST method
✔ Add Access-Control-Allow-Origin Integration Response Header Mapping to POST method
Created a stage called "prod", ensured it had the /contact resource, and deployed.
At the /contact - POST - Method Execution, The test works as expected (triggers Lambda func that uses SES to send email, which I do actually receive).
The only thing I feel unsure about with API Gateway is after I enable the CORS, I can't seem to find a place where that setting has been saved, and if I click again on enable CORS, it is back to the default form ( with Access-Control-Allow-Origin: '')*
Amazon SES, set up 2 verified identities for sending/receiving emails via lamda.
Lamda, set up a basic javascript function with default settings, the REST API is listed as a trigger, and does actually work as previously mentioned. The function code is:
var AWS = require('aws-sdk');
var ses = new AWS.SES({ region: "us-east-1" });
var RECEIVER = 'myemail#email.com';
var SENDER = 'me#example.net';
var response = {
"statusCode": 200,
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
},
"isBase64Encoded": false,
"body": "{ \"result\": \"Success\"\n}"
}
exports.handler = async function (event, context) {
console.log('Received event:', event);
var params = {
Destination: {
ToAddresses: [
RECEIVER
]
},
Message: {
Body: {
Text: {
Data: 'first name: ' + event.fname + 'last name: ' + event.lname + '\nemail: ' + event.email + '\nmessage: ' + event.message,
Charset: 'UTF-8'
}
},
Subject: {
Data: 'Website Query Form: ' + event.name,
Charset: 'UTF-8'
}
},
Source: SENDER
};
return ses.sendEmail(params).promise();
};
The only thing i can think of here is to maybe update the response to have "headers": {"Access-Control-Allow-Origin": "https://example.net"}
S3 bucket that holds the site contents, in permissions > CORS, I have the following JSON to allow a post of the contact form (notice no slash):
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"POST"
],
"AllowedOrigins": [
"https://example.net"
],
"ExposeHeaders": []
}
]
Permissions/Roles, Established Roles and permissions per
AWS guide: create dynamic contact forms for s3 static websites using aws lambda amazon api gateway and amazon ses
video titled: "Webinar: Dynamic Contact Forms for S3 Static Websites Using AWS Lambda, API Gateway & Amazon SES"
Client code, this is a very milk toast function being called to post the form on click.
function submitToAPI(event) {
event.preventDefault();
URL = "https://123abc.execute-api.us-east-1.amazonaws.com/prod/contact";
const namere = /[A-Za-z]{1}[A-Za-z]/;
const emailre = /^([\w-\.]+#([\w-]+\.)+[\w-]{2,6})?$/;
let fname = document.getElementById('first-name-input').value;
let lname = document.getElementById('last-name-input').value;
let email = document.getElementById('email-input').value;
let message = document.getElementById('message-input').value;
console.log(`first name: ${fname}, last name: ${lname}, email: ${email}\nmessage: ${message}`);
if (!namere.test(fname) || !namere.test(lname)) {
alert ("Name can not be less than 2 characters");
return;
}
if (email == "" || !emailre.test(email)) {
alert ("Please enter valid email address");
return;
}
if (message == "") {
alert ("Please enter a message");
return;
}
let data = {
fname : fname,
lname: lname,
email : email,
message : message
};
$.ajax(
{
type: "POST",
url : URL,
dataType: "json",
crossDomain: "true",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
success: function () {
alert("Successful");
document.getElementById("contact-form").reset();
location.reload();
},
error: function () {
alert("Unsuccessful");
}
});
}
The problem was that the response in the lambda function had "Access-Control-Allow-Origin" set to "*".
This should have been set to the exact origin (no trailing slash), so if the origin is 'https://example.net', then the response in the lamda function should have "Access-Control-Allow-Origin" set to 'https://example.net' as shown below:
var response = {
"statusCode": 200,
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "https://example.net"
},
"isBase64Encoded": false,
"body": "{ \"result\": \"Success\"\n}"
}```
I have a working RTK Query api, reading from a backend that after a successful login was sending the token in the payload.
The backend API changed and now the token comes in the response's Authorization header and I can't figure out how to read it.
This is what I had before, on my reducer. I used a matcher for when the request was fulfilled and stored the token in the payload:
// reducer.js
const authReducer = createSlice({
// ...
extraReducers: (builder) => {
builder.addMatcher(backendApi.endpoints.login.matchFulfilled, (state, { payload }) => {
// save the payload.token in localstorage
}
}
});
It seems like getting the headers is not straightforward, and I actually can't find the Authorization header when trying to get the headers from the request:
// reducer.js
const authReducer = createSlice({
// ...
extraReducers: (builder) => {
builder.addMatcher(backendApi.endpoints.login.matchFulfilled, (state, { meta }) => {
const headers = meta.baseQueryMeta.response.headers; // this is a Headers {} object
console.log(headers.get('content-type')); // prints application/json; charset=utf-8
console.log(headers.get('authorization')); // prints undefined
}
}
});
When I try to debug and print all headers with console.log(Array.from(headers)) this is what I get:
[
[
"cache-control",
"max-age=0, private, must-revalidate"
],
[
"content-type",
"application/json; charset=utf-8"
]
]
It's super strange because the response has many more headers, but I can't access them.
Any guidance here? Maybe it's not possible to read the headers this way?
Thanks in advance!
You are doing everything right there. If headers.get('authorization') comes back as undefined I would assume it is a CORS issue preventing your JavaScript from accessing that.
So your server would need to set the correct CORS headers, nothing to do on the client side.
In order to test the client side connectivity with our Openfire XMPP server, the following test script (nodejs) was initially tested, which ran successfully.
async function connectX() {
try {
const keyPair = await XmppUser.generateKeys()
XmppUser.connect(username, password, keyPairs).then(
async user => {
user.getFriends().then(friends => {
console.log("List of Friends: ");
console.log(friends);
user.getChatHistory().then(history => {
console.log("Chat History: ")
console.log(history);
user.closeConnection();
}).catch(e => console.log(e));
}).catch(e => console.log(e));
}
).catch(e => console.log(e));
} catch(e) {
console.log(e)
}
}
connectX()
Output:
List of Friends:
[ 'test1.test#chat.company.io', 'test2.test#chat.company.io' ]
Chat History:
{ messages:
[ { date: 2020-08-11T12:18:34.314Z,
from: 'test1.test#chat.company.io',
to: 'test6.test#chat.company.io',
message: 'Hello! Received.',
id: 'D255Q-132' }
] }
lastId: '1',
firstId: '1',
count: '1' }
However, when I run the script in an ionic angular app using the same ChatService class it leads me to the following CORS error.
Access to fetch at 'https://chat.company.io/.well-known/host-meta' from origin 'http://localhost:8100' 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.
For information, https://chat.company.io/.well-known/host-meta exists and has the following content:
<?xml version='1.0' encoding='utf-8'?>
<XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'>
<Link rel="urn:xmpp:alt-connections:httppoll"
href="https://chat.company.io:443" />
</XRD>
The backend infrastructure includes an Nginx server and the chat server runs behind it with the following open ports: 443, 7070, 5222, 5223.
Please help in figuring out what the issue might be.
Possible CORS issue,
enable support for CORS in Openfire, server -> server settings -> http binding -> CORS section.
I am using angularjs in my front-end and this is the piece of code where i call my loclhost , todo variable should have the value , but i get error
Failed to load http://localhost:8080/Cart/1: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
When i use it directly i got the json value.
var cartResource = $resource('http://localhost:8080/Cart/:cartId',
{cartId: '#id'});
$scope.cart1 = cartResource.get({cartId: 1},function(todo) {
// success
console.log("k","k")
}, function(errResponse) {
console.log("nooooo",errResponse)
});
You might probably enable the CORS filter on your backend! If your backend server is Play Framework, here is some documentation on how this is done:
https://www.playframework.com/documentation/2.6.x/CorsFilter
For me the problem was that i have to set the origin in my headers beside cors sittings as in back-end code
$resource('http://localhost:8080/cart/:cartId',
{cartId :'#cartId' },
{ update: { method: 'PUT' }},
{ headers : { 'Origin': 'http://localhost:8080' }} );
I have two applications running indepepently, one taking care of my backend (written in Scala Play) then other one being my frontend (Angular with a static Node server).
I try to request data on my frontend through a form from my Scala Play app.
this.insertionOrder = function(){
$http({
method: 'POST',
url: '//localhost:9000/insertsupplier',
header: {
'Content-type': 'application/json',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS'
},
data:{
'supplier_id': 1,
'suppliername': 'xxx',
'supplier_address': 'xxx xxx xxx xxx',
'contact': 'xxx#xxx.com',
'datecreated': '2017-10-15T09:45:00.000UTC+00:00'
}
}).then(function(response){
console.log(response);
return response.data
}, function(err){
console.log(err)
});
};
and my play app looks like this:
Controller:
def insertsupplier = Action(parse.json) { implicit request =>
val json = request.body
val sup: Supplier = json.as[Supplier]
sup.insertSql(con)
Ok("test")
}
my build.sbt contains filters:
libraryDependencies ++= Seq(
cache ,
ws,
jdbc,
filters
)
and the MyFilters.scala
class MyFilters (implicit inj:Injector) extends HttpFilters with Injectable {
implicit val as = inject[ActorSystem]
implicit val mat = ActorMaterializer()
val gzip = new GzipFilter()
val csrf = inject[CSRFFilter]
val cors = inject[CORSFilter]
//println(s"csrf: ${csrf.tokenProvider}")
//println(s"csrf: ${csrf.tokenProvider.generateToken}")
def filters = Seq(gzip,cors,csrf)
}
and finally my application.conf
play.filters.cors {
pathPrefixes = ["*"]
allowedOrigins = ["http://localhost:3000","https://localhost:3000","http://localhost:3000/*","https://localhost:3000/*"]
allowedHttpMethods = ["GET", "POST", "OPTIONS"]
allowedHttpHeaders = ["Accept"]
# preflightMaxAge = 1 hour
}
play.filters.csrf {
cookie.name = "XSRF-TOKEN"
header.name = "X-XSRF-TOKEN"
}
play.http.filters = "filters.MyFilters"
I keep getting the error "XMLHttpRequest cannot load http://localhost:9000/insertsupplier. 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 500."
I feel that first my CORS setup is wrong anyway --> What needs to be changed? I am new to this.
And am I even able to use cors in order to access data from localhost?
It may be that there’s nothing wrong at all with your CORS setup, because the “The response had HTTP status code 500” part of the error message indicates that the actual immediate problem is that an OPTIONS request to your server caused some unexpected failure on the server side.
From just the code snippets in the question, it’s not possible to tell what might be causing that 500 failure in the server side. It may be completely unrelated to your CORS config.
But regardless, you should drop the parts of your frontend code that are adding the header 'Access-Control-Allow-Origin' : '*', and 'Access-Control-Allow-Methods'. Those headers are response headers that must be sent from the server side, not from frontend code.
But the 'Content-type': 'application/json' part of your frontend code is valid, and assuming it’s actually necessary in order to get the expected response from the server, there’s no way you can make your request without triggering browsers to do a CORS preflight OPTIONS request.
But if the CORS preflight OPTIONS request fails, the browser never gets around to trying the POST request your code is actually attempting to send. And if your backend responds to that OPTIONS request with a 500 response, then the preflight fails. It must instead respond with a 200 or 204.