We have an issue with our API implementation.We are implementing APIs using Slim Framework ,PHP in Nginx Servers
Suppose we implement our api in domain api.mydomain.com and we try to send GET,POST,PUT request to domains like services.mydomain.com or apps.mydomain.com.Our requests are need to be add custom headers for 'x-api-key' and 'x-session-key' for security.But using jquery when we try to add in any methods we cant able to send requests to different domain. We tried it by adding both ways
headers: { 'X_API_KEY' : varibaleName.apiSecretKey },
beforeSend: function(xhr){xhr.setRequestHeader('X-Test-Header', 'test-value');},
jQuery.ajax({
url: secretIdUrl,
type:'GET',
crossDomain: true,
//headers: { 'X_API_KEY' : varibaleName.apiSecretKey },
beforeSend: function(xhr){xhr.setRequestHeader('X-Test-Header', 'test-value');},
dataType: "json",
success: function (data) {
if(data.results){
widgetControl.setSecretID(data.results.id);
}
}
});
Can you please guide us to resolve this issue in client side in ajax requests if you have experience in similar issues
References :
http://enable-cors.org
http://dev.opera.com/articles/view/dom-access-control-using-cross-origin-resource-sharing
http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
Try:
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'X_API_KEY'; # and all headers ', ' separated
}
More of add_header: http://wiki.nginx.org/HttpHeadersModule#add_header
Related
I need a reverse proxy for a backend Rest API to avoid CORS and debugging issues while developing a Svelte App. I've tried a few options like Node JS Express with http-proxy-middleware, Nginx, etc. The problem is that the backend JAX-RS Rest API requires j_security_check authentication. My modest network protocol skills run out trying to configure that in the proxy...
How would I make the following work:
Svelte App (http:5000) -> Proxy (http:3333) -> Rest API (http:8080 w/j_security_check)
So for example:
Svelte:
const ping = async () => {
const response = await fetch('http://localhost:3333/api/ping', {
method: 'GET',
headers: {
Accept: 'application/json',
},
});
return await response.json();
};
Nginx so far:
location /api/ {
add_header Access-Control-Allow-Origin "http://localhost:5000";
add_header Access-Control-Allow-Methods "GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH";
proxy_pass http://backend:8080/;
proxy_set_header Host $host;
}
I guess I'm missing a lot of header config from the above. If it's even possible for j_security_check.
Since this is local development proxy only, it would be optimal if the proxy could handle the authentication and leave those details hidden from the Svelte App.
I've a client on a server (https://example.com) and an API on another server (https://api.myapis.com/thisapi)
When my client calls the API server I have this in my NGINX log:
XXX.XXX.XXX.XXX - - [03/Jan/2021:19:07:03 +0100] "OPTIONS /thisapi/particular/route/ HTTP/1.1" 200 13 "https://example.com/app/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0"
So I suppose it's OK for the NGINX server, which has this conf:
location /thisapi/ {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For$remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:1234/;
add_header 'Access-Control-Allow-Origin' 'https://example.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
}
Here is how I make the API call with axios:
axios.post(`${process.env.VUE_APP_API_URL}/particular/route/`, {
text: text.value,
},
{
headers: {
'Content-Type': 'application/json',
},
})
.then((response) => {
console.log(response.data);
link.value = `${process.env.VUE_APP_URL}${process.env.VUE_APP_PUBLICPATH}${response.data}`;
})
.catch((error) => {
console.log(error);
})
.then(() => {
loading.value = false;
});
return true;
}
And I have this in my Firefox console:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.myapis.com/thisapi/particular/route/. (Reason: Multiple CORS header ‘Access-Control-Allow-Origin’ not allowed).
I really don't see where I messed up... If anybody could give me a hand, it would be great. Thanks in advance.
I usually don't handle this in Nginx, but rather in the backend itself.
Try:
add_header 'Access-Control-Allow-Origin' '*' always;
If it now works like you expect it, that means 'https://example.com' is not correct.
(Btw you shouldn't use * in your code, it's just for demonstration purpose.)
Origin is consisted of 3 parts:
Protocol
https
http
Domain Name
(like www.example.com)
Port
Usually this is either 80 or 443
Make sure that the origin you are adding to the ‘Access-Control-Allow-Origin’ list, is exactly what it should be.
Check whether it is https or http.
EDITED:
Check the request and response headers.
The bluish parts should be the same.
If they are not the same for you, that means whatever you are doing, isn't working like it should be.
OK I understood what went wrong, I was mistaken by another answer here: https://stackoverflow.com/a/65532334/1098303
This experimented user told CORS was to lift restrictions, so that's what I did in my nodeJS app. I added another "Origin", like this:
res.setHeader('Access-Control-Allow-Origin', 'myothersource');
That is what made the error.
Now that I removed the header addition in my NodeJS app, everything is find, but I still wonder how you can "lift restrictions" in a NodeJS app compared to what is set on the nginx server, it seems impossible and you might have to choose between an nginx conf or a NodeJS one.
I have a woocommerce site and I want its REST API to be open to the world.
I have learned that CORS headers need to be set, so I google and setup the following hook:
add_action('rest_api_init', function() {
remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
add_filter('rest_pre_serve_request', function( $value ) {
header( 'Access-Control-Allow-Origin: *' );
header( 'Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, PATCH, DELETE' );
header( 'Access-Control-Allow-Credentials: true' );
header('Access-Control-Allow-Headers: Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Origin,Content-Type,X-Auth-Token,Content-Range,Range');
return $value;
});
}, 15);
I confirmed that my server is responding with the correct CORS headers:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers:
Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Origin,Content-Type,X-Auth-Token,Content-Range,Range
Access-Control-Allow-Methods: OPTIONS, GET, POST, PUT, PATCH, DELETE
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages
Then I headed to code the client side:
xhr = new XMLHttpRequest();
xhr.open('POST', 'https://..../wp-json/wc/v3/products');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Basic ' + btoa('mykey:mysecret'));
xhr.send(JSON.stirngify({ ... });
Above code was entered in Chrome console under a https://google.com tab. I just can't get the preflight request to work, here are the errors:
OPTIONS https://..../wp-json/wc/v3/products 401 (Unauthorized)
Access to XMLHttpRequest at 'https://..../wp-json/wc/v3/products' from origin
'https://www.google.com' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: It does not have
HTTP ok status.
Even though the response headers are exactly like posted above.
What am I doing wrong?
if you are using: "Access-Control-Allow-Credentials" = true make sure that "Access-Control-Allow-Origin" is not "*", it must be set with a proper domain!
I'm calling this function from my asp.net form and getting following error on firebug console while calling ajax.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://anotherdomain/test.json. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
var url= 'http://anotherdomain/test.json';
$.ajax({
url: url,
crossOrigin: true,
type: 'GET',
xhrFields: { withCredentials: true },
accept: 'application/json'
}).done(function (data) {
alert(data);
}).fail(function (xhr, textStatus, error) {
var title, message;
switch (xhr.status) {
case 403:
title = xhr.responseJSON.errorSummary;
message = 'Please login to your server before running the test.';
break;
default:
title = 'Invalid URL or Cross-Origin Request Blocked';
message = 'You must explictly add this site (' + window.location.origin + ') to the list of allowed websites in your server.';
break;
}
});
I've done alternate way but still unable to find the solution.
Note: I've no server rights to make server side(API/URL) changes.
This happens generally when you try access another domain's resources.
This is a security feature for avoiding everyone freely accessing any resources of that domain (which can be accessed for example to have an exact same copy of your website on a pirate domain).
The header of the response, even if it's 200OK do not allow other origins (domains, port) to access the resources.
You can fix this problem if you are the owner of both domains:
Solution 1: via .htaccess
To change that, you can write this in the .htaccess of the requested domain file:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
If you only want to give access to one domain, the .htaccess should look like this:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin 'https://my-domain.example'
</IfModule>
Solution 2: set headers the correct way
If you set this into the response header of the requested file, you will allow everyone to access the resources:
Access-Control-Allow-Origin : *
OR
Access-Control-Allow-Origin : http://www.my-domain.example
Server side put this on top of .php:
header('Access-Control-Allow-Origin: *');
You can set specific domain restriction access:
header('Access-Control-Allow-Origin: https://www.example.com')
in your ajax request, adding:
dataType: "jsonp",
after line :
type: 'GET',
should solve this problem ..
hope this help you
If you are using Express js in backend you can install the package cors, and then use it in your server like this :
const cors = require("cors");
app.use(cors());
This fixed my issue
This worked for me:
Create php file that will download content of another domain page without using js:
<?
//file name: your_php_page.php
echo file_get_contents('http://anotherdomain/test.json');
?>
Then run it in ajax (jquery). Example:
$.ajax({
url: your_php_page.php,
//optional data might be usefull
//type: 'GET',
//dataType: "jsonp",
//dataType: 'xml',
context: document.body
}).done(function(data) {
alert("data");
});
You have to modify your server side code, as given below
public class CorsResponseFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
responseContext.getHeaders().add("Access-Control-Allow-Origin","*");
responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
}
}
You must have got the idea why you are getting this problem after going through above answers.
self.send_header('Access-Control-Allow-Origin', '*')
You just have to add the above line in your server side.
In a pinch, you can use this Chrome Extension to disable CORS on your local browser.
Allow CORS: Access-Control-Allow-Origin Chrome Extension
I'm trying to make a DELETE request with AngularJS.
I'm sending this headers from the Server:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: origin, x-requested-with, content-type, accept');
header('Access-Control-Allow-Method: GET, POST, OPTIONS, DELETE');
But in Chrome, when I do an
$http({method: 'DELETE', url: EmployeesURL + "remove/id/" + id})
it throws a Method DELETE is not allowed by Access-Control-Allow-Methods. error.
Looks like you are missing an 's' Access-Control-Allow-Methods