AngularJS : Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource - apache

here is my code :
angular.module('option')
.factory('optionListService', ['$resource', function($resource) {
return $resource(HOST+'option/action/:id', {}, {
'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
});
}]);
and this work for GET requests and not for POST !
I'm using Apache as a server and configured it with :
<Limit GET HEAD POST PUT DELETE OPTIONS>
Order Allow,Deny
Allow from all
</Limit>
Header set Access-Control-Allow-Origin "*"
and in my angularjs I include in config of module app:
delete $httpProvider.defaults.headers.common['X-Requested-With'];
delete $httpProvider.defaults.headers.post['Content-type'];
but the request POST still not working !!
I hope that someone can give any idea.

Add those headers on the server side:
Access-Control-Request-Headers: X-Requested-With, accept, content-type
Access-Control-Allow-Methods: GET, POST
If still not working post the details of the preflight OPTIONS request which the browser is sending.
Why is this required?
If it is not a simple request (e.g. GET or POST of form data) the browser sends a preflight HTTP OPTIONSrequest to the server to check if CORS is allowed. This request contains some Access-Control-Request headers (can differ based on the specific request):
Access-Control-Request-Headers: accept, content-type
Access-Control-Request-Method: POST
Now it is important that the server references the same Access-Control-Allow header in the response:
Access-Control-Allow-Headers: accept, content-type
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: *
Otherwise the request is rejected by the browser.
#ilyas : finaly after 3hours of reseach I sovelved this problem
//Part added by ilyas :
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
//End of part.
I hope this help others.

Add Header into your file which you hitting from ajax call as follows
<? php header('Access-Control-Allow-Origin: *'); ?>

I found great example and explanation here http://www.codingpedia.org/ama/how-to-add-cors-support-on-the-server-side-in-java-with-jersey/
#GET
#Path("{id}")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response getPodcastById(#PathParam("id") Long id, #QueryParam("detailed") boolean detailed)
throws IOException, AppException {
Podcast podcastById = podcastService.getPodcastById(id);
return Response.ok() //200
.entity(podcastById, detailed ? new Annotation[] {PodcastDetailedView.Factory.get()} : new Annotation[0])
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.allow("OPTIONS").build();
}

Here is a problem on server side. If your application is using spring framework. You can fix it by using the filter method
#Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "X-PINGOTHER,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization");
res.addHeader("Access-Control-Expose-Headers", "xsrf-token");
if ("OPTIONS".equals(req.getMethod())) {
res.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
By the way, you can dig deeper it via post angularjs spring cross-origin request blocked

Related

Request Failed when Add custom headers Vue

I'm doing a request with Axios but this fail when add custom headers (custom headers are required by the API).
If add the custom headers the response is:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
I have seen that two requests are made:
1- firs request:
2- Second request
In the API are enabled CORS
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-
Type, Accept, Access-Control-Request-Method,t-id-establecimiento,bt-
username,bt-nombre-empleado,ipaddress");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Allow: GET, POST, OPTIONS, PUT, DELETE");
My request in Vue:
let headers = this.getHeader()
this.$http(`${mUrl}`,{headers})
.then(function (resp) {
console.log(resp.data)
})
.catch(function (err) {
console.log('rerrrr' + err)
})
My custom header:
{
'Authorization': "Bearer " + urlParams.get('token'),
'Content-Type': 'application/json',
'bt-id-establecimiento': urlParams.get('bt-id-establecimiento'),
'bt-username': urlParams.get('bt-username'),
'bt-nombre-empleado': urlParams.get('bt-nombre-empleado'),
'ipaddress': urlParams.get('ipaddress'),
}
When dealing with a CORS error, most of the time you do not need to modify your request headers. 99% of the time, the problem is in the backend. Make sure to allow CORS in:
Server Configuration and
Application
If you are using XAMPP or any Apache server, by default CORS is not enabled. Although you already allow CORS on your application, it will still be blocked by the server.
Take note: make sure to restart your server when making changes to the configuration file

XMLHttpRequest blocked by CORS Policy on axios.post

The axios.post (code below) must send data to url api/add-todo, but I get these errors:
axios.post('http://localhost/vueoctober/todo/api/add-todo', todo).then(function (response) {
console.log(response);
}).catch(function(error) {
console.log(error);
});
The route api/add-todo is handled with October method Route::get() (https://octobercms.com/docs/services/router). Why is it not found?
If I change axios.post to axios.get it will be working! But I need post data, not get.
What I tried:
1) I tried to add these headers to .htaccess:
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTION"
It's working only for axios.get. The axios.post is still blocking.
2) I added Header set Access-Control-Allow-Origin "*" to httpd.conf.
Vue app is serving at port 8080, therefore axios.post url can't be relative.
I also stumbled and struggled with this on FF, even though I have this in the .htaccess:
Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS".
After more searching I found a Gist by #marcomessa that fixed my issues.
https://gist.github.com/marcomessa/54d077a0208439f5340126ff629a3718
Look at the error message carefully, it says the response to the preflight request didn't have an HTTP ok status.
Clearly, your server-side code doesn't have a route handler for the OPTIONS request, so you need to add one.
As an aside, after the browser gets a successful OPTIONS response, it will make the POST request but you said:
The route api/add-todo is handled with October method Route::get()
You'll need to use Route::post() to handle that.
Hours of googling and I got answer...
1) Install plugin Cross-Origin Resource Sharing (CORS).
2) In htaccess of Vue app add:
Header set Access-Control-Allow-Origin '*'
Header set Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTION"
NOTICE! Write SET not ADD!
That's it.
So for clarification on this. There are always numerous ways to answer a problem. Here is what I did for mine. Check this for Preflight Request. The preflight request is created by the browser and is not for security. This function I created first will throw an okay message upon a request, then if the data contains any data it will then do what it is called (this is where you check for security). I don't have to mess with .htaccess files. Though I did install the CORS plugin because it is a nice plugin. Also the video from watch-learn does the author is making a cross-origin request in which he goes over how to correct the problem. I think he just filmed the video before preflight requests started to be a browser norm. Found routing information here.
Route::match(['POST', 'OPTIONS'],'api/update-todo', function(Request $req) {
$data = $req->input();
if (!empty($data)) {
Todo::where('id', $data['id'])
->update([
'name' => $data['name'],
'description' => $data['description'],
'status' => $data['status']
]);
return response()->json([
'Success' => $data,
]);
} else {
return response()->json([
'Success' => $req,
]);
}
});
I can not resolve it via axios, I wasted a lot of hours, but I resolved it very easy by this way.
Let's think we are posting:
{name:"Cynthia Merk", age:"22"}
I did the next function to send the last JSON (any JSON structure works):
const PostFunction = (data, letFunction, errorHandle) => {
let uri = "http://.../create.php";
let xhr = new XMLHttpRequest();
xhr.overrideMimeType("application/json");
xhr.open("POST", uri, true);
xhr.addEventListener("readystatechange", function() {
if(xhr.readyState === 4 && xhr.status === 200) {
letFunction(this.responseText);
}else{
errorHandle(this.responseText);
}
});
xhr.send(JSON.stringify(data));
}
You can invoke this function, it needs changes the "uri" variable value and it's required to use JSON.stringify to send the data.
In PHP the API is very easy too, for dummies:
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE");
header("Allow: POST, GET, OPTIONS, PUT, DELETE");
class DB extends PDO {
private $host = 'localhost';
private $dbname = 'zamuSysScheme';
private $user = 'root';
private $password = 'admin';
private $charset = 'utf8';
public function __construct(){
try{
$dns = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
parent::__construct($dns, $this->user, $this->password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
} catch(PDOException $e){
echo 'Error: ' . $e->getMessage();
exit;
}
}
}
$method = $_SERVER['REQUEST_METHOD'];
$pdo = new DB();
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$json = file_get_contents('php://input');
$decoded = json_decode($json, true);
try{
$Name = $decoded["name"];
$Age = $decoded["age"];
if(!isset($Name)){
header("HTTP/1.1 402 FAIL");
echo "The paramenter Name is not present";
exit;
}
if(!isset($Age)){
header("HTTP/1.1 403 FAIL");
echo "The paramenter Age is not present";
exit;
}
$sqlStatement = "INSERT INTO Client (Name, Age) VALUES";
$sqlStatement .= "(:Name, :Age)";
$stmt = $pdo->prepare($sqlStatement);
$stmt->bindValue(':Name', $Name, PDO::PARAM_INT);
$stmt->bindValue(':Age', $Age, PDO::PARAM_INT);
$stmt->execute();
$Client_Id = $pdo->lastInsertId();
if($Client_Id){
header("HTTP/1.1 200 OK");
echo $Pago_Id;
exit;
}
}catch(Exception $except){
header("HTTP/1.1 400 FAIL");
echo "Error: " . $json . " /// " . $except;
exit;
}
}
header("HTTP/1.1 401 BAD REQUEST");
?>
I hope it can help you, any question is allowed and if I have the answer I'll glad to help.

How to remove these swagger warnings, about HEAD and OPTIONS?

I used swagger on express js and when I do a query I am getting this warnings.
WARNING! Unable to find a Swagger operation that matches HEAD ... - this will show if I will try to use curl.
WARNING! Unable to find a Swagger operation that matches OPTIONS ... - while this one is when accessed from a webpage.
I already add helmet and this to the code.
app.use((_, res: Response, next: NextFunction) => {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
res.header(
'Access-Control-Allow-Headers',
'Content-Type, api_key, Authorization',
);
next();
});
What I miss?
Finally got it working, I mean the warning is not showing anymore. The solution is just a one liner, sending HTTP status of 200 telling the browser that the request is supported.
export function optionCORS(req: Request, res: Response, next: NextFunction): void {
// I am just setting the headers if the request is an OPTION or HEAD
// For now I didn't interfere with the other request like POST, etc.
// I have a guess that swagger is is doing it.
if (req.method === 'OPTIONS' || req.method === 'HEAD') {
const origin: string = req.headers.origin as string;
// On my angular I have interceptor that will set the ```withCredentials```
// option to true, so I cant use * on Allow-Origin so I grab the
// request.headers.origin an used it.
// Also we need to set the Allow-Credentials to true.
res.header('Access-Control-Allow-Origin', origin);
res.header('Access-Control-Allow-Credentials', 'true');
// Then the usual headers.
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS');
res.header(
'Access-Control-Allow-Headers',
'Accept, Authorization, Content-Type, Content-Length, Origin, ' +
'X-Requested-With',
);
// And this what I miss, just the HTTP 200 status.
// So the client will know that the request is supported.
res.sendStatus(200);
return;
}
// If the request is not an OPTIONS or HEAD continue as usual,
// it look like swagger is handling it.
next();
}
Then you can use it as middleware.
app.use(optionCORS);
If you using swagger-express-middleware set WARN=off environment variable
https://github.com/APIDevTools/swagger-express-middleware/blob/ed73f82e57adb868b10e1989dac555b8d943dab8/lib/helpers/util.js#L27

CORS issue between subdomains in Laravel5

I built an API on Laravel5 and had CORS issues on localhost in development enviroment, so I developed this middleware and used on the API's routes, which solved the issue:
class Cors
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request)
->header('Access-Control-Allow-Origin', 'http://zekrishna.com')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
return $response;
}
}
When I depolyed the app the CORS problems started again. I used the same server to host the API and front-end, where the front-end is on the server's root and the API on a subdomain.
Here's my .htacess on public/:
...
<IfModule mod_headers.c>
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
</IfModule>
What am I doing wrong?
Here's the error:
XMLHttpRequest cannot load
http://api.zekrishna.com/api/agenda/?api_token=9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B.
Redirect from
'http://api.zekrishna.com/api/agenda/?api_token=9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B'
to
'http://api.zekrishna.com/api/agenda?api_token=9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin
'http://zekrishna.com' is therefore not allowed access.
EDIT
I deleted my .htaccess rules and changed my middleware: (due to duplicated Access-Control-Allow-Origin on response header)
public function handle($request, Closure $next)
{
$response = $next($request)
->header('Access-Control-Allow-Origin', 'http://zekrishna.com')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers: *')
->header('Access-Control-Allow-Credentials: true')
->header('Access-Control-Allow-Credentials: true');
return $response;
}
I'm using jQuery $.ajax method to call the API
const API_TOKEN = '9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B';
const API = 'http://api.zekrishna.com/api';
...
$.ajax({
url: API + '/agenda/',
type: 'GET',
crossDomain: true,
data: {api_token: API_TOKEN}
})
.done(setConcerts)
I can access this via an HTTP GET, and there appears to be two headers sent. Your htaccess is setting one, as is your middleware.
XMLHttpRequest cannot load http://api.zekrishna.com/api/agenda?api_token=9BuDRcUxUbl9jW2FDnMxToijR8plDsT4xkVRg7m3AThJHJWXqsNSOGy94x1B. The 'Access-Control-Allow-Origin' header contains multiple values 'http://zekrishna.com, *', but only one is allowed. Origin is therefore not allowed access
Is it possible that your local environment htaccess isn't kicking in?
I removed the last slash on my request and worked!
The server was redirecting and these request was not allowed.
Before:
$.ajax({
url: API + '/agenda/',
...
})
then:
$.ajax({
url: API + '/agenda',
...
})

Magento 2 API with Angular 2 Token authentication

This is integration issue. Your help is much appreciated (Hint || Guide)
I have both Angular2 and Magento2 (bitnami) installed locally. Magento conf was changed to have the right headers (See below) for CROS.
I'm calling Magento2 from Angular2 to get the token and I'm getting the following issue:
OPTIONS http://192.168.56.1:82/magento/index.php/rest/V1/integration/admin/token 400 (Bad Request)
XMLHttpRequest cannot load http://192.168.56.1:82/magento/index.php/rest/V1/integration/admin/token. Response for preflight has invalid HTTP status code 400
EXCEPTION: Response with status: 0 for URL: null
Angular 2 side:
let headers = new Headers({'Content-type': 'application/json'});
headers.append('Access-Control-Allow-Origin', '*');
headers.append('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,PUT,DELETE');
headers.append('Access-Control-Allow-Headers', 'Origin,Authorization,X-Auth-Token,Accept,Content-Type');
headers.append('Access-Control-Allow-Credentials', 'true');
let options = new RequestOptions({ headers: headers });
return this.http.post( 'http://192.168.56.1:82/magento/index.php/rest/V1/integration/admin/token',
JSON.stringify('{"username":"angUser", "password":"angUser2017"}'),
options)
.map(res => res.json());
Magento2 API User
angUser / angUser2017
Consumer Key: 5bhvi7gjvyafcp35rajuxh0y4me2plga
Consumer secret: yh1nefyw1u80rd0ip1q6f8pijv9x72f1
Access Token: g5plfwth2rhlwtuwfhhqp7mg6sebrxc3
Access Token Secret: i1f4t7j65oo8ydtnteub9xr7wrswe99c
Magento headers:
Response Headers
Access-Control-Allow-Credentials: True
Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization
Access-Control-Allow-Methods: GET,POST,OPTIONS,PUT,DELETE
Access-Control-Allow-Origin: *
I had a similar issue before and I tracked it down to this method where there is no check for ->isOptions(). So every API call from another domain was triggering a Request method is invalid exception.
/**
* Retrieve current HTTP method.
*
* #return string
* #throws \Magento\Framework\Exception\InputException
*/
public function getHttpMethod()
{
if (!$this->isGet() && !$this->isPost() && !$this->isPut() && !$this->isDelete()) {
throw new \Magento\Framework\Exception\InputException(new Phrase('Request method is invalid.'));
}
return $this->getMethod();
}
You can find a possible workaround in the github forum if you are using apache.
In my specific case what I ended up doing was serving both front-end and api from the same domain to avoid problems with CORS (I use nginx).
An example of the configuration needed for this can be something like:
location ~ ^/(index.php/)?rest {
try_files $uri $uri/ /index.php?$args;
}
location / {
root /var/www/angular/public/;
index index.html;
}