Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: guzzle/psr7
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.8.3
Choose a base ref
...
head repository: guzzle/psr7
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1.9.1
Choose a head ref
  • 8 commits
  • 11 files changed
  • 3 contributors

Commits on Mar 20, 2022

  1. Release 1.8.4 (#486)

    Co-authored-by: Tim Düsterhus <[email protected]>
    GrahamCampbell and TimWolla authored Mar 20, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    902db15 View commit details
  2. Release 1.8.5 (#491)

    GrahamCampbell authored Mar 20, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    337e3ad View commit details

Commits on Jun 20, 2022

  1. Release 1.9.0 (#520)

    GrahamCampbell authored Jun 20, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e98e3e6 View commit details

Commits on Apr 8, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7cd3009 View commit details

Commits on Apr 17, 2023

  1. Remove branch alias

    GrahamCampbell authored Apr 17, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0e75375 View commit details
  2. Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    GrahamCampbell Graham Campbell
    Copy the full SHA
    18fd891 View commit details
  3. Release 1.9.1

    GrahamCampbell committed Apr 17, 2023

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    GrahamCampbell Graham Campbell
    Copy the full SHA
    c8b21de View commit details
  4. Release 1.9.1

    GrahamCampbell authored Apr 17, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e4490ca View commit details
Showing with 291 additions and 27 deletions.
  1. +2 −6 .github/workflows/ci.yml
  2. +3 −4 .github/workflows/integration.yml
  3. +2 −2 .github/workflows/static.yml
  4. +26 −2 CHANGELOG.md
  5. +22 −2 README.md
  6. +4 −6 composer.json
  7. +60 −5 src/MessageTrait.php
  8. +55 −0 src/UriComparator.php
  9. +66 −0 tests/RequestTest.php
  10. +9 −0 tests/ResponseTest.php
  11. +42 −0 tests/UriComparatorTest.php
8 changes: 2 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ on:
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
strategy:
max-parallel: 10
matrix:
@@ -21,11 +21,7 @@ jobs:
extensions: mbstring

- name: Checkout code
uses: actions/checkout@v2

- name: Mimic PHP 8.0
run: composer config platform.php 8.0.999
if: matrix.php > 8
uses: actions/checkout@v3

- name: Install dependencies
run: composer update --no-interaction --no-progress
7 changes: 3 additions & 4 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -4,14 +4,13 @@ on:
pull_request:

jobs:

build:
name: Test
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
strategy:
max-parallel: 10
matrix:
php: ['7.2', '7.3', '7.4', '8.0']
php: ['7.2', '7.3', '7.4', '8.0', '8.1']

steps:
- name: Set up PHP
@@ -21,7 +20,7 @@ jobs:
coverage: none

- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Download dependencies
uses: ramsey/composer-install@v1
4 changes: 2 additions & 2 deletions .github/workflows/static.yml
Original file line number Diff line number Diff line change
@@ -6,11 +6,11 @@ on:
jobs:
php-cs-fixer:
name: PHP-CS-Fixer
runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Setup PHP
uses: shivammathur/setup-php@v2
28 changes: 26 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -3,12 +3,36 @@

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## Unreleased

## 1.9.1 - 2023-04-17

### Fixed

- Fixed header validation issue

## 1.9.0 - 2022-06-20

### Added

- Added `UriComparator::isCrossOrigin` method

## 1.8.5 - 2022-03-20

### Fixed

- Correct header value validation

## 1.8.4 - 2022-03-20

### Fixed

- Validate header values properly

## 1.8.3 - 2021-10-05

### Fixed
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PSR-7 Message Implementation

This repository contains a full [PSR-7](http://www.php-fig.org/psr/psr-7/)
This repository contains a full [PSR-7](https://www.php-fig.org/psr/psr-7/)
message implementation, several stream decorators, and some helpful
functionality like query string parsing.

@@ -659,7 +659,7 @@ manually but instead is used indirectly via `Psr\Http\Message\UriInterface::__to

`public static function fromParts(array $parts): UriInterface`

Creates a URI from a hash of [`parse_url`](http://php.net/manual/en/function.parse-url.php) components.
Creates a URI from a hash of [`parse_url`](https://www.php.net/manual/en/function.parse-url.php) components.


### `GuzzleHttp\Psr7\Uri::withQueryValue`
@@ -684,6 +684,16 @@ associative array of key => value.
Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the
provided key are removed.

## Cross-Origin Detection

`GuzzleHttp\Psr7\UriComparator` provides methods to determine if a modified URL should be considered cross-origin.

### `GuzzleHttp\Psr7\UriComparator::isCrossOrigin`

`public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool`

Determines if a modified URL should be considered cross-origin with respect to an original URL.

## Reference Resolution

`GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according
@@ -809,14 +819,24 @@ This of course assumes they will be resolved against the same base URI. If this
equivalence or difference of relative references does not mean anything.


## Version Guidance

| Version | Status | PHP Version |
|---------|----------------|------------------|
| 1.x | Security fixes | >=5.4,<8.1 |
| 2.x | Latest | ^7.2.5 \|\| ^8.0 |


## Security

If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/psr7/security/policy) for more information.


## License

Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information.


## For Enterprise

Available as part of the Tidelift Subscription
10 changes: 4 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
@@ -61,13 +61,11 @@
"GuzzleHttp\\Tests\\Psr7\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.7-dev"
}
},
"config": {
"preferred-install": "dist",
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"bamarni/composer-bin-plugin": true
}
}
}
65 changes: 60 additions & 5 deletions src/MessageTrait.php
Original file line number Diff line number Diff line change
@@ -157,17 +157,22 @@ private function setHeaders(array $headers)
}
}

/**
* @param mixed $value
*
* @return string[]
*/
private function normalizeHeaderValue($value)
{
if (!is_array($value)) {
return $this->trimHeaderValues([$value]);
return $this->trimAndValidateHeaderValues([$value]);
}

if (count($value) === 0) {
throw new \InvalidArgumentException('Header value can not be an empty array.');
}

return $this->trimHeaderValues($value);
return $this->trimAndValidateHeaderValues($value);
}

/**
@@ -178,13 +183,13 @@ private function normalizeHeaderValue($value)
* header-field = field-name ":" OWS field-value OWS
* OWS = *( SP / HTAB )
*
* @param string[] $values Header values
* @param mixed[] $values Header values
*
* @return string[] Trimmed header values
*
* @see https://tools.ietf.org/html/rfc7230#section-3.2.4
*/
private function trimHeaderValues(array $values)
private function trimAndValidateHeaderValues(array $values)
{
return array_map(function ($value) {
if (!is_scalar($value) && null !== $value) {
@@ -194,10 +199,20 @@ private function trimHeaderValues(array $values)
));
}

return trim((string) $value, " \t");
$trimmed = trim((string) $value, " \t");
$this->assertValue($trimmed);

return $trimmed;
}, array_values($values));
}

/**
* @see https://tools.ietf.org/html/rfc7230#section-3.2
*
* @param mixed $header
*
* @return void
*/
private function assertHeader($header)
{
if (!is_string($header)) {
@@ -210,5 +225,45 @@ private function assertHeader($header)
if ($header === '') {
throw new \InvalidArgumentException('Header name can not be empty.');
}

if (! preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) {
throw new \InvalidArgumentException(
sprintf('"%s" is not valid header name.', $header)
);
}
}

/**
* @param string $value
*
* @return void
*
* @see https://tools.ietf.org/html/rfc7230#section-3.2
*
* field-value = *( field-content / obs-fold )
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
* field-vchar = VCHAR / obs-text
* VCHAR = %x21-7E
* obs-text = %x80-FF
* obs-fold = CRLF 1*( SP / HTAB )
*/
private function assertValue($value)
{
// The regular expression intentionally does not support the obs-fold production, because as
// per RFC 7230#3.2.4:
//
// A sender MUST NOT generate a message that includes
// line folding (i.e., that has any field-value that contains a match to
// the obs-fold rule) unless the message is intended for packaging
// within the message/http media type.
//
// Clients must not send a request with line folding and a server sending folded headers is
// likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting
// folding is not likely to break any legitimate use case.
if (! preg_match('/^[\x20\x09\x21-\x7E\x80-\xFF]*$/D', $value)) {
throw new \InvalidArgumentException(
sprintf('"%s" is not valid header value.', $value)
);
}
}
}
55 changes: 55 additions & 0 deletions src/UriComparator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace GuzzleHttp\Psr7;

use Psr\Http\Message\UriInterface;

/**
* Provides methods to determine if a modified URL should be considered cross-origin.
*
* @author Graham Campbell
*/
final class UriComparator
{
/**
* Determines if a modified URL should be considered cross-origin with
* respect to an original URL.
*
* @return bool
*/
public static function isCrossOrigin(UriInterface $original, UriInterface $modified)
{
if (\strcasecmp($original->getHost(), $modified->getHost()) !== 0) {
return true;
}

if ($original->getScheme() !== $modified->getScheme()) {
return true;
}

if (self::computePort($original) !== self::computePort($modified)) {
return true;
}

return false;
}

/**
* @return int
*/
private static function computePort(UriInterface $uri)
{
$port = $uri->getPort();

if (null !== $port) {
return $port;
}

return 'https' === $uri->getScheme() ? 443 : 80;
}

private function __construct()
{
// cannot be instantiated
}
}
Loading