Skip to content

Commit

Permalink
Feature/hhvm 4.35 patch (#39)
Browse files Browse the repository at this point in the history
* wip

* updated

* Update .hhconfig

* changed dependency

* Update .travis.yml

* Update .travis.sh

* Update README.md

* added cors middleware
  • Loading branch information
ytake authored Feb 14, 2020
1 parent cfed5e2 commit 8714f2e
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 12 deletions.
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@
"hhvm": "^4.35",
"hhvm/hsl": "^4.0",
"hhvm/hsl-experimental": "^4.25",
"hhvm/hhvm-autoload": "^3.0.0",
"hhvm/hhvm-autoload": "^3.0",
"hhvm/type-assert": "^3.7",
"hack-psr/psr7-http-message-hhi": "^1.0.0",
"ytake/hungrr": "^0.9.0",
"ytake/hhypermedia": "^0.5.0",
"nazg/glue": "^1.4.0",
"nazg/heredity": "^1.8.0",
"nazg/heredity": "^1.9",
"nazg/hcache": "^0.5.0",
"nazg/http-server-request-handler": "^0.4.1",
"nazg/http-executor": "^0.8.0",
"nazg/http-server-request-handler": "^0.5",
"nazg/http-executor": "^0.9",
"facebook/hack-router": ">=0.17 <1.0",
"facebook/hack-http-request-response-interfaces": "^0.2",
"hack-logging/hack-logging": "^0.4.0"
Expand Down
2 changes: 1 addition & 1 deletion src/Foundation/Application.hack
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class Application {
public function __construct(
private Container $container,
private IO\ReadHandle $readHandle,
private IO\WriteHandle $writeHandle,
private IO\CloseableWriteHandle $writeHandle,
) {}

public function build(ApplicationConfig $config): this {
Expand Down
4 changes: 2 additions & 2 deletions src/Middleware/Dispatcher.hack
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
namespace Nazg\Middleware;

use type HH\Lib\Experimental\IO\WriteHandle;
use type HH\Lib\Experimental\IO\CloseableWriteHandle;
use type Nazg\Heredity\AsyncHeredity;
use type Nazg\Glue\Container;
use type Nazg\Http\Server\AsyncMiddlewareInterface;
Expand All @@ -30,7 +30,7 @@ class Dispatcher extends AsyncHeredity {

<<__Override>>
protected async function processorAsync(
WriteHandle $writeHandle,
CloseableWriteHandle $writeHandle,
AsyncMiddlewareInterface $middleware,
ServerRequestInterface $request
): Awaitable<ResponseInterface> {
Expand Down
4 changes: 2 additions & 2 deletions src/Middleware/LogExceptionMiddleware.hack
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Nazg\Middleware;

use type HackLogging\Logger;
use type HackLogging\LogLevel;
use type HH\Lib\Experimental\IO\WriteHandle;
use type HH\Lib\Experimental\IO\CloseableWriteHandle;
use type Facebook\Experimental\Http\Message\ResponseInterface;
use type Facebook\Experimental\Http\Message\ServerRequestInterface;
use type Nazg\Http\Server\AsyncMiddlewareInterface;
Expand All @@ -30,7 +30,7 @@ class LogExceptionMiddleware implements AsyncMiddlewareInterface {
) {}

public async function processAsync(
WriteHandle $writeHandle,
CloseableWriteHandle $writeHandle,
ServerRequestInterface $request,
AsyncRequestHandlerInterface $handler,
): Awaitable<ResponseInterface> {
Expand Down
77 changes: 77 additions & 0 deletions src/Middleware/SimpleCorsMiddleware.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*
* Copyright (c) 2017-2020 Yuuki Takezawa
*
*/
namespace Nazg\Middleware;

use type Facebook\HackRouter\HttpMethod;
use type Facebook\Experimental\Http\Message\ResponseInterface;
use type Facebook\Experimental\Http\Message\ServerRequestInterface;
use type HH\Lib\Experimental\IO\CloseableWriteHandle;
use type Nazg\Http\Server\AsyncMiddlewareInterface;
use type Nazg\Http\Server\AsyncRequestHandlerInterface;
use function implode;

type CorsSetting = shape(
?'origin' => string,
?'header' => string,
'methods' => Vector<HttpMethod>,
);

enum AccessControl : string as string {
AllowOrigin = 'Access-Control-Allow-Origin';
AllowHeaders = 'Access-Control-Allow-Headers';
AllowMethods = 'Access-Control-Allow-Methods';
}

class SimpleCorsMiddleware implements AsyncMiddlewareInterface {

protected string $allowOrigin = '*';
protected string
$allowHeaders = 'X-Requested-With, Content-Type, Accept, Origin, Authorization';
protected Vector<HttpMethod>
$allowMethods = Vector {
HttpMethod::GET,
HttpMethod::HEAD,
HttpMethod::POST,
};

public function __construct(protected CorsSetting $cors) {}

public async function processAsync(
CloseableWriteHandle $writeHandle,
ServerRequestInterface $request,
AsyncRequestHandlerInterface $handler,
): Awaitable<ResponseInterface> {
$response = await $handler->handleAsync($writeHandle, $request);
$origin = ($this->cors['origin']) ?? $this->allowOrigin;
$header = ($this->cors['header']) ?? $this->allowHeaders;
$methods =
($this->cors['methods']->isEmpty())
? $this->allowMethods
: $this->cors['methods'];
return
$response->withHeader(AccessControl::AllowOrigin, vec[$origin])
->withHeader(AccessControl::AllowHeaders, vec[$header])
->withHeader(
AccessControl::AllowMethods,
vec[$this->implodeMethods($methods)],
);
}

<<__Rx>>
protected function implodeMethods(Vector<HttpMethod> $methods): string {
return implode(",", $methods);
}
}
36 changes: 36 additions & 0 deletions src/Middleware/SimpleCorsMiddlewareProvider.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license.
*
* Copyright (c) 2017-2020 Yuuki Takezawa
*
*/
namespace Nazg\Middleware;

use type Facebook\HackRouter\HttpMethod;
use type Nazg\Glue\Container;
use type Nazg\Glue\ProviderInterface;

class SimpleCorsMiddlewareProvider implements ProviderInterface<SimpleCorsMiddleware> {

public function get(
Container $container
): SimpleCorsMiddleware {
return new SimpleCorsMiddleware(shape(
'methods' => Vector {
HttpMethod::GET,
HttpMethod::HEAD,
HttpMethod::POST,
},
)
);
}
}
2 changes: 1 addition & 1 deletion tests/Logger/LoggerProviderTest.hack
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class LoggerProviderTest extends HackTest {
$container->bind(ApplicationConfig::class)
->to(ApplicationConfig::class);
expect(() ==> $logger->get($container))
->toThrow(\HH\Lib\Experimental\OS\NotFoundException::class);
->toThrow(\HH\Lib\Experimental\OS\Exception::class);
}

public function testShouldReturnLoggerInstance(): void {
Expand Down
16 changes: 16 additions & 0 deletions tests/Middleware/FakeActionMiddleware.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use type HH\Lib\Experimental\IO\CloseableWriteHandle;
use type Facebook\Experimental\Http\Message\ResponseInterface;
use type Facebook\Experimental\Http\Message\ServerRequestInterface;
use type Nazg\Http\Server\AsyncMiddlewareInterface;
use type Nazg\Http\Server\AsyncRequestHandlerInterface;

final class FakeActionMiddleware implements AsyncMiddlewareInterface {

public async function processAsync(
CloseableWriteHandle $writeHandle,
ServerRequestInterface $request,
AsyncRequestHandlerInterface $handler,
): Awaitable<ResponseInterface> {
return await $handler->handleAsync($writeHandle, $request);
}
}
4 changes: 2 additions & 2 deletions tests/Middleware/FakeThrowExceptionMiddleware.hack
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use type HH\Lib\Experimental\IO\WriteHandle;
use type HH\Lib\Experimental\IO\CloseableWriteHandle;
use type Facebook\Experimental\Http\Message\ResponseInterface;
use type Facebook\Experimental\Http\Message\ServerRequestInterface;
use type Nazg\Http\Server\AsyncMiddlewareInterface;
Expand All @@ -7,7 +7,7 @@ use type Nazg\Http\Server\AsyncRequestHandlerInterface;
final class FakeThrowExceptionMiddleware implements AsyncMiddlewareInterface {

public async function processAsync(
WriteHandle $writeHandle,
CloseableWriteHandle $writeHandle,
ServerRequestInterface $request,
AsyncRequestHandlerInterface $handler,
): Awaitable<ResponseInterface> {
Expand Down
56 changes: 56 additions & 0 deletions tests/Middleware/SimpleCorsMiddlewareTest.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use type HackLogging\Logger;
use type Nazg\Glue\{Container, Scope, DependencyFactory};
use type Nazg\Heredity\AsyncMiddlewareStack;
use type Facebook\HackTest\HackTest;
use type Ytake\Hungrr\ServerRequestFactory;
use type Nazg\RequestHandler\AsyncFallbackHandler;
use type Nazg\Foundation\ApplicationConfig;
use namespace Nazg\Logger;
use namespace Nazg\Middleware;
use namespace HH\Lib\Experimental\IO;
use function Facebook\FBExpect\expect;

final class SimpleCorsMiddlewareTest extends HackTest {

private function getDependency(): Container {
$container = new Container(new DependencyFactory());
$container->bind(Middleware\SimpleCorsMiddleware::class)
->provider(new Middleware\SimpleCorsMiddlewareProvider());
$container->bind(FakeThrowExceptionMiddleware::class)
->to(FakeThrowExceptionMiddleware::class);
$container->bind(FakeActionMiddleware::class)
->to(FakeActionMiddleware::class);
\HH\Asio\join($container->lockAsync());
return $container;
}

public async function testShouldReturnCorsHeader(): Awaitable<void> {
$filename = __DIR__ . '/../storages/testing.log';
list($read, $write) = IO\pipe_nd();
$heredity = new Middleware\Dispatcher(
new AsyncMiddlewareStack(
vec[
Middleware\SimpleCorsMiddleware::class,
FakeActionMiddleware::class
],
new Middleware\GlueResolver($this->getDependency())
),
new AsyncFallbackHandler(),
);
$res = await $heredity->handleAsync(
$write,
ServerRequestFactory::fromGlobals($read)
);
$headers = $res->getHeaders();
expect($headers)->toContainKey('Access-Control-Allow-Origin');
expect($headers)->toContainKey('Access-Control-Allow-Headers');
expect($headers)->toContainKey('Access-Control-Allow-Methods');

expect($headers['Access-Control-Allow-Origin'])
->toBeSame(vec['*']);
expect($headers['Access-Control-Allow-Headers'])
->toBeSame(vec['X-Requested-With, Content-Type, Accept, Origin, Authorization']);
expect($headers['Access-Control-Allow-Methods'])
->toBeSame(vec['GET,HEAD,POST']);
}
}

0 comments on commit 8714f2e

Please sign in to comment.