mantis-matrix-integration – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 # PSR-7 Message Implementation
2  
3 This repository contains a full [PSR-7](https://www.php-fig.org/psr/psr-7/)
4 message implementation, several stream decorators, and some helpful
5 functionality like query string parsing.
6  
7 ![CI](https://github.com/guzzle/psr7/workflows/CI/badge.svg)
8 ![Static analysis](https://github.com/guzzle/psr7/workflows/Static%20analysis/badge.svg)
9  
10  
11 ## Features
12  
13 This package comes with a number of stream implementations and stream
14 decorators.
15  
16  
17 ## Installation
18  
19 ```shell
20 composer require guzzlehttp/psr7
21 ```
22  
23 ## Version Guidance
24  
25 | Version | Status | PHP Version |
26 |---------|---------------------|--------------|
27 | 1.x | EOL (2024-06-30) | >=5.4,<8.2 |
28 | 2.x | Latest | >=7.2.5,<8.5 |
29  
30  
31 ## AppendStream
32  
33 `GuzzleHttp\Psr7\AppendStream`
34  
35 Reads from multiple streams, one after the other.
36  
37 ```php
38 use GuzzleHttp\Psr7;
39  
40 $a = Psr7\Utils::streamFor('abc, ');
41 $b = Psr7\Utils::streamFor('123.');
42 $composed = new Psr7\AppendStream([$a, $b]);
43  
44 $composed->addStream(Psr7\Utils::streamFor(' Above all listen to me'));
45  
46 echo $composed; // abc, 123. Above all listen to me.
47 ```
48  
49  
50 ## BufferStream
51  
52 `GuzzleHttp\Psr7\BufferStream`
53  
54 Provides a buffer stream that can be written to fill a buffer, and read
55 from to remove bytes from the buffer.
56  
57 This stream returns a "hwm" metadata value that tells upstream consumers
58 what the configured high water mark of the stream is, or the maximum
59 preferred size of the buffer.
60  
61 ```php
62 use GuzzleHttp\Psr7;
63  
64 // When more than 1024 bytes are in the buffer, it will begin returning
65 // false to writes. This is an indication that writers should slow down.
66 $buffer = new Psr7\BufferStream(1024);
67 ```
68  
69  
70 ## CachingStream
71  
72 The CachingStream is used to allow seeking over previously read bytes on
73 non-seekable streams. This can be useful when transferring a non-seekable
74 entity body fails due to needing to rewind the stream (for example, resulting
75 from a redirect). Data that is read from the remote stream will be buffered in
76 a PHP temp stream so that previously read bytes are cached first in memory,
77 then on disk.
78  
79 ```php
80 use GuzzleHttp\Psr7;
81  
82 $original = Psr7\Utils::streamFor(fopen('http://www.google.com', 'r'));
83 $stream = new Psr7\CachingStream($original);
84  
85 $stream->read(1024);
86 echo $stream->tell();
87 // 1024
88  
89 $stream->seek(0);
90 echo $stream->tell();
91 // 0
92 ```
93  
94  
95 ## DroppingStream
96  
97 `GuzzleHttp\Psr7\DroppingStream`
98  
99 Stream decorator that begins dropping data once the size of the underlying
100 stream becomes too full.
101  
102 ```php
103 use GuzzleHttp\Psr7;
104  
105 // Create an empty stream
106 $stream = Psr7\Utils::streamFor();
107  
108 // Start dropping data when the stream has more than 10 bytes
109 $dropping = new Psr7\DroppingStream($stream, 10);
110  
111 $dropping->write('01234567890123456789');
112 echo $stream; // 0123456789
113 ```
114  
115  
116 ## FnStream
117  
118 `GuzzleHttp\Psr7\FnStream`
119  
120 Compose stream implementations based on a hash of functions.
121  
122 Allows for easy testing and extension of a provided stream without needing
123 to create a concrete class for a simple extension point.
124  
125 ```php
126  
127 use GuzzleHttp\Psr7;
128  
129 $stream = Psr7\Utils::streamFor('hi');
130 $fnStream = Psr7\FnStream::decorate($stream, [
131 'rewind' => function () use ($stream) {
132 echo 'About to rewind - ';
133 $stream->rewind();
134 echo 'rewound!';
135 }
136 ]);
137  
138 $fnStream->rewind();
139 // Outputs: About to rewind - rewound!
140 ```
141  
142  
143 ## InflateStream
144  
145 `GuzzleHttp\Psr7\InflateStream`
146  
147 Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content.
148  
149 This stream decorator converts the provided stream to a PHP stream resource,
150 then appends the zlib.inflate filter. The stream is then converted back
151 to a Guzzle stream resource to be used as a Guzzle stream.
152  
153  
154 ## LazyOpenStream
155  
156 `GuzzleHttp\Psr7\LazyOpenStream`
157  
158 Lazily reads or writes to a file that is opened only after an IO operation
159 take place on the stream.
160  
161 ```php
162 use GuzzleHttp\Psr7;
163  
164 $stream = new Psr7\LazyOpenStream('/path/to/file', 'r');
165 // The file has not yet been opened...
166  
167 echo $stream->read(10);
168 // The file is opened and read from only when needed.
169 ```
170  
171  
172 ## LimitStream
173  
174 `GuzzleHttp\Psr7\LimitStream`
175  
176 LimitStream can be used to read a subset or slice of an existing stream object.
177 This can be useful for breaking a large file into smaller pieces to be sent in
178 chunks (e.g. Amazon S3's multipart upload API).
179  
180 ```php
181 use GuzzleHttp\Psr7;
182  
183 $original = Psr7\Utils::streamFor(fopen('/tmp/test.txt', 'r+'));
184 echo $original->getSize();
185 // >>> 1048576
186  
187 // Limit the size of the body to 1024 bytes and start reading from byte 2048
188 $stream = new Psr7\LimitStream($original, 1024, 2048);
189 echo $stream->getSize();
190 // >>> 1024
191 echo $stream->tell();
192 // >>> 0
193 ```
194  
195  
196 ## MultipartStream
197  
198 `GuzzleHttp\Psr7\MultipartStream`
199  
200 Stream that when read returns bytes for a streaming multipart or
201 multipart/form-data stream.
202  
203  
204 ## NoSeekStream
205  
206 `GuzzleHttp\Psr7\NoSeekStream`
207  
208 NoSeekStream wraps a stream and does not allow seeking.
209  
210 ```php
211 use GuzzleHttp\Psr7;
212  
213 $original = Psr7\Utils::streamFor('foo');
214 $noSeek = new Psr7\NoSeekStream($original);
215  
216 echo $noSeek->read(3);
217 // foo
218 var_export($noSeek->isSeekable());
219 // false
220 $noSeek->seek(0);
221 var_export($noSeek->read(3));
222 // NULL
223 ```
224  
225  
226 ## PumpStream
227  
228 `GuzzleHttp\Psr7\PumpStream`
229  
230 Provides a read only stream that pumps data from a PHP callable.
231  
232 When invoking the provided callable, the PumpStream will pass the amount of
233 data requested to read to the callable. The callable can choose to ignore
234 this value and return fewer or more bytes than requested. Any extra data
235 returned by the provided callable is buffered internally until drained using
236 the read() function of the PumpStream. The provided callable MUST return
237 false when there is no more data to read.
238  
239  
240 ## Implementing stream decorators
241  
242 Creating a stream decorator is very easy thanks to the
243 `GuzzleHttp\Psr7\StreamDecoratorTrait`. This trait provides methods that
244 implement `Psr\Http\Message\StreamInterface` by proxying to an underlying
245 stream. Just `use` the `StreamDecoratorTrait` and implement your custom
246 methods.
247  
248 For example, let's say we wanted to call a specific function each time the last
249 byte is read from a stream. This could be implemented by overriding the
250 `read()` method.
251  
252 ```php
253 use Psr\Http\Message\StreamInterface;
254 use GuzzleHttp\Psr7\StreamDecoratorTrait;
255  
256 class EofCallbackStream implements StreamInterface
257 {
258 use StreamDecoratorTrait;
259  
260 private $callback;
261  
262 private $stream;
263  
264 public function __construct(StreamInterface $stream, callable $cb)
265 {
266 $this->stream = $stream;
267 $this->callback = $cb;
268 }
269  
270 public function read($length)
271 {
272 $result = $this->stream->read($length);
273  
274 // Invoke the callback when EOF is hit.
275 if ($this->eof()) {
276 ($this->callback)();
277 }
278  
279 return $result;
280 }
281 }
282 ```
283  
284 This decorator could be added to any existing stream and used like so:
285  
286 ```php
287 use GuzzleHttp\Psr7;
288  
289 $original = Psr7\Utils::streamFor('foo');
290  
291 $eofStream = new EofCallbackStream($original, function () {
292 echo 'EOF!';
293 });
294  
295 $eofStream->read(2);
296 $eofStream->read(1);
297 // echoes "EOF!"
298 $eofStream->seek(0);
299 $eofStream->read(3);
300 // echoes "EOF!"
301 ```
302  
303  
304 ## PHP StreamWrapper
305  
306 You can use the `GuzzleHttp\Psr7\StreamWrapper` class if you need to use a
307 PSR-7 stream as a PHP stream resource.
308  
309 Use the `GuzzleHttp\Psr7\StreamWrapper::getResource()` method to create a PHP
310 stream from a PSR-7 stream.
311  
312 ```php
313 use GuzzleHttp\Psr7\StreamWrapper;
314  
315 $stream = GuzzleHttp\Psr7\Utils::streamFor('hello!');
316 $resource = StreamWrapper::getResource($stream);
317 echo fread($resource, 6); // outputs hello!
318 ```
319  
320  
321 # Static API
322  
323 There are various static methods available under the `GuzzleHttp\Psr7` namespace.
324  
325  
326 ## `GuzzleHttp\Psr7\Message::toString`
327  
328 `public static function toString(MessageInterface $message): string`
329  
330 Returns the string representation of an HTTP message.
331  
332 ```php
333 $request = new GuzzleHttp\Psr7\Request('GET', 'http://example.com');
334 echo GuzzleHttp\Psr7\Message::toString($request);
335 ```
336  
337  
338 ## `GuzzleHttp\Psr7\Message::bodySummary`
339  
340 `public static function bodySummary(MessageInterface $message, int $truncateAt = 120): string|null`
341  
342 Get a short summary of the message body.
343  
344 Will return `null` if the response is not printable.
345  
346  
347 ## `GuzzleHttp\Psr7\Message::rewindBody`
348  
349 `public static function rewindBody(MessageInterface $message): void`
350  
351 Attempts to rewind a message body and throws an exception on failure.
352  
353 The body of the message will only be rewound if a call to `tell()`
354 returns a value other than `0`.
355  
356  
357 ## `GuzzleHttp\Psr7\Message::parseMessage`
358  
359 `public static function parseMessage(string $message): array`
360  
361 Parses an HTTP message into an associative array.
362  
363 The array contains the "start-line" key containing the start line of
364 the message, "headers" key containing an associative array of header
365 array values, and a "body" key containing the body of the message.
366  
367  
368 ## `GuzzleHttp\Psr7\Message::parseRequestUri`
369  
370 `public static function parseRequestUri(string $path, array $headers): string`
371  
372 Constructs a URI for an HTTP request message.
373  
374  
375 ## `GuzzleHttp\Psr7\Message::parseRequest`
376  
377 `public static function parseRequest(string $message): Request`
378  
379 Parses a request message string into a request object.
380  
381  
382 ## `GuzzleHttp\Psr7\Message::parseResponse`
383  
384 `public static function parseResponse(string $message): Response`
385  
386 Parses a response message string into a response object.
387  
388  
389 ## `GuzzleHttp\Psr7\Header::parse`
390  
391 `public static function parse(string|array $header): array`
392  
393 Parse an array of header values containing ";" separated data into an
394 array of associative arrays representing the header key value pair data
395 of the header. When a parameter does not contain a value, but just
396 contains a key, this function will inject a key with a '' string value.
397  
398  
399 ## `GuzzleHttp\Psr7\Header::splitList`
400  
401 `public static function splitList(string|string[] $header): string[]`
402  
403 Splits a HTTP header defined to contain a comma-separated list into
404 each individual value:
405  
406 ```
407 $knownEtags = Header::splitList($request->getHeader('if-none-match'));
408 ```
409  
410 Example headers include `accept`, `cache-control` and `if-none-match`.
411  
412  
413 ## `GuzzleHttp\Psr7\Header::normalize` (deprecated)
414  
415 `public static function normalize(string|array $header): array`
416  
417 `Header::normalize()` is deprecated in favor of [`Header::splitList()`](README.md#guzzlehttppsr7headersplitlist)
418 which performs the same operation with a cleaned up API and improved
419 documentation.
420  
421 Converts an array of header values that may contain comma separated
422 headers into an array of headers with no comma separated values.
423  
424  
425 ## `GuzzleHttp\Psr7\Query::parse`
426  
427 `public static function parse(string $str, int|bool $urlEncoding = true): array`
428  
429 Parse a query string into an associative array.
430  
431 If multiple values are found for the same key, the value of that key
432 value pair will become an array. This function does not parse nested
433 PHP style arrays into an associative array (e.g., `foo[a]=1&foo[b]=2`
434 will be parsed into `['foo[a]' => '1', 'foo[b]' => '2'])`.
435  
436  
437 ## `GuzzleHttp\Psr7\Query::build`
438  
439 `public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986, bool $treatBoolsAsInts = true): string`
440  
441 Build a query string from an array of key value pairs.
442  
443 This function can use the return value of `parse()` to build a query
444 string. This function does not modify the provided keys when an array is
445 encountered (like `http_build_query()` would).
446  
447  
448 ## `GuzzleHttp\Psr7\Utils::caselessRemove`
449  
450 `public static function caselessRemove(iterable<string> $keys, $keys, array $data): array`
451  
452 Remove the items given by the keys, case insensitively from the data.
453  
454  
455 ## `GuzzleHttp\Psr7\Utils::copyToStream`
456  
457 `public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void`
458  
459 Copy the contents of a stream into another stream until the given number
460 of bytes have been read.
461  
462  
463 ## `GuzzleHttp\Psr7\Utils::copyToString`
464  
465 `public static function copyToString(StreamInterface $stream, int $maxLen = -1): string`
466  
467 Copy the contents of a stream into a string until the given number of
468 bytes have been read.
469  
470  
471 ## `GuzzleHttp\Psr7\Utils::hash`
472  
473 `public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string`
474  
475 Calculate a hash of a stream.
476  
477 This method reads the entire stream to calculate a rolling hash, based on
478 PHP's `hash_init` functions.
479  
480  
481 ## `GuzzleHttp\Psr7\Utils::modifyRequest`
482  
483 `public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface`
484  
485 Clone and modify a request with the given changes.
486  
487 This method is useful for reducing the number of clones needed to mutate
488 a message.
489  
490 - method: (string) Changes the HTTP method.
491 - set_headers: (array) Sets the given headers.
492 - remove_headers: (array) Remove the given headers.
493 - body: (mixed) Sets the given body.
494 - uri: (UriInterface) Set the URI.
495 - query: (string) Set the query string value of the URI.
496 - version: (string) Set the protocol version.
497  
498  
499 ## `GuzzleHttp\Psr7\Utils::readLine`
500  
501 `public static function readLine(StreamInterface $stream, ?int $maxLength = null): string`
502  
503 Read a line from the stream up to the maximum allowed buffer length.
504  
505  
506 ## `GuzzleHttp\Psr7\Utils::redactUserInfo`
507  
508 `public static function redactUserInfo(UriInterface $uri): UriInterface`
509  
510 Redact the password in the user info part of a URI.
511  
512  
513 ## `GuzzleHttp\Psr7\Utils::streamFor`
514  
515 `public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource = '', array $options = []): StreamInterface`
516  
517 Create a new stream based on the input type.
518  
519 Options is an associative array that can contain the following keys:
520  
521 - metadata: Array of custom metadata.
522 - size: Size of the stream.
523  
524 This method accepts the following `$resource` types:
525  
526 - `Psr\Http\Message\StreamInterface`: Returns the value as-is.
527 - `string`: Creates a stream object that uses the given string as the contents.
528 - `resource`: Creates a stream object that wraps the given PHP stream resource.
529 - `Iterator`: If the provided value implements `Iterator`, then a read-only
530 stream object will be created that wraps the given iterable. Each time the
531 stream is read from, data from the iterator will fill a buffer and will be
532 continuously called until the buffer is equal to the requested read size.
533 Subsequent read calls will first read from the buffer and then call `next`
534 on the underlying iterator until it is exhausted.
535 - `object` with `__toString()`: If the object has the `__toString()` method,
536 the object will be cast to a string and then a stream will be returned that
537 uses the string value.
538 - `NULL`: When `null` is passed, an empty stream object is returned.
539 - `callable` When a callable is passed, a read-only stream object will be
540 created that invokes the given callable. The callable is invoked with the
541 number of suggested bytes to read. The callable can return any number of
542 bytes, but MUST return `false` when there is no more data to return. The
543 stream object that wraps the callable will invoke the callable until the
544 number of requested bytes are available. Any additional bytes will be
545 buffered and used in subsequent reads.
546  
547 ```php
548 $stream = GuzzleHttp\Psr7\Utils::streamFor('foo');
549 $stream = GuzzleHttp\Psr7\Utils::streamFor(fopen('/path/to/file', 'r'));
550  
551 $generator = function ($bytes) {
552 for ($i = 0; $i < $bytes; $i++) {
553 yield ' ';
554 }
555 }
556  
557 $stream = GuzzleHttp\Psr7\Utils::streamFor($generator(100));
558 ```
559  
560  
561 ## `GuzzleHttp\Psr7\Utils::tryFopen`
562  
563 `public static function tryFopen(string $filename, string $mode): resource`
564  
565 Safely opens a PHP stream resource using a filename.
566  
567 When fopen fails, PHP normally raises a warning. This function adds an
568 error handler that checks for errors and throws an exception instead.
569  
570  
571 ## `GuzzleHttp\Psr7\Utils::tryGetContents`
572  
573 `public static function tryGetContents(resource $stream): string`
574  
575 Safely gets the contents of a given stream.
576  
577 When stream_get_contents fails, PHP normally raises a warning. This
578 function adds an error handler that checks for errors and throws an
579 exception instead.
580  
581  
582 ## `GuzzleHttp\Psr7\Utils::uriFor`
583  
584 `public static function uriFor(string|UriInterface $uri): UriInterface`
585  
586 Returns a UriInterface for the given value.
587  
588 This function accepts a string or UriInterface and returns a
589 UriInterface for the given value. If the value is already a
590 UriInterface, it is returned as-is.
591  
592  
593 ## `GuzzleHttp\Psr7\MimeType::fromFilename`
594  
595 `public static function fromFilename(string $filename): string|null`
596  
597 Determines the mimetype of a file by looking at its extension.
598  
599  
600 ## `GuzzleHttp\Psr7\MimeType::fromExtension`
601  
602 `public static function fromExtension(string $extension): string|null`
603  
604 Maps a file extensions to a mimetype.
605  
606  
607 ## Upgrading from Function API
608  
609 The static API was first introduced in 1.7.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API was removed in 2.0.0. A migration table has been provided here for your convenience:
610  
611 | Original Function | Replacement Method |
612 |----------------|----------------|
613 | `str` | `Message::toString` |
614 | `uri_for` | `Utils::uriFor` |
615 | `stream_for` | `Utils::streamFor` |
616 | `parse_header` | `Header::parse` |
617 | `normalize_header` | `Header::normalize` |
618 | `modify_request` | `Utils::modifyRequest` |
619 | `rewind_body` | `Message::rewindBody` |
620 | `try_fopen` | `Utils::tryFopen` |
621 | `copy_to_string` | `Utils::copyToString` |
622 | `copy_to_stream` | `Utils::copyToStream` |
623 | `hash` | `Utils::hash` |
624 | `readline` | `Utils::readLine` |
625 | `parse_request` | `Message::parseRequest` |
626 | `parse_response` | `Message::parseResponse` |
627 | `parse_query` | `Query::parse` |
628 | `build_query` | `Query::build` |
629 | `mimetype_from_filename` | `MimeType::fromFilename` |
630 | `mimetype_from_extension` | `MimeType::fromExtension` |
631 | `_parse_message` | `Message::parseMessage` |
632 | `_parse_request_uri` | `Message::parseRequestUri` |
633 | `get_message_body_summary` | `Message::bodySummary` |
634 | `_caseless_remove` | `Utils::caselessRemove` |
635  
636  
637 # Additional URI Methods
638  
639 Aside from the standard `Psr\Http\Message\UriInterface` implementation in form of the `GuzzleHttp\Psr7\Uri` class,
640 this library also provides additional functionality when working with URIs as static methods.
641  
642 ## URI Types
643  
644 An instance of `Psr\Http\Message\UriInterface` can either be an absolute URI or a relative reference.
645 An absolute URI has a scheme. A relative reference is used to express a URI relative to another URI,
646 the base URI. Relative references can be divided into several forms according to
647 [RFC 3986 Section 4.2](https://datatracker.ietf.org/doc/html/rfc3986#section-4.2):
648  
649 - network-path references, e.g. `//example.com/path`
650 - absolute-path references, e.g. `/path`
651 - relative-path references, e.g. `subpath`
652  
653 The following methods can be used to identify the type of the URI.
654  
655 ### `GuzzleHttp\Psr7\Uri::isAbsolute`
656  
657 `public static function isAbsolute(UriInterface $uri): bool`
658  
659 Whether the URI is absolute, i.e. it has a scheme.
660  
661 ### `GuzzleHttp\Psr7\Uri::isNetworkPathReference`
662  
663 `public static function isNetworkPathReference(UriInterface $uri): bool`
664  
665 Whether the URI is a network-path reference. A relative reference that begins with two slash characters is
666 termed an network-path reference.
667  
668 ### `GuzzleHttp\Psr7\Uri::isAbsolutePathReference`
669  
670 `public static function isAbsolutePathReference(UriInterface $uri): bool`
671  
672 Whether the URI is a absolute-path reference. A relative reference that begins with a single slash character is
673 termed an absolute-path reference.
674  
675 ### `GuzzleHttp\Psr7\Uri::isRelativePathReference`
676  
677 `public static function isRelativePathReference(UriInterface $uri): bool`
678  
679 Whether the URI is a relative-path reference. A relative reference that does not begin with a slash character is
680 termed a relative-path reference.
681  
682 ### `GuzzleHttp\Psr7\Uri::isSameDocumentReference`
683  
684 `public static function isSameDocumentReference(UriInterface $uri, ?UriInterface $base = null): bool`
685  
686 Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its
687 fragment component, identical to the base URI. When no base URI is given, only an empty URI reference
688 (apart from its fragment) is considered a same-document reference.
689  
690 ## URI Components
691  
692 Additional methods to work with URI components.
693  
694 ### `GuzzleHttp\Psr7\Uri::isDefaultPort`
695  
696 `public static function isDefaultPort(UriInterface $uri): bool`
697  
698 Whether the URI has the default port of the current scheme. `Psr\Http\Message\UriInterface::getPort` may return null
699 or the standard port. This method can be used independently of the implementation.
700  
701 ### `GuzzleHttp\Psr7\Uri::composeComponents`
702  
703 `public static function composeComponents($scheme, $authority, $path, $query, $fragment): string`
704  
705 Composes a URI reference string from its various components according to
706 [RFC 3986 Section 5.3](https://datatracker.ietf.org/doc/html/rfc3986#section-5.3). Usually this method does not need
707 to be called manually but instead is used indirectly via `Psr\Http\Message\UriInterface::__toString`.
708  
709 ### `GuzzleHttp\Psr7\Uri::fromParts`
710  
711 `public static function fromParts(array $parts): UriInterface`
712  
713 Creates a URI from a hash of [`parse_url`](https://www.php.net/manual/en/function.parse-url.php) components.
714  
715  
716 ### `GuzzleHttp\Psr7\Uri::withQueryValue`
717  
718 `public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface`
719  
720 Creates a new URI with a specific query string value. Any existing query string values that exactly match the
721 provided key are removed and replaced with the given key value pair. A value of null will set the query string
722 key without a value, e.g. "key" instead of "key=value".
723  
724 ### `GuzzleHttp\Psr7\Uri::withQueryValues`
725  
726 `public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface`
727  
728 Creates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an
729 associative array of key => value.
730  
731 ### `GuzzleHttp\Psr7\Uri::withoutQueryValue`
732  
733 `public static function withoutQueryValue(UriInterface $uri, $key): UriInterface`
734  
735 Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the
736 provided key are removed.
737  
738 ## Cross-Origin Detection
739  
740 `GuzzleHttp\Psr7\UriComparator` provides methods to determine if a modified URL should be considered cross-origin.
741  
742 ### `GuzzleHttp\Psr7\UriComparator::isCrossOrigin`
743  
744 `public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool`
745  
746 Determines if a modified URL should be considered cross-origin with respect to an original URL.
747  
748 ## Reference Resolution
749  
750 `GuzzleHttp\Psr7\UriResolver` provides methods to resolve a URI reference in the context of a base URI according
751 to [RFC 3986 Section 5](https://datatracker.ietf.org/doc/html/rfc3986#section-5). This is for example also what web
752 browsers do when resolving a link in a website based on the current request URI.
753  
754 ### `GuzzleHttp\Psr7\UriResolver::resolve`
755  
756 `public static function resolve(UriInterface $base, UriInterface $rel): UriInterface`
757  
758 Converts the relative URI into a new URI that is resolved against the base URI.
759  
760 ### `GuzzleHttp\Psr7\UriResolver::removeDotSegments`
761  
762 `public static function removeDotSegments(string $path): string`
763  
764 Removes dot segments from a path and returns the new path according to
765 [RFC 3986 Section 5.2.4](https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.4).
766  
767 ### `GuzzleHttp\Psr7\UriResolver::relativize`
768  
769 `public static function relativize(UriInterface $base, UriInterface $target): UriInterface`
770  
771 Returns the target URI as a relative reference from the base URI. This method is the counterpart to resolve():
772  
773 ```php
774 (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))
775 ```
776  
777 One use-case is to use the current request URI as base URI and then generate relative links in your documents
778 to reduce the document size or offer self-contained downloadable document archives.
779  
780 ```php
781 $base = new Uri('http://example.com/a/b/');
782 echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'.
783 echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'.
784 echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
785 echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'.
786 ```
787  
788 ## Normalization and Comparison
789  
790 `GuzzleHttp\Psr7\UriNormalizer` provides methods to normalize and compare URIs according to
791 [RFC 3986 Section 6](https://datatracker.ietf.org/doc/html/rfc3986#section-6).
792  
793 ### `GuzzleHttp\Psr7\UriNormalizer::normalize`
794  
795 `public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS): UriInterface`
796  
797 Returns a normalized URI. The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
798 This methods adds additional normalizations that can be configured with the `$flags` parameter which is a bitmask
799 of normalizations to apply. The following normalizations are available:
800  
801 - `UriNormalizer::PRESERVING_NORMALIZATIONS`
802  
803 Default normalizations which only include the ones that preserve semantics.
804  
805 - `UriNormalizer::CAPITALIZE_PERCENT_ENCODING`
806  
807 All letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
808  
809 Example: `http://example.org/a%c2%b1b` → `http://example.org/a%C2%B1b`
810  
811 - `UriNormalizer::DECODE_UNRESERVED_CHARACTERS`
812  
813 Decodes percent-encoded octets of unreserved characters. For consistency, percent-encoded octets in the ranges of
814 ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should
815 not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved
816 characters by URI normalizers.
817  
818 Example: `http://example.org/%7Eusern%61me/` → `http://example.org/~username/`
819  
820 - `UriNormalizer::CONVERT_EMPTY_PATH`
821  
822 Converts the empty path to "/" for http and https URIs.
823  
824 Example: `http://example.org` → `http://example.org/`
825  
826 - `UriNormalizer::REMOVE_DEFAULT_HOST`
827  
828 Removes the default host of the given URI scheme from the URI. Only the "file" scheme defines the default host
829 "localhost". All of `file:/myfile`, `file:///myfile`, and `file://localhost/myfile` are equivalent according to
830 RFC 3986.
831  
832 Example: `file://localhost/myfile` → `file:///myfile`
833  
834 - `UriNormalizer::REMOVE_DEFAULT_PORT`
835  
836 Removes the default port of the given URI scheme from the URI.
837  
838 Example: `http://example.org:80/` → `http://example.org/`
839  
840 - `UriNormalizer::REMOVE_DOT_SEGMENTS`
841  
842 Removes unnecessary dot-segments. Dot-segments in relative-path references are not removed as it would
843 change the semantics of the URI reference.
844  
845 Example: `http://example.org/../a/b/../c/./d.html` → `http://example.org/a/c/d.html`
846  
847 - `UriNormalizer::REMOVE_DUPLICATE_SLASHES`
848  
849 Paths which include two or more adjacent slashes are converted to one. Webservers usually ignore duplicate slashes
850 and treat those URIs equivalent. But in theory those URIs do not need to be equivalent. So this normalization
851 may change the semantics. Encoded slashes (%2F) are not removed.
852  
853 Example: `http://example.org//foo///bar.html` → `http://example.org/foo/bar.html`
854  
855 - `UriNormalizer::SORT_QUERY_PARAMETERS`
856  
857 Sort query parameters with their values in alphabetical order. However, the order of parameters in a URI may be
858 significant (this is not defined by the standard). So this normalization is not safe and may change the semantics
859 of the URI.
860  
861 Example: `?lang=en&article=fred` → `?article=fred&lang=en`
862  
863 ### `GuzzleHttp\Psr7\UriNormalizer::isEquivalent`
864  
865 `public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS): bool`
866  
867 Whether two URIs can be considered equivalent. Both URIs are normalized automatically before comparison with the given
868 `$normalizations` bitmask. The method also accepts relative URI references and returns true when they are equivalent.
869 This of course assumes they will be resolved against the same base URI. If this is not the case, determination of
870 equivalence or difference of relative references does not mean anything.
871  
872  
873 ## Security
874  
875 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.
876  
877  
878 ## License
879  
880 Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information.
881  
882  
883 ## For Enterprise
884  
885 Available as part of the Tidelift Subscription
886  
887 The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-psr7?utm_source=packagist-guzzlehttp-psr7&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)