1<?php
2namespace Ratchet\Http;
3use Ratchet\MessageInterface;
4use Ratchet\ConnectionInterface;
5use GuzzleHttp\Psr7 as gPsr;
6
7/**
8 * This class receives streaming data from a client request
9 * and parses HTTP headers, returning a PSR-7 Request object
10 * once it's been buffered
11 */
12class HttpRequestParser implements MessageInterface {
13    const EOM = "\r\n\r\n";
14
15    /**
16     * The maximum number of bytes the request can be
17     * This is a security measure to prevent attacks
18     * @var int
19     */
20    public $maxSize = 4096;
21
22    /**
23     * @param \Ratchet\ConnectionInterface $context
24     * @param string                       $data Data stream to buffer
25     * @return \Psr\Http\Message\RequestInterface
26     * @throws \OverflowException If the message buffer has become too large
27     */
28    public function onMessage(ConnectionInterface $context, $data) {
29        if (!isset($context->httpBuffer)) {
30            $context->httpBuffer = '';
31        }
32
33        $context->httpBuffer .= $data;
34
35        if (strlen($context->httpBuffer) > (int)$this->maxSize) {
36            throw new \OverflowException("Maximum buffer size of {$this->maxSize} exceeded parsing HTTP header");
37        }
38
39        if ($this->isEom($context->httpBuffer)) {
40            $request = $this->parse($context->httpBuffer);
41
42            unset($context->httpBuffer);
43
44            return $request;
45        }
46    }
47
48    /**
49     * Determine if the message has been buffered as per the HTTP specification
50     * @param  string  $message
51     * @return boolean
52     */
53    public function isEom($message) {
54        return (boolean)strpos($message, static::EOM);
55    }
56
57    /**
58     * @param string $headers
59     * @return \Psr\Http\Message\RequestInterface
60     */
61    public function parse($headers) {
62        return gPsr\parse_request($headers);
63    }
64}
65