Skip to content

Commit 06428d2

Browse files
Release v6.2.0
1 parent 4735617 commit 06428d2

File tree

16 files changed

+1456
-2
lines changed

16 files changed

+1456
-2
lines changed

src/Controller/Base.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ abstract class Base {
2424
// методы, доступ к которым ограничен без оплаты мест
2525
public const ALLOWED_WITH_PAYMENT_ONLY_METHODS = [];
2626

27+
// методы, в которых мы должны фильтровать контент
28+
public const NEED_FILTER_CONTENT_METHODS = [];
29+
2730
// список запрещенных методов по ролям, пример:
2831
// [
2932
// ROLE_GUEST => [
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace BaseFrame\Exception\Request;
4+
5+
use BaseFrame\Exception\RequestException;
6+
7+
/**
8+
* Недопустимое содержимое запроса
9+
*/
10+
class InappropriateContentException extends RequestException {
11+
12+
}

src/Http/Header/ContentType.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace BaseFrame\Http\Header;
4+
5+
/**
6+
* Обработчик для заголовка типа контента
7+
*/
8+
class ContentType extends Header {
9+
10+
protected const _HEADER_KEY = "CONTENT_TYPE"; // ключ хедера
11+
12+
public function getContentType():string {
13+
14+
return trim(explode(";", $this->getValue())[0]);
15+
}
16+
}

src/Icap/Client/HttpRequest.php

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
3+
namespace BaseFrame\Icap\Client;
4+
5+
/**
6+
* Класс http реквеств
7+
*/
8+
class HttpRequest {
9+
10+
private string $method; // метод реквеста (GET, POST)
11+
private string $url; // url реквеста
12+
private array $headers = []; // хедеры реквеста
13+
private mixed $body_stream; // тело запроса
14+
15+
/**
16+
* Конструктор
17+
*
18+
* @param string $method
19+
* @param string $url
20+
* @param array $headers
21+
* @param null $body_stream
22+
*/
23+
public function __construct(string $method, string $url, array $headers = [], $body_stream = null) {
24+
25+
$this->method = strtoupper($method);
26+
$this->url = $url;
27+
$this->headers = $headers;
28+
$this->body_stream = $body_stream;
29+
}
30+
31+
/**
32+
* Размер хедера
33+
*
34+
* @return int
35+
*/
36+
public function headersLength():int {
37+
38+
$lines = "{$this->method} {$this->url} HTTP/1.1\r\n";
39+
foreach ($this->headers as $name => $value) {
40+
$lines .= "$name: $value\r\n";
41+
}
42+
return strlen($lines . "\r\n");
43+
}
44+
45+
/**
46+
* Есть ли тело у запроса
47+
*
48+
* @return bool
49+
*/
50+
public function hasBody():bool {
51+
52+
return $this->body_stream !== null;
53+
}
54+
55+
/**
56+
* Разбить реквест по чанкам
57+
*
58+
* @return iterable
59+
*/
60+
public function toChunks():iterable {
61+
62+
// если в хедере задан размер контента, отдаем все сразу
63+
if (isset($this->headers["Content-Length"])) {
64+
return $this->withFullBody();
65+
}
66+
67+
// иначе возвращаем по частям
68+
return $this->withChunkedBody();
69+
}
70+
71+
/**
72+
* Отдать http хедер в виде чанков
73+
*
74+
* @return iterable
75+
*/
76+
public function headerToChunks():iterable {
77+
78+
yield "{$this->method} {$this->url} HTTP/1.1\r\n";
79+
foreach ($this->headers as $name => $value) {
80+
yield "$name: $value\r\n";
81+
}
82+
yield "\r\n";
83+
}
84+
85+
/**
86+
* Отдать http тело в виде чанков
87+
*
88+
* @param int $preview_size
89+
*
90+
* @return iterable
91+
*/
92+
public function bodyToChunks(int $preview_size = 0):iterable {
93+
94+
if ($this->body_stream) {
95+
96+
if ($preview_size !== 0 && !feof($this->body_stream)) {
97+
98+
$chunk = fread($this->body_stream, $preview_size);
99+
yield dechex(strlen($chunk)) . "\r\n" . $chunk . "\r\n";
100+
}
101+
102+
while (!feof($this->body_stream)) {
103+
104+
$chunk = fread($this->body_stream, 8192);
105+
yield dechex(strlen($chunk)) . "\r\n";
106+
yield $chunk . "\r\n";
107+
}
108+
yield "0\r\n\r\n";
109+
}
110+
}
111+
112+
/**
113+
* Генератор тела запроса, разбитого по частям
114+
*
115+
* @return iterable
116+
*/
117+
public function withChunkedBody():iterable {
118+
119+
yield "{$this->method} {$this->url} HTTP/1.1\r\n";
120+
foreach ($this->headers as $name => $value) {
121+
yield "$name: $value\r\n";
122+
}
123+
yield "\r\n";
124+
125+
if ($this->body_stream) {
126+
127+
while (!feof($this->body_stream)) {
128+
129+
$chunk = fread($this->body_stream, 8192);
130+
yield dechex(strlen($chunk)) . "\r\n";
131+
yield $chunk . "\r\n";
132+
}
133+
yield "0\r\n\r\n";
134+
}
135+
}
136+
137+
/**
138+
* Генератор тела запроса
139+
*
140+
* @return iterable
141+
*/
142+
public function withFullBody():iterable {
143+
144+
yield "{$this->method} {$this->url} HTTP/1.1\r\n";
145+
foreach ($this->headers as $name => $value) {
146+
yield "$name: $value\r\n";
147+
}
148+
yield "\r\n";
149+
150+
if ($this->body_stream) {
151+
152+
$body = stream_get_contents($this->body_stream);
153+
yield dechex(strlen($body)) . "\r\n";
154+
yield $body . "\r\n";
155+
}
156+
yield "0\r\n\r\n";
157+
}
158+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
<?php
2+
3+
namespace BaseFrame\Icap\Client;
4+
5+
/**
6+
* Билдер http запроса
7+
*/
8+
class HttpRequestBuilder {
9+
10+
private string $method = "GET"; // метод http запроса
11+
private string $url = "/"; // url запроса
12+
private array $headers = []; // хедеры запроса
13+
private mixed $body_stream = null; // тело запроса
14+
15+
/**
16+
* Установить метод
17+
*
18+
* @param string $method
19+
*
20+
* @return $this
21+
*/
22+
public function method(string $method):self {
23+
24+
$this->method = strtoupper($method);
25+
return $this;
26+
}
27+
28+
/**
29+
* Установить url
30+
*
31+
* @param string $url
32+
*
33+
* @return $this
34+
*/
35+
public function url(string $url):self {
36+
37+
$this->url = $url;
38+
return $this;
39+
}
40+
41+
/**
42+
* Добавить хедер
43+
*
44+
* @param string $name
45+
* @param string $value
46+
*
47+
* @return $this
48+
*/
49+
public function addHeader(string $name, string $value):self {
50+
51+
$this->headers[$name] = $value;
52+
return $this;
53+
}
54+
55+
/**
56+
* Сформировать тело в виде файла
57+
*
58+
* @param string $filePath
59+
*
60+
* @return $this
61+
*/
62+
public function bodyFromFile(string $filePath):self {
63+
64+
$this->body_stream = fopen($filePath, "rb");
65+
$this->headers["Content-Type"] = "application/octet-stream";
66+
$this->headers["Transfer-Encoding"] = "chunked";
67+
return $this;
68+
}
69+
70+
/**
71+
* Сформировать тело в виде формы
72+
*
73+
* @param array $fields
74+
*
75+
* @return $this
76+
*/
77+
public function bodyFromForm(array $fields):self {
78+
79+
$encoded = json_encode($fields, JSON_UNESCAPED_UNICODE);
80+
$this->body_stream = fopen("php://temp", "r+");
81+
fwrite($this->body_stream, $encoded);
82+
rewind($this->body_stream);
83+
$this->headers["Content-Type"] = "application/json";
84+
$this->headers["Content-Length"] = strlen($encoded);
85+
return $this;
86+
}
87+
88+
/**
89+
* Сформировать тело в виде multipart формы
90+
*
91+
* @param string $fieldName
92+
* @param string $filePath
93+
* @param string|null $fileName
94+
*
95+
* @return $this
96+
* @throws \Random\RandomException
97+
*/
98+
public function bodyFromMultipartFile(string $fieldName, string $filePath, string $fileName = null):self {
99+
100+
$boundary = "----CompassFormBoundary" . bin2hex(random_bytes(16));
101+
$this->headers["Content-Type"] = "multipart/form-data; boundary=" . $boundary;
102+
$this->headers["Transfer-Encoding"] = "chunked";
103+
104+
$fileName = $fileName ?? basename($filePath);
105+
$stream = fopen("php://temp", "r+");
106+
107+
fwrite($stream, "--{$boundary}\r\n");
108+
fwrite($stream, "Content-Disposition: form-data; name=\"{$fieldName}\"; filename=\"{$fileName}\"\r\n");
109+
fwrite($stream, "Content-Type: application/octet-stream\r\n\r\n");
110+
111+
$fileStream = fopen($filePath, "rb");
112+
stream_copy_to_stream($fileStream, $stream);
113+
fclose($fileStream);
114+
115+
fwrite($stream, "\r\n--{$boundary}--\r\n");
116+
rewind($stream);
117+
118+
$this->body_stream = $stream;
119+
120+
return $this;
121+
}
122+
123+
/**
124+
* Сформировать объект http запроса
125+
*
126+
* @return HttpRequest
127+
*/
128+
public function build():HttpRequest {
129+
130+
return new HttpRequest($this->method, $this->url, $this->headers, $this->body_stream);
131+
}
132+
}

0 commit comments

Comments
 (0)