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

rewrite Headers #351

Merged
merged 13 commits into from
Jan 13, 2025
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
10 changes: 5 additions & 5 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ jobs:
coverage: "xdebug"
composer-options: "--optimize-autoloader --prefer-dist --prefer-stable -v"
test-name: ""
min-msi: 99
min-covered-msi: 99
min-msi: 98
min-covered-msi: 98
skip-phpunit: false
skip-vitest: true
skip-stryker: true
upload-codecov: false
upload-codeclimate: false
upload-coveralls: false
upload-codecov: true
upload-codeclimate: true
upload-coveralls: true
upload-flag: ""
secrets:
ENV_CODECLIMATE_API_KEY: ${{ secrets.CODECLIMATE_API_KEY }}
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
## Code Status

[![codecov](https://codecov.io/gh/mimmi20/ua-generic-request/branch/master/graph/badge.svg)](https://codecov.io/gh/mimmi20/ua-generic-request)
[![Test Coverage](https://api.codeclimate.com/v1/badges/dff8d0a2ce0c7df2d03f/test_coverage)](https://codeclimate.com/github/mimmi20/ua-generic-request/test_coverage)
[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/mimmi20/ua-generic-request.svg)](https://isitmaintained.com/project/mimmi20/ua-generic-request "Average time to resolve an issue")
[![Percentage of issues still open](https://isitmaintained.com/badge/open/mimmi20/ua-generic-request.svg)](https://isitmaintained.com/project/mimmi20/ua-generic-request "Percentage of issues still open")
[![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fmimmi20%2Fua-generic-request%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/mimmi20/ua-generic-request/master)
[![Maintainability](https://api.codeclimate.com/v1/badges/dff8d0a2ce0c7df2d03f/maintainability)](https://codeclimate.com/github/mimmi20/ua-generic-request/maintainability)

## Requirements

Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"php": "~8.3.0 || ~8.4.0 || ~8.5.0",
"ext-mbstring": "*",
"laminas/laminas-diactoros": "^3.5.0",
"mimmi20/ua-loader-interface": "^3.0.0",
"mimmi20/ua-loader-interface": "^4.0.1",
"mimmi20/ua-normalizer": "^7.0.0",
"mimmi20/ua-parser-interface": "^2.0.0",
"psr/http-message": "^1.1 || ^2.0"
Expand All @@ -34,8 +34,8 @@
"infection/infection": "^0.29.10",
"mimmi20/browser-detector-version": "^11.0.0",
"mimmi20/coding-standard": "^6.0.5",
"mimmi20/ua-browser-type": "^10.0.0",
"mimmi20/ua-result": "^10.0.2",
"mimmi20/ua-browser-type": "^11.0.0",
"mimmi20/ua-result": "^12.0.0",
"nikic/php-parser": "^5.4.0",
"phpstan/extension-installer": "^1.4.3",
"phpstan/phpstan": "^2.1.1",
Expand Down Expand Up @@ -69,6 +69,7 @@
"infection/extension-installer": true,
"phpstan/extension-installer": true
},
"lock": false,
"preferred-install": "dist",
"sort-packages": true
}
Expand Down
2 changes: 2 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
declare(strict_types = 1);

use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\If_\ReduceAlwaysFalseIfOrRector;
use Rector\DeadCode\Rector\If_\RemoveAlwaysTrueIfConditionRector;
use Rector\DeadCode\Rector\If_\RemoveDeadInstanceOfRector;
use Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector;
Expand Down Expand Up @@ -39,6 +40,7 @@
FirstClassCallableRector::class,
RemoveAlwaysTrueIfConditionRector::class,
RemoveParentCallWithoutParentRector::class,
ReduceAlwaysFalseIfOrRector::class,
],
);
};
3 changes: 3 additions & 0 deletions src/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ final class Constants
/** @api */
public const string HEADER_NB_CONTENT = 'x-nb-content';

/** @api */
public const string HEADER_CRAWLED_BY = 'x-crawled-by';

/** @api */
public const string HEADER_SEC_CH_UA = 'Sec-CH-UA';

Expand Down
66 changes: 27 additions & 39 deletions src/GenericRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@
Constants::HEADER_UA_OS,
Constants::HEADER_BAIDU_FLYFLOW,
Constants::HEADER_PUFFIN_UA,
Constants::HEADER_CRAWLED_BY,
Constants::HEADER_USERAGENT,
];

/** @var array<non-empty-string, non-empty-string> */
private array $headers = [];

/** @var array<non-empty-string, HeaderInterface> */
private array $filteredHeaders = [];
private array $headers = [];

/** @throws void */
public function __construct(MessageInterface $message, private readonly HeaderLoaderInterface $headerLoader)
{
$filteredHeaders = [];

foreach (array_keys($message->getHeaders()) as $header) {
if (!is_string($header) || $header === '') {
continue;
Expand All @@ -84,24 +84,32 @@
}

if ($header === '') {
continue;

Check warning on line 87 in src/GenericRequest.php

View workflow job for this annotation

GitHub Actions / UnitTests / Code Coverage with PHPUnit (ubuntu-24.04, 8.3, lowest)

Escaped Mutant for Mutator "Continue_": @@ @@ $header = mb_substr($header, 5); } if ($header === '') { - continue; + break; } $filteredHeaders[$header] = $headerLine; }

Check warning on line 87 in src/GenericRequest.php

View workflow job for this annotation

GitHub Actions / UnitTests / Code Coverage with PHPUnit (ubuntu-24.04, 8.3, lowest)

Escaped Mutant for Mutator "Continue_": @@ @@ $header = mb_substr($header, 5); } if ($header === '') { - continue; + break; } $filteredHeaders[$header] = $headerLine; }
}

$this->headers[$header] = $headerLine;
$filteredHeaders[$header] = $headerLine;
}

$this->filterHeaders();
}
$filtered = array_filter(
array: self::HEADERS,
callback: static fn (string $value): bool => array_key_exists(
mb_strtolower($value),
$filteredHeaders,
),
);

/**
* @return array<non-empty-string, non-empty-string>
*
* @throws void
*/
#[Override]
public function getHeaders(): array
{
return $this->headers;
foreach ($filtered as $header) {
try {
$headerObj = $this->headerLoader->load(
$header,
$filteredHeaders[mb_strtolower($header)],
);
} catch (NotFoundException) {
continue;
}

$this->headers[$header] = $headerObj;
}
}

/**
Expand All @@ -110,9 +118,9 @@
* @throws void
*/
#[Override]
public function getFilteredHeaders(): array
public function getHeaders(): array
{
return $this->filteredHeaders;
return $this->headers;
}

/** @throws void */
Expand All @@ -121,30 +129,10 @@
{
$data = [];

foreach ($this->filteredHeaders as $name => $header) {
foreach ($this->headers as $name => $header) {
$data[$name] = $header->getValue();
}

return sha1(serialize($data));
}

/** @throws void */
private function filterHeaders(): void
{
$headers = $this->headers;
$filtered = array_filter(
self::HEADERS,
static fn (string $value): bool => array_key_exists(mb_strtolower($value), $headers),
);

foreach ($filtered as $header) {
try {
$headerObj = $this->headerLoader->load($header, $headers[mb_strtolower($header)]);
} catch (NotFoundException) {
continue;
}

$this->filteredHeaders[$header] = $headerObj;
}
}
}
9 changes: 1 addition & 8 deletions src/GenericRequestInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,12 @@

interface GenericRequestInterface
{
/**
* @return array<non-empty-string, non-empty-string>
*
* @throws void
*/
public function getHeaders(): array;

/**
* @return array<non-empty-string, HeaderInterface>
*
* @throws void
*/
public function getFilteredHeaders(): array;
public function getHeaders(): array;

/** @throws void */
public function getHash(): string;
Expand Down
60 changes: 60 additions & 0 deletions src/Header/ClientHeader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

/**
* This file is part of the mimmi20/ua-generic-request package.
*
* Copyright (c) 2015-2025, Thomas Mueller <mimmi20@live.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types = 1);

namespace UaRequest\Header;

use Override;
use UaParser\ClientCodeInterface;
use UaParser\ClientVersionInterface;

final class ClientHeader implements HeaderInterface
{
use HeaderTrait;

/** @throws void */
public function __construct(
string $value,
private readonly ClientCodeInterface $clientCode,
private readonly ClientVersionInterface $clientVersion,
) {
$this->value = $value;
}

/** @throws void */
#[Override]
public function hasClientCode(): bool
{
return $this->clientCode->hasClientCode($this->value);
}

/** @throws void */
#[Override]
public function getClientCode(): string | null
{
return $this->clientCode->getClientCode($this->value);
}

/** @throws void */
#[Override]
public function hasClientVersion(): bool
{
return $this->clientVersion->hasClientVersion($this->value);
}

/** @throws void */
#[Override]
public function getClientVersion(string | null $code = null): string | null
{
return $this->clientVersion->getClientVersion($this->value, $code);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,14 @@
namespace UaRequest\Header;

use Override;
use UaParser\DeviceParserInterface;
use UaParser\DeviceCodeInterface;

use function preg_match;

final class BaiduFlyflow implements HeaderInterface
final class DeviceCodeOnlyHeader implements HeaderInterface
{
use HeaderTrait;

/** @throws void */
public function __construct(string $value, private readonly DeviceParserInterface $deviceParser)
public function __construct(string $value, private readonly DeviceCodeInterface $deviceCode)
{
$this->value = $value;
}
Expand All @@ -32,25 +30,13 @@ public function __construct(string $value, private readonly DeviceParserInterfac
#[Override]
public function hasDeviceCode(): bool
{
$hasMatch = preg_match('/;htc;htc;/i', $this->value);

return !$hasMatch;
return $this->deviceCode->hasDeviceCode($this->value);
}

/** @throws void */
#[Override]
public function getDeviceCode(): string | null
{
if (preg_match('/;htc;htc;/i', $this->value)) {
return null;
}

$code = $this->deviceParser->parse($this->value);

if ($code === '') {
return null;
}

return $code;
return $this->deviceCode->getDeviceCode($this->value);
}
}
Loading