• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sirn-se / websocket-php / 12595823711

03 Jan 2025 09:47AM UTC coverage: 99.904% (-0.1%) from 100.0%
12595823711

Pull #89

github

web-flow
Merge 7c98205c6 into d4081f0e4
Pull Request #89: Handle invalid server requests

8 of 9 new or added lines in 1 file covered. (88.89%)

1043 of 1044 relevant lines covered (99.9%)

22.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.3
/src/Http/HttpHandler.php
1
<?php
2

3
/**
4
 * Copyright (C) 2014-2024 Textalk and contributors.
5
 * This file is part of Websocket PHP and is free software under the ISC License.
6
 */
7

8
namespace WebSocket\Http;
9

10
use Phrity\Net\{
11
    SocketStream,
12
    Uri
13
};
14
use Psr\Http\Message\MessageInterface;
15
use Psr\Log\{
16
    LoggerInterface,
17
    LoggerAwareInterface,
18
};
19
use RuntimeException;
20
use Stringable;
21
use WebSocket\Trait\StringableTrait;
22

23
/**
24
 * WebSocket\Http\HttpHandler class.
25
 * Reads and writes HTTP message to/from stream.
26
 * @deprecated Remove LoggerAwareInterface in v4
27
 */
28
class HttpHandler implements LoggerAwareInterface, Stringable
29
{
30
    use StringableTrait;
31

32
    private SocketStream $stream;
33
    private bool $ssl;
34

35
    public function __construct(SocketStream $stream, bool $ssl = false)
36
    {
37
        $this->stream = $stream;
105✔
38
        $this->ssl = $ssl;
105✔
39
    }
40

41
    /**
42
     * @deprecated Remove in v4
43
     */
44
    public function setLogger(LoggerInterface $logger): void
45
    {
46
    }
99✔
47

48
    public function pull(): MessageInterface
49
    {
50
        $status = $this->readLine();
76✔
51

52
        // Pulling server request
53
        preg_match('!^(?P<method>[A-Z]+) (?P<path>[^ ]*) HTTP/(?P<version>[0-9/.]+)!', $status, $matches);
73✔
54
        if (!empty($matches)) {
73✔
55
            $message = new ServerRequest($matches['method']);
26✔
56
            $path = $matches['path'];
26✔
57
            $version = $matches['version'];
26✔
58
        }
59

60
        // Pulling response
61
        preg_match('!^HTTP/(?P<version>[0-9/.]+) (?P<code>[0-9]*) (?P<reason>.*)!', $status, $matches);
73✔
62
        if (!empty($matches)) {
73✔
63
            $message = new Response($matches['code'], $matches['reason']);
46✔
64
            $version = $matches['version'];
46✔
65
        }
66

67
        if (empty($message)) {
73✔
68
            throw new RuntimeException('Invalid Http request.');
1✔
69
        }
70

71
        $message = $message->withProtocolVersion($version);
72✔
72

73
        while ($header = $this->readLine()) {
72✔
74
            $parts = explode(':', $header, 2);
68✔
75
            if (count($parts) == 2) {
68✔
76
                if ($message->getheaderLine($parts[0]) === '') {
68✔
77
                    $message = $message->withHeader($parts[0], trim($parts[1]));
68✔
78
                } else {
79
                    $message = $message->withAddedHeader($parts[0], trim($parts[1]));
4✔
80
                }
81
            }
82
        }
83
        if ($message instanceof Request) {
72✔
84
            $scheme = $this->ssl ? 'wss' : 'ws';
26✔
85
            $uri = new Uri("{$scheme}://{$message->getHeaderLine('Host')}{$path}");
26✔
86
            $message = $message->withUri($uri, true);
26✔
87
        }
88

89
        return $message;
72✔
90
    }
91

92
    public function push(MessageInterface $message): MessageInterface
93
    {
94
        $data = implode("\r\n", $message->getAsArray()) . "\r\n\r\n";
72✔
95
        $this->stream->write($data);
72✔
96
        return $message;
70✔
97
    }
98

99
    private function readLine(): string
100
    {
101
        $data = '';
76✔
102
        do {
103
            $buffer = $this->stream->readLine(1024);
76✔
104
            if (is_null($buffer)) {
73✔
NEW
105
                throw new RuntimeException('Could not read Http request.');
×
106
            }
107
            $data .= $buffer;
73✔
108
        } while (!str_ends_with($data, "\r\n"));
73✔
109
        return trim($data);
73✔
110
    }
111
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc