Skip to content
This repository has been archived by the owner on May 25, 2020. It is now read-only.

Commit

Permalink
Merge pull request #12 (Apply symfony fix by default)
Browse files Browse the repository at this point in the history
  • Loading branch information
tarampampam authored Apr 3, 2019
2 parents 2a6c9df + a52b9b2 commit 33208ba
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 13 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog][keepachangelog] and this project adheres to [Semantic Versioning][semver].

## v1.3.0

### Added

- Worker option `--not-fix-symfony-file-validation` for disabling symfony file validation fixing [#10]

[#10]:https://github.com/avto-dev/roadrunner-laravel/issues/10

## v1.2.1

### Fixed
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ If you wants to disable package service-provider auto discover, just add into yo
`--(not-)reset-redis-connections` | Обрывает (или нет) соединения с redis после обработки входящего запроса
`--(not-)refresh-app` | Принудительно пересоздает инстанс приложения после обработки **каждого** запроса
`--(not-)inject-stats-into-request` | **Перед** обработкой **каждого** запроса добавляет в объект `Request` макросы (`::getTimestamp()` и `::getAllocatedMemory()`), возвращающие значения временной метки и объем выделенной памяти
`--not-fix-symfony-file-validation` | Do **not** fix `isValid` method in `\Symfony\Component\HttpFoundation\File\UploadedFile` [#10]

> Параметры запуска указываются в файле-конфигурации (например: `./.rr.local.yml`) по пути `http.workers.command`, например: `php ./vendor/bin/rr-worker --some-parameter`
Expand Down Expand Up @@ -130,3 +131,4 @@ This is open-sourced software licensed under the [MIT License][link_license].
[link_license]:https://github.com/avto-dev/roadrunner-laravel/blob/master/LICENSE
[getcomposer]:https://getcomposer.org/download/
[roadrunner]:https://github.com/spiral/roadrunner
[#10]:https://github.com/avto-dev/roadrunner-laravel/issues/10
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"require-dev": {
"ext-pdo_sqlite": "*",
"ext-pdo": "*",
"ext-sqlite3": "*",
"avto-dev/dev-tools": "^1.9",
"jeremeamia/superclosure": "^2.4",
Expand Down
1 change: 1 addition & 0 deletions configs/rr/.rr.local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ http:
# - `--(not-)reset-redis-connections`
# - `--(not-)refresh-app`
# - `--(not-)inject-stats-into-request`
# - `--not-fix-symfony-file-validation`
command: "php ./vendor/bin/rr-worker"

# connection method (pipes, tcp://:9000, unix://socket.unix). default "pipes"
Expand Down
1 change: 1 addition & 0 deletions configs/rr/.rr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ http:
# - `--(not-)reset-redis-connections`
# - `--(not-)refresh-app`
# - `--(not-)inject-stats-into-request`
# - `--not-fix-symfony-file-validation`
command: "php ./vendor/bin/rr-worker"

# connection method (pipes, tcp://:9000, unix://socket.unix). default "pipes"
Expand Down
32 changes: 32 additions & 0 deletions fixes/fix-symfony-file-validation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Symfony\Component\HttpFoundation\File {

/**
* ***************************************************************************
* ******* WARNING **** WARNING **** WARNING **** WARNING **** WARNING *******
* ***************************************************************************
* ******* *******
* ******* THIS FUNCTION OVERLOADING IS NECESSARY MEASURE *******
* ******* https://github.com/avto-dev/roadrunner-laravel/issues/10 *******
* ******* https://github.com/spiral/roadrunner/issues/133 *******
* ******* *******
* ***************************************************************************.
*
* @see \Symfony\Component\HttpFoundation\File\UploadedFile::isValid
*
* Tells whether the file was uploaded via HTTP POST.
* @link https://php.net/manual/en/function.is-uploaded-file.php
*
* @param string $filename The filename being checked
*
* @return bool always true
*
* @since 4.0.3
* @since 5.0
*/
function is_uploaded_file($filename)
{
return true;
}
}
41 changes: 39 additions & 2 deletions src/Worker/CallbacksInitializer/CallbacksInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,54 @@ protected function defaults(CallbacksInterface $callbacks)
$request->headers->set(self::FORCE_HTTPS_HEADER_NAME, 'HTTPS');
});
}

if ($this->skipSymfonyFileValidationFixing() === false) {
$this->fixSymfonyFileValidation($callbacks);
}
}

/**
* For option: "--force-https".
* Need to skip symfony file validation fixing?
*
* @see \AvtoDev\RoadRunnerLaravel\ServiceProvider::boot()
* @return bool
*/
protected function skipSymfonyFileValidationFixing(): bool
{
return $this->start_options->hasOption(self::FIX_SYMFONY_FILE_VALIDATION_OPTION)
&& $this->start_options->getOption(self::FIX_SYMFONY_FILE_VALIDATION_OPTION) === false;
}

/**
* Symfony `isValid` method fix.
*
* @see \Symfony\Component\HttpFoundation\File\UploadedFile::isValid
* @see <https://github.com/avto-dev/roadrunner-laravel/issues/10>
* @see <https://github.com/spiral/roadrunner/issues/133>
*
* @param CallbacksInterface $callbacks
*
* @return void
*/
protected function fixSymfonyFileValidation(CallbacksInterface $callbacks)
{
$callbacks->beforeLoopStarts()
->push(function (Application $app) {
// THIS MAGIC WORKS ONLY ONCE!
if (! \function_exists('\\Symfony\\Component\\HttpFoundation\\File\\is_uploaded_file')) {
require __DIR__ . '/../../../fixes/fix-symfony-file-validation.php';
}
});
}

/**
* For option: "--force-https".
*
* @param CallbacksInterface $callbacks
* @param bool|mixed $value
*
* @return void
*
* @see \AvtoDev\RoadRunnerLaravel\ServiceProvider::boot()
*/
protected function initForceHttps(CallbacksInterface $callbacks, $value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ interface CallbacksInitializerInterface
*/
const REQUEST_ALLOCATED_MEMORY_MACRO = 'getAllocatedMemory';

/**
* Option name for fixing symfony file validation.
*/
const FIX_SYMFONY_FILE_VALIDATION_OPTION = 'fix-symfony-file-validation';

/**
* Constructor.
*
Expand Down
78 changes: 67 additions & 11 deletions tests/Worker/CallbacksInitializer/CallbacksInitializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

namespace AvtoDev\RoadRunnerLaravel\Tests\Worker\CallbacksInitializer;

use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Traits\Macroable;
use AvtoDev\RoadRunnerLaravel\Tests\AbstractTestCase;
use Illuminate\Config\Repository as ConfigRepository;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use AvtoDev\RoadRunnerLaravel\Worker\Callbacks\Callbacks;
use AvtoDev\RoadRunnerLaravel\Worker\StartOptions\StartOptions;
use AvtoDev\RoadRunnerLaravel\Worker\CallbacksInitializer\CallbacksInitializer;
Expand Down Expand Up @@ -102,34 +104,88 @@ protected function initFooBar()
/**
* @return void
*/
public function testDefaultActionsInitialized()
public function testDefaultActionCollectCycles()
{
// Get default closures without touching $this->.. instances
$callbacks = new Callbacks;
$this->callMethod(new CallbacksInitializer(new StartOptions, $callbacks), 'defaults', [$callbacks]);
$first_closure = $callbacks->afterLoopIterationStack()->first();
$second_closure = $callbacks->beforeHandleRequestStack()->first();
$closure = $callbacks->afterLoopIterationStack()->first();

// And now - call same methods using $this->.. instances
$this->initializer->makeInit();

$this->assertSame(
$this::getClosureHash($first_closure),
$this::getClosureHash($closure),
$this::getClosureHash($this->callbacks->afterLoopIterationStack()->first())
);

// Test call
$closure($this->app, new Request, new Response);
}

/**
* @return void
*/
public function testDefaultActionRemoveForceHttpsHeader()
{
$callbacks = new Callbacks;
$this->callMethod(new CallbacksInitializer(new StartOptions, $callbacks), 'defaults', [$callbacks]);
$remove_force_https_closure = $callbacks->beforeHandleRequestStack()->first();

$this->initializer->makeInit();

$this->assertSame(
$this::getClosureHash($second_closure),
$this::getClosureHash($remove_force_https_closure),
$this::getClosureHash($this->callbacks->beforeHandleRequestStack()->first())
);

// Test call
$first_closure($this->app, new Request, new Response);

($request = new Request)->headers->set(CallbacksInitializer::FORCE_HTTPS_HEADER_NAME, 'true');
$second_closure($this->app, $request);
$remove_force_https_closure($this->app, $request);
$this->assertFalse($request->headers->has(CallbacksInitializer::FORCE_HTTPS_HEADER_NAME));
}

/**
* @return void
*/
public function testDefaultActionFixSymfonyFileValidation()
{
$callbacks = new Callbacks;
$this->callMethod(new CallbacksInitializer(new StartOptions, $callbacks), 'defaults', [$callbacks]);
$closure = $callbacks->beforeLoopStarts()->first();

$this->initializer->makeInit();

$this->assertSame(
$this::getClosureHash($closure),
$this::getClosureHash($this->callbacks->beforeLoopStarts()->first())
);

$tmp_file = \tempnam(\sys_get_temp_dir(), $file_name = Str::random(32));
// If uncomment next line - "magic" doesn't work! (looks like PHP optimization in action)
// $this->assertFalse((new UploadedFile($tmp_file, $file_name))->isValid());
$this->assertFalse(\function_exists($func = '\\Symfony\\Component\\HttpFoundation\\File\\is_uploaded_file'));
$closure($this->app);
$this->assertTrue(\function_exists($func));
$this->assertTrue((new UploadedFile($tmp_file, $file_name))->isValid());

if (\is_file($tmp_file)) {
\unlink($tmp_file);
}
}

/**
* @return void
*/
public function testDefaultActionSkipSymfonyFileValidationFixing()
{
$callbacks = new Callbacks;
$this->callMethod(new CallbacksInitializer(new StartOptions([
'--not-fix-symfony-file-validation',
]), $callbacks), 'defaults', [$callbacks]);

$this->initializer->makeInit();

$this->assertCount(0, $callbacks->beforeLoopStarts());
}

/**
* @return void
*/
Expand Down

0 comments on commit 33208ba

Please sign in to comment.