1: <?php
2:
3: namespace Budabot\Core;
4:
5: use Exception;
6:
7: class InvalidHttpRequest extends Exception {
8: }
9:
10: class HttpRequest {
11:
12: private $method;
13: private $uri;
14: private $extraHeaders = array();
15: private $queryParams = array();
16: private $streamScheme = null;
17: private $streamPort = null;
18: private $streamHost = null;
19: private $uriComponents = array();
20:
21:
22:
23: static public $overridePathPrefix = null;
24:
25: public function __construct($method, $uri, $queryParams, $extraHeaders) {
26: $this->method = $method;
27: $this->uri = $uri;
28: $this->queryParams = $queryParams;
29: $this->extraHeaders = $extraHeaders;
30:
31: $this->parseUri();
32:
33: $this->extractStreamScheme();
34: $this->extractStreamPort();
35: $this->extractStreamHost();
36: }
37:
38: private function parseUri() {
39: $this->uriComponents = parse_url($this->uri);
40: if (!is_array($this->uriComponents)) {
41: throw new InvalidHttpRequest("Invalid URI: '{$this->uri}'");
42: }
43: }
44:
45: private function extractStreamScheme() {
46: if ($this->uriComponents['scheme'] == 'http') {
47: $this->streamScheme = 'tcp';
48: } else if ($this->uriComponents['scheme'] == 'https') {
49: $this->streamScheme = 'ssl';
50: } else {
51: throw new InvalidHttpRequest("URI has no valid scheme: '{$this->uri}'");
52: }
53: }
54:
55: private function extractStreamPort() {
56: if ($this->uriComponents['scheme'] == 'http') {
57: if (isset($this->uriComponents['port'])) {
58: $this->streamPort = $this->uriComponents['port'];
59: } else {
60: $this->streamPort = 80;
61: }
62: } else if ($this->uriComponents['scheme'] == 'https') {
63: if (isset($this->uriComponents['port'])) {
64: $this->streamPort = $this->uriComponents['port'];
65: } else {
66: $this->streamPort = 443;
67: }
68: } else {
69: throw new InvalidHttpRequest("URI has no valid scheme: '{$this->uri}'");
70: }
71: }
72:
73: private function extractStreamHost() {
74: if (!isset($this->uriComponents['host'])) {
75: throw new InvalidHttpRequest("URI has no host: '{$this->uri}'");
76: }
77: $this->streamHost = $this->uriComponents['host'];
78: }
79:
80: public function getHost() {
81: return $this->streamHost;
82: }
83:
84: public function getPort() {
85: return $this->streamPort;
86: }
87:
88: public function getScheme() {
89: return $this->streamScheme;
90: }
91:
92: public function getData() {
93: $data = $this->getHeaderData();
94: if ($this->method == 'post') {
95: $data .= $this->getPostQueryStr();
96: }
97:
98: return $data;
99: }
100:
101: private function getHeaderData() {
102: $path = $this->getRequestPath();
103: $data = strtoupper($this->method) . " $path HTTP/1.0\r\n";
104:
105: forEach ($this->getHeaders() as $header => $value) {
106: $data .= "$header: $value\r\n";
107: }
108:
109: $data .= "\r\n";
110: return $data;
111: }
112:
113: private function getRequestPath() {
114: $path = isset($this->uriComponents['path']) ? $this->uriComponents['path'] : '/';
115: $queryStr = isset($this->uriComponents['query']) ? $this->uriComponents['query'] : null;
116:
117: if ($this->method == 'get') {
118: parse_str($queryStr, $queryArray);
119: $queryArray = array_merge($queryArray, $this->queryParams);
120: $queryStr = http_build_query($queryArray);
121: } else if ($this->method == 'post') {
122: } else {
123: throw new InvalidHttpRequest("Invalid http method: '{$this->method}'");
124: }
125:
126: if (self::$overridePathPrefix) {
127: $path = self::$overridePathPrefix . $path;
128: }
129:
130: return "$path?$queryStr";
131: }
132:
133: private function getHeaders() {
134: $headers = array();
135: $headers['Host'] = $this->streamHost;
136: if ($this->method == 'post' && $this->queryParams) {
137: $headers['Content-Type'] = 'application/x-www-form-urlencoded';
138: $headers['Content-Length'] = strlen($this->getPostQueryStr());
139: }
140:
141: $headers = array_merge($headers, $this->extraHeaders);
142: return $headers;
143: }
144:
145: private function getPostQueryStr() {
146: return http_build_query($this->queryParams);
147: }
148: }
149: