Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional header fixes #33

Merged
merged 3 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Replaces `textalk/websocket`.

The client and server provides methods for reading and writing to WebSocket streams.

This fork is maintained by Sören Jensen, who has been maintaining the original textalk/websocket
repo since `v1.3`.
This repo replaces the abandoned `textalk/websocket` repo
and is maintained by Sören Jensen, who has been maintaining the original since `v1.3`.

## Documentation

Expand Down
5 changes: 5 additions & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

> PHP version `^8.0`
### `2.1.1`

* Fix issue with falsy but valid HTTP headers (@axklim)
* Additional check for HTTP headers (@sirn-se)

### `2.1.0`

* Http & Tick middleware support (@sirn-se)
Expand Down
5 changes: 3 additions & 2 deletions docs/Contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ make coverage
* Simon Lipp
* Quentin Bellus
* Patrick McCarren
* swmcdonnell,
* swmcdonnell
* Ignas Bernotas
* Mark Herhold
* Andreas Palm
Expand All @@ -85,4 +85,5 @@ make coverage
* Antonio Mora
* Simon Podlipsky
* etrinh
* zgrguric
* zgrguric
* axklim
8 changes: 4 additions & 4 deletions docs/Listener.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ If you use the listener method `->start()` this will be the only way to act on i
## Message listeners

The message listeners are called whenever the client or server receives a message of the same type.
All message listeners receive Client|Server, Connection and Message as arguments.
All message listeners receive `Client|Server`, `Connection` and `Message` as arguments.

```php
$client_or_server
Expand Down Expand Up @@ -40,8 +40,8 @@ $client_or_server

These listeners are called when the Client or Server connects and disconnects.

* On Client, the onConnect() will receive a Response as last argument
* On Server, the onConnect() will receive a ServerRequest as last argument
* On Client, the `onConnect()` will receive a `Response` as last argument
* On Server, the `onConnect()` will receive a `ServerRequest` as last argument

```php
$client_or_server
Expand Down Expand Up @@ -75,7 +75,7 @@ $client_or_server
Using above functions, your Client and Server will be able to receive incoming messages and take action accordingly.

But what if your implementation need to process other data, and send unsolicited messages?
The coroutine implementation will regulary call the onTick() method, depending on workload and configuration.
The coroutine implementation will regulary call the `onTick()` method, depending on workload and configuration.

```php
$client_or_server
Expand Down
2 changes: 1 addition & 1 deletion docs/Middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ These middlewares are included in library and can be added to provide additional

## Middleware descriptions

Descriptiopn of included middlewares.
Description of included middlewares.

### The CloseHandler middleware

Expand Down
10 changes: 3 additions & 7 deletions docs/Server.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,18 +162,14 @@ $server->close(1000, "Closing now");
When started, the server will continue to run until something tells it so stop.
There are some additional methods that control the server.

Start server - It will continuously listen to incoming messages and apply specified callback functions.
```php
// Start server - It will continuously listen to incoming messages and apply specified callback functions
$server->start();
```

Stop server - When called, server will no longer listen to incoming messages but will not disconnect clients.
```php
// Stop server - When called, server will no longer listen to incoming messages but will not disconnect clients
$server->stop();
```

Disconnect server - Server will immediately stop and disconnect all clients without normal close procedure.
```php
//Disconnect server - Server will immediately stop and disconnect all clients without normal close procedure
$server->disconnect();
```

Expand Down
12 changes: 9 additions & 3 deletions src/Http/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public function getHeaderLine(string $name): string
* @return static
* @throws \InvalidArgumentException for invalid header names or values.
*/
public function withHeader(string $name, $value): self
public function withHeader(string $name, mixed $value): self
{
$new = clone $this;
if ($this->hasHeader($name)) {
Expand All @@ -116,7 +116,7 @@ public function withHeader(string $name, $value): self
* @throws \InvalidArgumentException for invalid header names.
* @throws \InvalidArgumentException for invalid header values.
*/
public function withAddedHeader(string $name, $value): self
public function withAddedHeader(string $name, mixed $value): self
{
$new = clone $this;
$new->handleHeader($name, $value);
Expand Down Expand Up @@ -164,14 +164,20 @@ public function getAsArray(): array
return $lines;
}

private function handleHeader(string $name, string|array $value): void
private function handleHeader(string $name, mixed $value): void
{
// @todo: Add all available characters, these are just some of them.
if (!preg_match('|^[0-9a-zA-Z#_-]+$|', $name)) {
throw new InvalidArgumentException("'{$name}' is not a valid header field name.");
}
$value = is_array($value) ? $value : [$value];
if (empty($value)) {
throw new InvalidArgumentException("Invalid header value(s) provided.");
}
foreach ($value as $content) {
if (!is_string($content) && !is_numeric($content)) {
throw new InvalidArgumentException("Invalid header value(s) provided.");
}
$content = trim($content);
if ('' === $content) {
throw new InvalidArgumentException("Invalid header value(s) provided.");
Expand Down
38 changes: 18 additions & 20 deletions tests/suites/http/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace WebSocket\Test\Http;

use BadMethodCallException;
use Generator;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use Phrity\Net\StreamFactory;
Expand Down Expand Up @@ -215,7 +216,7 @@ public function testWithBodyError(): void
$request->withBody($factory->createStream());
}

public function testHaederNameError(): void
public function testHeaderNameError(): void
{
$request = new Request();
$this->expectException(InvalidArgumentException::class);
Expand All @@ -224,48 +225,45 @@ public function testHaederNameError(): void
$request->withHeader('.', 'invaid name');
}

public function testHaederValueError(): void
{
$request = new Request();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionCode(0);
$this->expectExceptionMessage("Invalid header value(s) provided.");
$request->withHeader('name', '');
}

/**
* @dataProvider provideInvalidHeaderValues
* @
*/
public function testHeaderValueInvalidVariants($value): void
public function testHeaderValueInvalidVariants(mixed $value): void
{
$request = new Request();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionCode(0);
$this->expectExceptionMessage("Invalid header value(s) provided.");
$request->withHeader('name', $value);
}

public static function provideInvalidHeaderValues(): \Generator
public static function provideInvalidHeaderValues(): Generator
{
yield [''];
yield [' '];
yield [['0', '']];
yield [[null]];
yield [[[0]]];
yield [[]];
}

/**
* @dataProvider provideValidHeaderValues
* @
*/
public function testHeaderValueValidVariants($value): void
public function testHeaderValueValidVariants(mixed $value, array $expected): void
{
$request = new Request();
$request = $request->withHeader('name', $value);
$this->assertInstanceOf(Request::class, $request);
$this->assertEquals($expected, $request->getHeaders());
}

public static function provideValidHeaderValues(): \Generator
public static function provideValidHeaderValues(): Generator
{
yield ['null'];
yield ['0'];
yield [' 0'];
yield ['1'];
yield ['null', ['name' => ['null']]];
yield ['0 ', ['name' => ['0']]];
yield [' 0', ['name' => ['0']]];
yield [['0', '1'], ['name' => ['0', '1']]];
yield [0, ['name' => ['0']]];
}
}