-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* wip * updated * Update .hhconfig * changed dependency * Update .travis.yml * Update .travis.sh * Update README.md * added cors middleware
- Loading branch information
Showing
10 changed files
with
197 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}, | ||
) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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']); | ||
} | ||
} |