Skip to content

Commit

Permalink
Merge pull request #110 from dreamfactorysoftware/develop
Browse files Browse the repository at this point in the history
Fix CORS Preflight Handling for Laravel 9
  • Loading branch information
Anas authored Mar 10, 2023
2 parents c91d00a + 13a6e53 commit ccf6d3f
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 28 deletions.
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"prefer-stable": true,
"require": {
"php": "^8.0",
"fruitcake/laravel-cors": "~3.0.0",
"doctrine/dbal": "^3.1.4",
"guzzlehttp/guzzle": "~7.4.5",
"symfony/yaml": "^6.0",
Expand Down
2 changes: 1 addition & 1 deletion routes/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
$resourcePathPattern = '[0-9a-zA-ZÀ-ÿ-_@&\#\!=,:;\/\^\$\.\|\{\}\[\]\(\)\*\+\?\' ]+';
$controller = 'DreamFactory\Core\Http\Controllers\RestController';
// Don't use any() below, or include OPTIONS here, breaks CORS
$verbs = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'];
$verbs = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];

Route::get('', $controller . '@index');
// Support old versioning in URL, i.e api/v2 and api/v2/service
Expand Down
16 changes: 3 additions & 13 deletions src/LaravelServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,9 @@ protected function addAliases()
*/
protected function addMiddleware()
{
// the method name was changed in Laravel 5.4
if (method_exists(\Illuminate\Routing\Router::class, 'aliasMiddleware')) {
Route::aliasMiddleware('df.auth_check', AuthCheck::class);
Route::aliasMiddleware('df.access_check', AccessCheck::class);
Route::aliasMiddleware('df.verb_override', VerbOverrides::class);
} else {
/** @noinspection PhpUndefinedMethodInspection */
Route::middleware('df.auth_check', AuthCheck::class);
/** @noinspection PhpUndefinedMethodInspection */
Route::middleware('df.access_check', AccessCheck::class);
/** @noinspection PhpUndefinedMethodInspection */
Route::middleware('df.verb_override', VerbOverrides::class);
}
Route::aliasMiddleware('df.auth_check', AuthCheck::class);
Route::aliasMiddleware('df.access_check', AccessCheck::class);
Route::aliasMiddleware('df.verb_override', VerbOverrides::class);

/** Add the first user check to the web group */
Route::prependMiddlewareToGroup('web', FirstUserCheck::class);
Expand Down
21 changes: 8 additions & 13 deletions src/Providers/CorsServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

namespace DreamFactory\Core\Providers;

use Fruitcake\Cors\HandleCors;
use Fruitcake\Cors\CorsService;
use DreamFactory\Core\Services\DfCorsService;
use DreamFactory\Core\Models\CorsConfig;
use Fruitcake\Cors\CorsService;
use Illuminate\Http\Middleware\HandleCors;
use Illuminate\Database\QueryException;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;
Expand Down Expand Up @@ -35,21 +36,15 @@ public function register()
*/
public function boot(Request $request, Kernel $kernel)
{
$api_prefix = config('df.api_route_prefix', 'api');
config(['cors.paths' => [$api_prefix . '/*']]);

$config = $this->getOptions($request);
$this->app->singleton(CorsService::class, function () use ($config){
return new CorsService($config);
return new DfCorsService($config);
});

/** @noinspection PhpUndefinedMethodInspection */
//$this->app['router']->middleware('cors', HandleCors::class);

if (method_exists(\Illuminate\Routing\Router::class, 'aliasMiddleware')) {
Route::aliasMiddleware('df.cors', HandleCors::class);
} else {
/** @noinspection PhpUndefinedMethodInspection */
Route::middleware('df.cors', HandleCors::class);
}

Route::aliasMiddleware('df.cors', HandleCors::class);
Route::prependMiddlewareToGroup('df.api', 'df.cors');
}

Expand Down
34 changes: 34 additions & 0 deletions src/Services/DfCorsService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace DreamFactory\Core\Services;

use Fruitcake\Cors\CorsService;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class DfCorsService extends CorsService
{
/** @var string[] */
private array $allowedMethodsCopy = [];


public function setOptions(array $options): void
{
$this->allowedMethodsCopy = $options['allowedMethods'] ?? $options['allowed_methods'] ?? $this->allowedMethodsCopy;
parent::setOptions($options);
}

public function handlePreflightRequest(Request $request): Response
{
$response = new Response();

$requestMethod = strtoupper($request->headers->get('Access-Control-Request-Method'));
if(!in_array($requestMethod, $this->allowedMethodsCopy)) {
$response->setStatusCode(405, 'Method not allowed');
} else {
$response->setStatusCode(204);
}

return $this->addPreflightRequestHeaders($response, $request);
}
}

0 comments on commit ccf6d3f

Please sign in to comment.