I have created an app for the Registration Form using [Ionic + PHP] and I face the following issue.
CORS Add-on: Activated - It works Fine when I use it in the http://localhost:8100/ionic-lab
CORS Add-on: Deactivated - It does not works Fine when I use it in the http://localhost:8100/ionic-lab and the below mentioned error occurs.
Below I will explain the codes in my Files.
remote-service.ts
constructor(public http: Http) {
this.headers = new Headers()
this.headers.append('Content-Type', 'application/json')
this.headers.append('Content-Type', 'application/x-www-form-urlencoded')
this.headers.append('Access-Control-Allow-Origin', 'http://localhost:8100')
this.headers.append('Access-Control-Allow-Credentials', 'true')
this.headers.append('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, HEAD')
this.headers.append('Access-Control-Allow-Origin', '*')
this.headers.append('Accept', 'application/json')
this.headers.append('Accept', 'application/x-www-form-urlencoded')
console.log('Hello RemoteServiceProvider Provider');
}
getAllUsers() {
let options = new RequestOptions({ headers: this.headers })
return this.http.get('http://haitutorial.com/HybridApp/listAllUsers.php', options)
.map(res => res.json());
}
getAllUsers() - This function will fetch all the users Registered from the specific URL.
database.php
<?php
include('database.php');
header('Access-Control-Allow-Origin' , '*');
header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
header('Accept','application/json');
header('content-type','application/json');
$query = "SELECT * FROM `users` WHERE `status`='1' AND `delete_status`='0' ORDER BY `user_id` DESC";
$result = mysqli_query($con,$query);
$count = mysqli_num_rows($result);
$resultant_array = array();
if($count>0)
{
while($informations = mysqli_fetch_assoc($result))
{
$resultant_array[] = $informations;
}
print_r(json_encode($resultant_array));
}
else
{
$resultant_array[] = ["success"=> 200, "message"=> "No Data Found", "status_code"=>1 ];
echo $output = json_encode($resultant_array);
}
?>
The Above URL mentioned in the getAllUsers() works in the Browser but when placed inside the Ionic App it shows the below Error.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://haitutorial.com/HybridApp/listAllUsers.php. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
The above Issue is solved when I enable the CORS add-on in the Browser. But when I Disable the CORS add-on in the Browser it shows the Error.
Like wise the Same Error prevails in the Insert Page Also. When I Insert the Data from the APP it redirects to the List Page and the Data are not displayed telling the above said Error.
I have added header() in the PHP File also. But I am unable to trace out the Error. I am in need to Fix this Error without the use of Add-on like stuffs in the browser and needs to run successfully in APP too.
You need to set header at server end not ionic side.
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");
Related
I'm building an API to activate and validate active installations of my PHP Scripts,
but I get the "Access to XMLHttpRequest at 'http://api.domain.te/requests/verify' from origin 'http://domain.te' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource" error on console.
Here is my jQuery code:
function verify() {
$.post(url+"requests/verify", {
domain: domain
}, function(data) {
if (data.success === true) {
return true;
}
});
return false;
}
I have read through similar questions and tried all the suggestions, but none seems to be working.
On my PHP code I have:
public function verify()
{
$data['success'] = false;
$data['status'] = 'error';
$data['message'] = 'An error occurred';
if ($this->actives_m->check($this->request->getPost("domain")??""))
{
$data['success'] = true;
$data['status'] = 'success';
$data['message'] = 'Product is Active!';
}
else
{
$data['message'] = 'Product is Inactive!';
}
$this->response->setHeader('Access-Control-Allow-Origin', '*');
$this->response->setHeader('Access-Control-Allow-Methods', 'GET, POST');
return $this->response->setJSON($data);
}
I have also tried setting the headers at the beginning of the script after <?php but still did not work.
I also tried the built in PHP header() function like so:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
I have even modified my JS to look like:
function verify() {
$.ajax({
url: url+"requests/verify",
type: "POST",
dataType: "JSON",
data: {domain: domain},
crossDomain: true,
success: function(data) {
if (data.success === true) {
return true;
}
}
});
return false;
}
So far nothing seems to be working, Where should I go from here?
UPDATE:
I realize that if I use Pure Javascript like:
const xhr = new XMLHttpRequest();
xhr.open('GET', url+"requests/verify");
xhr.onreadystatechange = function(data) {
if (data.success === true) {
return true;
}
}
xhr.send();
It works as expected, but I have to use jQuery to keep my code uniform, and for future reference.
Whenever, there is a cross-origin issue, there are two routes that are hit. Lets say in your example, you have GET request to "http://api.domain.te/requests/verify", So before hitting your server with GET request it will hit same url with OPTIONS request. This verifies whether your server allows the API for the Cross Origin Request.
So In CI4 routes you have to define same URL or include a wild card to enable your cross origin request.
Here, the following example is for wild card request.
$routes->options('(:any)', 'Controller/options');
Here this route matches any routes with OPTIONS method and a single method called Options is there to handle it.
This options method can be defined as follows :
public function options($any)
{
return $this->response->setHeader('Access-Control-Allow-Origin', '*') //for allow any domain, insecure
->setHeader('Access-Control-Allow-Headers', '*') //for allow any headers, insecure
->setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE') //method allowed
->setStatusCode(200); //status code
}
What this method essentially does is lets the browser know that request are allowed for Cross-Origin, with status Methods such as GET, POST, PUT and DELETE.
After browser hits this request, it will be directed to your request which should also have cross origin enabled as follow:
$this->response->setContentType('application/json')->setJSON($response)->send()->setHeader('Access-Control-Allow-Origin', '*');
Reference : https://carminemilieni.it/2019/09/19/resolve-cors-and-corb-in-codeigniter-4/
As you already do, CORS must be approached from the receiving server side, so I put headers from .htaccess in Apache sites (check how to do it if you use different server):
Header set Access-Control-Allow-Origin "*"
(in your case, it should be a * if can be multiple unknown domains)
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
(or the method ones if you want too)
Info and options on that header:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
You can check what headers are you sending out by using curl, do they appear?
curl -I http://api.domain.te/requests/verify
I have a module in Ionic who calls an api in PHP.
import { LoadingController } from 'ionic-angular';
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
....
getPatrocinios(cidade) {
var headers = new Headers();
headers.append('idCidade', cidade);
let url = 'http://somesite.com/test/index.php';
return this.http
.get(url, { headers: headers })
.map(res => res.json());
}
in PHP module i made this:
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET,HEAD,OPTIONS,POST,PUT');
header('Access-Control-Allow-Headers: Content-Type, Content-Range, Content-Disposition, Content-Description');
define('CHARSET', 'UTF-8');
define('REPLACE_FLAGS', ENT_COMPAT | ENT_XHTML);
function getHeaders($header_name = null) {
$keys=array_keys($_SERVER);
if(is_null($header_name)) {
$headers=preg_grep("/^HTTP_(.*)/si", $keys);
} else {
$header_name_safe=str_replace("-", "_", strtoupper(preg_quote($header_name)));
$headers=preg_grep("/^HTTP_${header_name_safe}$/si", $keys);
}
foreach($headers as $header) {
if(is_null($header_name)) {
$headervals[substr($header, 5)]=$_SERVER[$header];
} else {
return $_SERVER[$header];
}
}
return $headervals;
}
$id_cidade = getHeaders("idCidade");
...
Using Postman and puting the 'idCidade' in Headers tab, it works fine (status=200), but in the emulator of ionic i have the error: Request header field idCidade is not allowed by Access-Control-Allow-Headers in preflight response.
I tried most solution in stackoverflow, but still not working.
Some extra information:
Ionic Framework: 3.9.2
Ionic App Scripts: 3.1.8
Angular Core: 5.2.9
Angular Compiler CLI: 5.2.9
Node: 8.11.1
Someone to help me?
Request header field idCidade is not allowed by Access-Control-Allow-Headers in preflight response
What response header Access-Control-Allow-Headers Tells the browser is what request headers are allowed in the request. Look at the list that you provided
header('Access-Control-Allow-Headers: Content-Type, Content-Range, Content-Disposition, Content-Description');
The idCidade header is not included in that list.
I had the same problem in an App when i run with Ionic Serve.
If you are using Google Chrome, you can install a CORS extension, enable it, and testing again, in my case, that works.
Heres the extension i used:
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi
If the problem already exist, we can check other ways
This is the first time I'm making a post method request from Angular to CodeIgniter rest API.
postUsertask(Userid,TaskName)
{
let body ={
userid:Userid, taskname:TaskName
};
console.log(body);
return this.http.post("http://localhost/ci-abc/api/add_task",JSON.stringify(body) )
.map(res => res.json());
}
API method in codeigniter:
function add_task_post()
{
$obj=json_decode(file_get_contents('php://input'));
$taskname = $obj->taskname;
$userid = $obj->userid;
if (!$taskname || !$userid) {
$this->response("Enter taskname and userid to add", 400);
} else
$result = $this->todo_model->add_task($taskname, $userid);
if ($result === 0) {
$this->response("Task could not be added. Try again.", 404);
} else {
$this->response("success", 200);
}
}
Had to include to access the data
$obj=json_decode(file_get_contents('php://input'));
Because the $this->input->post and $_POST were empty and the data recieved from angular was an object so had to be accessed with -> notation. I am curious that this is not the right and ethical way to do this. Also when I didn't put JSON.stringify it gave me Cross Origin Request blocked error so that's why I put it. How should I make POST and PUT request in angular4 to rest API in CodeIgniter?
How do I get rid of CORS error which doesn't let me call the API method, if I can get rid of CORS error then I could also remove JSON.stringify which will send the data as it is and I believe the data should be accessed via input->post or $_POST.
EDIT 2:
These sort of errors while making POST PUT and DELETE API call.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://localhost/ci-abc/api/del_task?taskid=34.
(Reason: CORS preflight channel did not succeed)
EDIT (Perfect Solution):
Found out that the formdata object approach was deprecated so I just included a header in options and included in the API call http.post method which works fine and is much better solution.
constructor(public http:Http) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let options = new RequestOptions({ headers: headers });}
createUser(userName)
{
let body = { username:userName};
return this.http.post("http://localhost/ci-abc/api/create_user",body,this.options)
.map(res => res.json());
}
Deprecated approach (Works but deprecated/not usual practice):
Took few hours but found the solution, I created body as a new formdata object, appended parameters to it as key and their values and it worked fine now I am retrieving through $this->input->post.
let body = new FormData;
body.append('userid', Userid);
body.append('taskname', TaskName);
console.log(body);
return this.http.post("http://localhost/ci-abc/api/add_task",body)
.map(res => res.json());
Using these headers in the constructor of my codeigniters API controller
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Access-Control-Allow-Origin');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
API method:
function add_task_post()
{
$userid = $this->input->post('userid');
$taskname = $this->input->post('taskname');
if (!$taskname || !$userid) {
$this->response("Enter taskname and userid to add", 400);
} else
$result = $this->todo_model->add_task($taskname, $userid);
if ($result === 0) {
$this->response("Task could not be added. Try again.", 404);
} else {
$this->response("success", 200);
}
}
After running through this quick example of a GET request from Angular2 to a PHP file I continue to get -
Error 304
I am testing the difference between using node and php for the back end of an angular2 app. I have a simple GET request which is trying to retrieve a small amount of data from a php file.
The request seems to be going fine but the file is not being provided to the app.
304 NOT MODIFIED A conditional GET or HEAD request has been received
and would have resulted in a 200 OK response if it were not for the
fact that the condition evaluated to false.
In other words,
there is no need for the server to transfer a representation of the target resource because the request indicates that the client, which made the request conditional, already has a valid representation; the server is therefore redirecting the client to make use of that stored representation as if it were the payload of a 200 OK response.
CORS
I have CORS allowed inside the express app.js file.
I have CORS allowed in the PHP file.
How can I overcome this issue? I would at least like to console.log the data from the ng2 side.
Code Examples
PHP // Running on Apache port 80 # api.example.com
<?php
header("Access-Control-Allow-Origin: *");
$data = array(
array('id' => '1','first_name' => 'Cynthia'),
array('id' => '2','first_name' => 'Keith'),
array('id' => '3','first_name' => 'Robert'),
array('id' => '4','first_name' => 'Theresa'),
array('id' => '5','first_name' => 'Margaret')
);
echo json_encode($data);
?>
Angular2 // Running on Express Server # localhost:4200
import {Http, Response} from '#angular/http';
import {Injectable, Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `<ul>
<li *ngFor="let person of data">
{{person.id}} - {{person.first_name}}
</li>
</ul>`
})
export class AppComponent {
private data;
constructor(private http:Http){
}
ngOnInit(){
this.getData();
}
getData(){
this.http.get('api.example.com/index.php')
.subscribe(res => this.data = res.json());
}
}
I have tried to modify the getData() function none which have worked. Most recently this,
getData(){
let url = 'api.example.com/index.php';
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
this.http.get(url, options)
.subscribe(res => {
this.data = res.json();
console.log(this.data);
});
}
I had similar issue but have been able to fix it by setting the following headers on my api script;
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}
// Since Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
exit(0); }
Hope it helps
I have created a mail service on php, this service send letter to some user. Here is a code:
<?php
require 'vendor/autoload.php';
header('Content-type : application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: X-Requested-With, content-type');
$response = array(
'text' => '');
if(!empty($_POST)){
$json = json_decode($_POST["req"]);
$key = $json->key;
$sub = $json->subject;
$toemail = $json->emailTo;
$FromEmail = $json->emailFrom;
$html = $json ->html;
$sendgrid = new SendGrid($key);
$email = new SendGrid\Email();
$email->addTo($toemail)
->setFrom($FromEmail)
->setSubject($sub)
->setHtml($html);
$sendgrid->send($email);
$response['text'] = 'Email was sent from '.$FromEmail.' to'. $toemail.'. Success.';
}else{
$response['text'] = 'Sorry! $_POST is undefind';
}
echo json_encode($response);
?>
I need to create a cross domain request to this service using Angular.js.
Here is my code:
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
app.controller("emailCtrl", function ($scope, $http) {
var dataForAdminNewsletter = angular.toJson({
key: "********************************************",
subject: "New Email",
emailTo: "mail1#mail.com",
emailFrom: "mail1#mail.com",
html: 'You have a new subscriber' + $scope.emailField
});
$scope.sendPost = function () {
$http({
url: 'http://my.azurewebsites.net/mail.php',
method: "POST",
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
data: {
"req": dataForAdminNewsletter
}
});
}
});
As the result I have got the next error: XMLHttpRequest cannot load my.azurewebsites.net/mail.php. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'localhost:11708' is therefore not allowed access.
I can not change the code on the server side. Can somebody help me to resolve this issue with Angular?
Thank you.
I am using this lines in apache virtual host conf,
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
</IfModule>
<IfModule mod_headers.c>
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS"
</IfModule>
And it works as charm, may be this help.
simply put- You can't.
CORS should be enabled in the server for the angular service or as a matter of fact any external service to communicate with it.
Ref: https://gist.github.com/mlynch/be92735ce4c547bd45f6
Use fiddler or chromium devTools to check the request and response.
The response from the server should have the CORS Header.
changing the angular service request will not do any good
additionally You can check this link - https://forum.ionicframework.com/t/http-no-access-control-allow-origin-problem-on-post/5625/6