Just started a new project with CodeIgniter and after installation with composer I noticed the following warning in Routes.php:
// The Auto Routing (Legacy) is very dangerous. It is easy to create vulnerable apps...
So following the suggestion I set:
$routes->setAutoRoute(true);
and in Feature.php:
public bool $autoRoutesImproved = true;
My default route in Routes.php at the moment:
$routes->get('/', 'Authentication::index');
This is the Authentication controller
class Authentication extends BaseController {
public function index(): ResponseInterface {
...
return $this->response
->setBody($this->twig->render('login/view.twig'))
->setStatusCode(302);
}
public function postLogin(): ResponseInterface {
$authModel = new AuthenticationModel();
$response = $authModel->verifyLogin($_POST['loginUsername'], $_POST['loginPassword']);
return $this->response
->setBody($response)
->setStatusCode(200);
}
}
When I go to http://localhost:8080 the login page loads as it should.
I perform an AJAX request on the login page to verify the user credentials so that the latter can log in; but I am getting 404 on the following URL: http://localhost:8080/authentication/login
This is the AJAX request:
pageLoginForm.on('submit', function(e) {
let isValid = pageLoginForm.valid();
if (isValid) {
e.preventDefault();
$.ajax({
type: 'POST',
url: _baseUrl + 'authentication/login',
data: pageLoginForm.serializeArray(),
success: function (response) {
response === 'login' ? window.location.reload() : $('#errorMsg').text(response);
},
error: function () {
$('#errorMsg').text('An error occurred!');
}
});
}
});
I added the prefix "post" to my controller method as instructed by the documentation but it's not working.
Am I missing something?
It's a really frustrating issue with the pre-flight. Ajax made an options request to know if post is enebled. To solve this, make a controller to handle options requests whith:
php spark make:controller options
So modify controller in this way:
public function index()
{
return $this->optionsHandler();
}
public function optionsHandler(){
header("Access-Control-Allow-Headers: Origin, X-API-KEY, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Authorization, observe, enctype, Content-Length, X-Csrf-Token");
header("Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS");
header("Access-Control-Allow-Credentials: true");
header("HTTP/1.1 200 OK");
return die();
}
Then inside Config/Routes.php Add:
$routes->options('(:any)', 'Options::optionsHandler');
Take a look how I've implemented this in my project:
https://github.com/Akir4d/AOP
I hope this helps!
Related
Let's say I have a next js application which exists in a different domain that needs to call a laravel route. This route leads to a login page.
This is what I did on react side
const handleSubmit = async (e) => {
e.preventDefault();
try {
const result = await axios.get("http://localhost:5001/login", {
headers: {
// "content-type": "application/json",
"x-api-signature": "my-secret-token",
},
});
console.log(result);
} catch (error) {
console.log(error);
}
};
I am getting cors error on front end
// In Laravel auth.php
Route::get('login', [AuthenticatedSessionController::class, 'create'])
->name('login');
This route leads to a simple login page.
You can use CORS Middleware for Laravel
Or by using middleware, something like (not tested)
Note that https://stackoverflow.com should be your app domain.
class Cors
{
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', 'https://stackoverflow.com')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, X-Token-Auth, Authorization');
}
}
Read
Laravel CORS Guide: What It Is and How to Enable It
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 am new with GraphQL. I need to make an API with PHP and GraphQL.
I followed this tutorial:
https://medium.com/swlh/setting-up-graphql-with-php-9baba3f21501
everything was OK, but when opening the URL, I got this error:
{
"statusCode": 405,
"error": {
"type": "NOT_ALLOWED",
"description": "Method not allowed. Must be one of: OPTIONS"
}
}
I added this to the index page :
header('Access-Control-Allow-Origin', '*');
header('Access-Control-Allow-Headers', 'content-type');
header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
but the problem wasn't resolved.
Maybe something is missing here:
return function (App $app) {
$app->options('/{routes:.*}', function (Request $request, Response $response) {
// CORS Pre-Flight OPTIONS Request Handler
return $response;
});
Error Message : Method not Allowed
Error Status Code : 405
Reason :
Actually we get this error as response to our option request not to our Post request. Browser sends option request before it sends POST, PATCH, PUT, DELETE and so on.
GraphQL declines anything that is not GET or POST so option request is declined
Solution :
Go to our cors middleware and check if its option then returns empty response with status 200. So in this way option request will never reach to GraphQL middleware
Like :
if (req.method === "OPTIONS") {
return res.sendStatus(200);
}
as
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Methods",
"OPTIONS, GET, POST, PUT, PATCH, DELETE"
);
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
if (req.method === "OPTIONS") {
return res.sendStatus(200);
}
next();
});
$app = AppFactory::create();
Add
$app->setBasePath("/project/public/index.php");
I am new to Laravel and Lumen framework. I am doing my first project using Lumen. I am trying to create an API calling from angular
Here is my angular code :
app.controller('ListCtrl', ['$scope', '$http', '$location', '$window', function($scope, $http, $location, $window) {
$scope.data = {};
$scope.getdata = function() {
$scope.datas = [];
$headers = {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS, PUT',
'Content-Type': 'application/json',
'Accept': 'application/json'
};
$http({
url: "http://localhost/service/public/getdata/",
method: "GET",
params: {'place':$scope.data.place,'pincode':$scope.data.pincode},
headers: $headers
})
.success(function(data,status,headers,config) {
$scope.datas=JSON.stringify(data);
console.log($scope.datas);
$scope.navig('/show.html');
})
.error(function(){
alert("failed");
});
};
$scope.navig = function(url) {
$window.location.href = url;
};
}]);
And here is my Lumen route.php :
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Content-Type");
$app->get('/', function () use ($app) {
return $app->version();
});
$app->get('getdata','App\Http\Controllers\PlaceController#index');
And here is PlaceController.php
<?php
namespace App\Http\Controllers;
use App\Places;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PlaceController extends Controller
{
public function __construct()
{
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Content-Type");
//header("Access-Control-Allow-Origin: http://localhost:8100");
}
public function index()
{
$places = Place::all();
return response()->json($places);
}
}
But it shows "XMLHttpRequest cannot load http://localhost/service/public/getdata/?place=sdfs. Response for preflight is invalid (redirect)" error in console.log.
I have googled for two days,but cant find a solution.
Please help
You might be having problems due to invalid/incorrect Headers in your request. The only type of header that PlaceControllerseems to allow is Content-Type, but you're sending more than that.
Also, Access-Control-Allow-Origin and Access-Control-Allow-Methods headers should be added to the server response for your request, not to the request itself.
From MDN, cross-site requests (which seems to be your case) have to meet the following conditions:
The only allowed methods are:
GET
HEAD
POST
Apart from the headers set automatically by the user agent (e.g. Connection, User-Agent, etc.), the only headers which are allowed to be manually set are:
Accept
Accept-Language
Content-Language
Content-Type
The only allowed values for the Content-Type header are:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Note: I never worked with Laravel or Lumen, but in my case if I don't set the headers correctly I end up with the same response for preflight is invalid (redirect) error.
I am using laravel as backend and angujarjs as frontend to make an application. The frontend is sitting in another server, and therefore I have to deal with cross domain policy. I have enabled CORS, so I can "send" post request.
The problem is that when I am trying to get Input::all() in laravel, the request gets cancelled. (status shown 'cancelled' in Chrome network). But when I dont use Input, everything is OK.
//laravel
class SessionController extends BaseController {
protected $entity;
public function __construct(SessionEntity $entity)
{
$this->entity = $entity;
}
public function getLogin()
{
return Response::json('hello')->header('Access-Control-Allow-Origin', '*');
}
public function postLogin()
{
//$data = Input::all();
//return Response::json($data);
// $user = $entity->login($data);
// if($user)
// {
// return Response::json($user);
// } else {
// return Response::json($entity->errors(), 400);
// }
//the code below is OK (able to send response back) , but the code above is not, because I am using Input::all()
$data = array(
"email" => "324234",
"password" => "654321"
);
return Response::json($data);
}
}
//angularjs
.controller('LoginController', ['$scope', '$http', function($scope, $http) {
$scope.send = function(credential) {
$http({
method: 'POST',
url: 'http://localhost:8000/api/session/login',
data: credential,
headers: {
'Content-Type': 'application/json; charset=UTF-8'
}
})
.success(function(data, status, headers) {
console.log(data);
console.log(status);
console.log(headers);
});
};
}]);
Here's the headers to enable CORS
App::after(function($request, $response)
{
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
$response->headers->set('Access-Control-Allow-Headers', 'Content-Type');
$response->headers->set('Access-Control-Allow-Credentials', 'true');
$response->headers->set('Access-Control-Max-Age', '1728000');
$response->headers->set('Content-Type', 'application/json; charset=UTF-8');
return $response;
});
What did I miss??
I found it. I use namespace but didn't include 'use Input'.
silly me...
Also, I found that I have to explicitly set Content-Type to 'application/json' in order to receive data using Input::all() in laravel, otherwise I get no data.
For cross domain requests you must use jsonp instead json