I am calling a login method from subdomain on main domain, and I made a CORS middleware which should take care of it. However it doesn't work as expected.
I want to check if requests came from a specific domain, so I tried doing this:
public function handle($request, Closure $next)
{
if(!isset($_SERVER['HTTP_REFERER']))
return $next($request);
$originalDomain = config('session.domain');
$parsedUrl = parse_url($_SERVER['HTTP_REFERER']);
$splitDomain = explode('.', $parsedUrl['host'], 2);
$subdomain = $splitDomain[0];
$domain = $splitDomain[1];
$subdomainValid = ($parsedUrl['host'] != $originalDomain) && ($originalDomain == $domain);
if(!$subdomainValid)
return $next($request);
$allowedUrl = $parsedUrl['scheme'] . '://' . $subdomain . '.' . config('session.domain');
return $next($request)
->header('Access-Control-Allow-Origin', $allowedUrl)
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'Origin, x-requested-with, x-csrf-token');
}
But the issue I'm having is that $_SERVER['HTTP_REFERER'] sometimes doesn't return the value I expect. Shouldn't it return origin of the request?
I actually changed referrer to origin and added this part of code which resolves my issue:
if (isset($_SERVER['HTTP_ORIGIN']))
$referrer = $_SERVER['HTTP_ORIGIN'];
else
$referrer = request()->url();
Related
My angular application runs on http://localhost:4200/ and my Slim4 application runs on localhost:8080. When I try to integrate APIS between angular and slim, GET API works fine, but the POST API does not. I get the below CORS error,
Access to XMLHttpRequest at 'http://localhost:8080/admin/login' from origin 'http://localhost:4200' has been blocked by CORS policy: Request header field cache-control is not allowed by Access-Control-Allow-Headers in preflight response.
My angular request 'content-type' is 'applictaion/json'. Please find the slim4 response header below,
<?php
declare(strict_types=1);
namespace App\Application\ResponseEmitter;
use Psr\Http\Message\ResponseInterface;
use Slim\ResponseEmitter as SlimResponseEmitter;
class ResponseEmitter extends SlimResponseEmitter
{
/**
* {#inheritdoc}
*/
public function emit(ResponseInterface $response): void
{
// This variable should be set to the allowed host from which your API can be accessed with
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
$response = $response
->withHeader('Access-Control-Allow-Credentials', 'true')
->withHeader('Access-Control-Allow-Origin', $origin)
->withHeader(
'Access-Control-Allow-Headers',
'X-Requested-With, Content-Type, Accept, Origin, Authorization',
)
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS')
->withHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
->withAddedHeader('Cache-Control', 'post-check=0, pre-check=0')
->withHeader('Pragma', 'no-cache');
if (ob_get_contents()) {
ob_clean();
}
parent::emit($response);
}
}
Have you tried this?
->withHeader('Access-Control-Allow-Origin', '*')
I've tried to set up a Angular App with SLIM Framework v4 Backend; Angular is running local, while Slim is on a Deploy Server. So CORS Setup is needed and I did like given in the documentation:
$app->options('/{routes:.+}', function ($request, $response, $args) {
return $response;
});
$app->add(function ($request, $handler) {
$response = $handler->handle($request);
return $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});
On get Requests the Acces-Control-Allow-Origin Header is present; no problem, everything working as expected. On Put request (example):
$app->put('/event/{id}', function (Request $request, Response $response, $args) use ($app) {
$id = $args['id'];
$response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization');
$response->getBody()->write('Test with $id');
return $response;
});
even with an additional add in the function, the header is not present on the response in the browser.
What am I doing wrong?
The request and response object is immutable. You can try this:
$app->put('/event/{id}', function (Request $request, Response $response, $args) {
$id = $args['id'];
$response = $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization');
$response->getBody()->write('Test with $id');
return $response;
}
I wanted to set up a dynamic CORS middleware which would check on the fly if the subdomain I am using is the valid subdomain for my server. I have tested the logic behind it and it works, but when providing a variable to the header, it seems as if something isn't right?
Here is the code:
public function handle($request, Closure $next)
{
$originalDomain = config('session.domain');
$parsedUrl = parse_url(request()->url());
$splitDomain = explode('.', $parsedUrl['host'], 2);
$subdomain = $splitDomain[0];
$domain = $splitDomain[1];
$subdomainValid = $parsedUrl['host'] != $originalDomain && $originalDomain == $domain;
if(!$subdomainValid)
return $next($request);
$allowedUrl = $parsedUrl['scheme'] . '://' . $subdomain . '.' . config('session.domain_without_dot');
return $next($request)
->header('Access-Control-Allow-Origin', $allowedUrl)
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
}
I am getting the error that No 'Access-Control-Allow-Origin' header is present on the requested resource, but if I dump the variable I got, and paste it in, it works just fine.
I have resolved the issue by changing
$parsedUrl = parse_url(request()->url());
to
$parsedUrl = parse_url($_SERVER['HTTP_ORIGIN']);
Explanation
Since this middleware is put on the server, when request goes through the middleware, the request()->url() is actually the value of the server URL, not of the subdomain requesting it. With this change I am fetching an URL of the subdomain which requested the server resource.
I have a issue with my slim app, i want send json responses but with customed headers. My code is like follow:
index.php
require 'vendor/autoload.php';
require 'app/config.php';
require 'app/libs/api.cs.php';
$app = new Slim\App(
[
"settings" => $config,
"apics" => function() { return new APIHelper(); } //This is a class that contain a "helper" for api responses
]
);
require 'app/dependences.php';
require 'app/middleware.php';
require 'app/loader.php';
require 'app/routes.php';
// Run app
$app->run();
app/libs/api.cs.php (The "helper")
<?php
class APIHelper
{
public function sendResponse($response, $status='success' ,$code = 200, $message = "", $data = null)
{
$arrResponse = array();
$arrResponse['status'] = $status;
$arrResponse['code'] = $code;
$arrResponse['message'] = $message;
$arrResponse['data'] = $data;
return $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization, AeroTkn')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->withHeader('Content-Type','application/json')
->withHeader('X-Powered-By','My API Server')
->withJson($arrResponse,$code);
}
}
my routes file (app/routes.php)
$app->group('/foo', function () {
$this->get('', function ($req, $res, $args) {
return $this->apics->sendResponse($res, 'success' ,200, "Foo API Index By Get", null);
});
$this->post('', function ($req, $res, $args) {
try{
$oBody = $req->getParsedBody();
return $this->apics->sendResponse($res, 'success' ,200, "Foo API POST Response", $oBody);
}
catch(\Exception $ex){
return $this->apics->sendResponse($res, 'error' ,500, "Process Error", array('error' => $ex->getMessage()));
}
});
});
When i trying to run my app with request body, the result is the follow:
Headers:
connection →Keep-Alive
content-type →text/html
date →Wed, 30 Aug 2017 02:22:56 GMT
keep-alive →timeout=2, max=500
server →Apache
transfer-encoding →chunked
Body (returns as simple text and not json encoded)
{"status":"success","code":200,"message":"Foo API POST Response","data":{"one":"1", "two":"2"}}
I've trying put this class as a middleware, but i'm some confused in these subject.
Can you help me telling me if these method is good or where i'm bad.
Thanks to all and i hope for your answers! Nice day
Using Middleware is the ideal answer for your problem
Just add this function in your middeleware file
$app->add(function ($req, $res, $next) {
$response = $next($req, $res);
return $response
->withHeader('Access-Control-Allow-Origin', 'http://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
->withHeader('Content-Type','application/json');
->withHeader('X-Powered-By','My API Server');
});
I found the "error" was a kindergarden issue hahaha, I've download all my code from the web server for test in my machine, I have the same result, but i found that all my files had strange characters at start, so i re-save the files as utf-8 and the problem is solved. Little details that can create headaches!. Thanks to Nica and Ramy. Ramy: the solution was excellent, now the code are more organizated, i take this practice. Good day to all.
i make api in which i send image link then user can download image from this link
1st problem
$path = (public_path("images") . $filename);
echo $path than path would be like this
"C:\wamp\www\jobpost\public\imagesPerson.PNG" // why its not put \ after images
i do this but error occur
$path = (public_path("images") ."\". $filename);
2nd problem
after i test image download or not i manually place the link
return Response::download("C:\wamp\www\jobpost\public\images\Person.PNG");
error occur
Call to undefined method Illuminate\Auth\Access\Response::download()
i am already use this at the top of my controller
use Illuminate\Auth\Access\Response; // i comment this and use
use Response //error remove
3rd problem
when i use Response
return Response::download("C:\wamp\www\jobpost\public\images\Person.PNG");
error occur
Call to undefined method Symfony\Component\HttpFoundation\BinaryFileResponse::header()
i searched alot this is my header
$headers = array(
'Content-Type: PNG',
);
i replace this
return Response::download("C:\wamp\www\jobpost\public\images\Person.PNG");
from this
return( Response::download( "C:\wamp\www\jobpost\public\images\Person.PNG", 'filename.PNG', $headers) );
but still problem not solve
my cors.php
Cors.php
$headers = [
'Access-Control-Allow-Origin'=> '*',
'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers'=> 'Content-Type, X-Auth-Token, Origin',
'Access-Control-Allow-Credentials' => 'true'
];
if($request->getMethod() == "OPTIONS") {
// The client-side application can set only headers allowed in Access-Control-Allow-Headers
return Response::make('OK', 200, $headers);
}
$response = $next($request);
foreach($headers as $key => $value)
$response->header($key, $value);
return $response;
use
response()->download("C:\wamp\www\jobpost\public\images\Person.PNG");