annotate vendor/zendframework/zend-diactoros/src/Request/Serializer.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents c2387f117808
children
rev   line source
Chris@0 1 <?php
Chris@0 2 /**
Chris@0 3 * Zend Framework (http://framework.zend.com/)
Chris@0 4 *
Chris@0 5 * @see http://github.com/zendframework/zend-diactoros for the canonical source repository
Chris@0 6 * @copyright Copyright (c) 2015-2016 Zend Technologies USA Inc. (http://www.zend.com)
Chris@0 7 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
Chris@0 8 */
Chris@0 9
Chris@0 10 namespace Zend\Diactoros\Request;
Chris@0 11
Chris@0 12 use InvalidArgumentException;
Chris@0 13 use Psr\Http\Message\RequestInterface;
Chris@0 14 use Psr\Http\Message\StreamInterface;
Chris@0 15 use UnexpectedValueException;
Chris@0 16 use Zend\Diactoros\AbstractSerializer;
Chris@0 17 use Zend\Diactoros\Request;
Chris@0 18 use Zend\Diactoros\Stream;
Chris@0 19 use Zend\Diactoros\Uri;
Chris@0 20
Chris@16 21 use function preg_match;
Chris@16 22 use function sprintf;
Chris@16 23
Chris@0 24 /**
Chris@0 25 * Serialize (cast to string) or deserialize (cast string to Request) messages.
Chris@0 26 *
Chris@0 27 * This class provides functionality for serializing a RequestInterface instance
Chris@0 28 * to a string, as well as the reverse operation of creating a Request instance
Chris@0 29 * from a string/stream representing a message.
Chris@0 30 */
Chris@0 31 final class Serializer extends AbstractSerializer
Chris@0 32 {
Chris@0 33 /**
Chris@0 34 * Deserialize a request string to a request instance.
Chris@0 35 *
Chris@0 36 * Internally, casts the message to a stream and invokes fromStream().
Chris@0 37 *
Chris@0 38 * @param string $message
Chris@0 39 * @return Request
Chris@0 40 * @throws UnexpectedValueException when errors occur parsing the message.
Chris@0 41 */
Chris@0 42 public static function fromString($message)
Chris@0 43 {
Chris@0 44 $stream = new Stream('php://temp', 'wb+');
Chris@0 45 $stream->write($message);
Chris@0 46 return self::fromStream($stream);
Chris@0 47 }
Chris@0 48
Chris@0 49 /**
Chris@0 50 * Deserialize a request stream to a request instance.
Chris@0 51 *
Chris@0 52 * @param StreamInterface $stream
Chris@0 53 * @return Request
Chris@0 54 * @throws UnexpectedValueException when errors occur parsing the message.
Chris@0 55 */
Chris@0 56 public static function fromStream(StreamInterface $stream)
Chris@0 57 {
Chris@0 58 if (! $stream->isReadable() || ! $stream->isSeekable()) {
Chris@0 59 throw new InvalidArgumentException('Message stream must be both readable and seekable');
Chris@0 60 }
Chris@0 61
Chris@0 62 $stream->rewind();
Chris@0 63
Chris@0 64 list($method, $requestTarget, $version) = self::getRequestLine($stream);
Chris@0 65 $uri = self::createUriFromRequestTarget($requestTarget);
Chris@0 66
Chris@0 67 list($headers, $body) = self::splitStream($stream);
Chris@0 68
Chris@0 69 return (new Request($uri, $method, $body, $headers))
Chris@0 70 ->withProtocolVersion($version)
Chris@0 71 ->withRequestTarget($requestTarget);
Chris@0 72 }
Chris@0 73
Chris@0 74 /**
Chris@0 75 * Serialize a request message to a string.
Chris@0 76 *
Chris@0 77 * @param RequestInterface $request
Chris@0 78 * @return string
Chris@0 79 */
Chris@0 80 public static function toString(RequestInterface $request)
Chris@0 81 {
Chris@0 82 $httpMethod = $request->getMethod();
Chris@0 83 if (empty($httpMethod)) {
Chris@0 84 throw new UnexpectedValueException('Object can not be serialized because HTTP method is empty');
Chris@0 85 }
Chris@0 86 $headers = self::serializeHeaders($request->getHeaders());
Chris@0 87 $body = (string) $request->getBody();
Chris@0 88 $format = '%s %s HTTP/%s%s%s';
Chris@0 89
Chris@0 90 if (! empty($headers)) {
Chris@0 91 $headers = "\r\n" . $headers;
Chris@0 92 }
Chris@0 93 if (! empty($body)) {
Chris@0 94 $headers .= "\r\n\r\n";
Chris@0 95 }
Chris@0 96
Chris@0 97 return sprintf(
Chris@0 98 $format,
Chris@0 99 $httpMethod,
Chris@0 100 $request->getRequestTarget(),
Chris@0 101 $request->getProtocolVersion(),
Chris@0 102 $headers,
Chris@0 103 $body
Chris@0 104 );
Chris@0 105 }
Chris@0 106
Chris@0 107 /**
Chris@0 108 * Retrieve the components of the request line.
Chris@0 109 *
Chris@0 110 * Retrieves the first line of the stream and parses it, raising an
Chris@0 111 * exception if it does not follow specifications; if valid, returns a list
Chris@0 112 * with the method, target, and version, in that order.
Chris@0 113 *
Chris@0 114 * @param StreamInterface $stream
Chris@0 115 * @return array
Chris@0 116 */
Chris@0 117 private static function getRequestLine(StreamInterface $stream)
Chris@0 118 {
Chris@0 119 $requestLine = self::getLine($stream);
Chris@0 120
Chris@0 121 if (! preg_match(
Chris@0 122 '#^(?P<method>[!\#$%&\'*+.^_`|~a-zA-Z0-9-]+) (?P<target>[^\s]+) HTTP/(?P<version>[1-9]\d*\.\d+)$#',
Chris@0 123 $requestLine,
Chris@0 124 $matches
Chris@0 125 )) {
Chris@0 126 throw new UnexpectedValueException('Invalid request line detected');
Chris@0 127 }
Chris@0 128
Chris@0 129 return [$matches['method'], $matches['target'], $matches['version']];
Chris@0 130 }
Chris@0 131
Chris@0 132 /**
Chris@0 133 * Create and return a Uri instance based on the provided request target.
Chris@0 134 *
Chris@0 135 * If the request target is of authority or asterisk form, an empty Uri
Chris@0 136 * instance is returned; otherwise, the value is used to create and return
Chris@0 137 * a new Uri instance.
Chris@0 138 *
Chris@0 139 * @param string $requestTarget
Chris@0 140 * @return Uri
Chris@0 141 */
Chris@0 142 private static function createUriFromRequestTarget($requestTarget)
Chris@0 143 {
Chris@0 144 if (preg_match('#^https?://#', $requestTarget)) {
Chris@0 145 return new Uri($requestTarget);
Chris@0 146 }
Chris@0 147
Chris@0 148 if (preg_match('#^(\*|[^/])#', $requestTarget)) {
Chris@0 149 return new Uri();
Chris@0 150 }
Chris@0 151
Chris@0 152 return new Uri($requestTarget);
Chris@0 153 }
Chris@0 154 }