Skip to content

Commit 651ebf5

Browse files
committed
create separated Http package from web package
1 parent 541d399 commit 651ebf5

29 files changed

+1296
-3
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2024 DevNet Framework
3+
Copyright (c) DevNet Framework
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,22 @@
1-
# http
2-
The DevNet Http Library
1+
# DevNet HTTP
2+
This dependency is the HTTP library, which is part of the **DevNet Framework** and includes the following components:
3+
4+
- HTTP Messages
5+
- HTTP Middleware
6+
- HTTP Client
7+
8+
## Requirements
9+
- [DevNet Core](https://github.com/DevNet-Framework/core/) version 1.0
10+
- [Composer](https://getcomposer.org/) version 2.0 or higher
11+
12+
## Installation
13+
You can install DevNet Web as a third-party library to work with any PHP project, by running the following command in the terminal:
14+
```
15+
composer require devnet/http
16+
```
17+
18+
## Documentation
19+
Full documentation on how to use **DevNet Framework** is available at [devnet-framework.github.io](https://devnet-framework.github.io)
20+
21+
## License
22+
This library is licensed under the MIT license. See [License File](https://github.com/DevNet-Framework/web/blob/master/LICENSE) in the root folder for more information.

composer.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "devnet/http",
3+
"description": "The DevNet HTTP Library",
4+
"type": "library",
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "Mohammed Moussaoui",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"require": {
13+
"php": "^8.1",
14+
"devnet/system": "1.1.*"
15+
},
16+
"autoload": {
17+
"psr-4": {
18+
"DevNet\\Http\\": "lib/"
19+
}
20+
}
21+
}

lib/Client/HttpClient.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
/**
4+
* @author Mohammed Moussaoui
5+
* @license MIT license. For more license information, see the LICENSE file in the root directory.
6+
* @link https://github.com/DevNet-Framework
7+
*/
8+
9+
namespace DevNet\Http\Client;
10+
11+
use DevNet\Http\Message\Headers;
12+
use DevNet\Http\Message\HttpRequest;
13+
use DevNet\System\Async\Task;
14+
use DevNet\System\PropertyTrait;
15+
16+
class HttpClient extends HttpClientHandler
17+
{
18+
use PropertyTrait;
19+
20+
protected HttpClientOptions $options;
21+
22+
public function __construct(?HttpClientOptions $options = null)
23+
{
24+
if (!$options) {
25+
$options = new HttpClientOptions();
26+
}
27+
28+
$this->Options = $options;
29+
}
30+
31+
public function get_Options(): HttpClientOptions
32+
{
33+
return $this->options;
34+
}
35+
36+
public function requestAsync(string $method, string $url, ?HttpRequestContent $requestContent = null): Task
37+
{
38+
if (!empty($this->Options->BaseAddress)) {
39+
$url = $this->Options->BaseAddress . $url;
40+
}
41+
42+
$host = parse_url($url, PHP_URL_HOST);
43+
$headers = new Headers(['host' => $host]);
44+
$request = new HttpRequest($method, $url, $headers);
45+
46+
$request->setProtocol($this->Options->HttpVersion);
47+
if ($requestContent) {
48+
$request->Headers->add('content-type', $requestContent->ContentType);
49+
$request->Headers->add('content-length', $requestContent->ContentLength);
50+
$request->Body->write($requestContent->Content);
51+
}
52+
53+
return $this->sendAsync($request);
54+
}
55+
56+
public function getStringAsync(string $url, ?HttpRequestContent $requestContent = null): Task
57+
{
58+
$task = $this->getAsync($url, $requestContent);
59+
return $task->then(function (Task $antecedent) {
60+
$response = $antecedent->Result;
61+
if ($response->Body->IsReadable) {
62+
if ($response->Body->Length > 0) {
63+
return $response->Body->read($response->Body->Length);
64+
}
65+
66+
return '';
67+
}
68+
});
69+
}
70+
71+
public function getAsync(string $url, ?HttpRequestContent $requestContent = null): Task
72+
{
73+
return $this->requestAsync('GET', $url, $requestContent);
74+
}
75+
76+
public function postAsync(string $url, ?HttpRequestContent $requestContent): Task
77+
{
78+
return $this->requestAsync('POST', $url, $requestContent);
79+
}
80+
81+
public function putAsync(string $url, ?HttpRequestContent $requestContent): Task
82+
{
83+
return $this->requestAsync('PUT', $url, $requestContent);
84+
}
85+
86+
public function deleteAsync(string $url): Task
87+
{
88+
return $this->requestAsync('DELETE', $url);
89+
}
90+
}

lib/Client/HttpClientHandler.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/**
4+
* @author Mohammed Moussaoui
5+
* @license MIT license. For more license information, see the LICENSE file in the root directory.
6+
* @link https://github.com/DevNet-Framework
7+
*/
8+
9+
namespace DevNet\Http\Client;
10+
11+
use DevNet\System\Async\Task;
12+
use DevNet\Http\Client\Internal\HttpRequestRawBuilder;
13+
use DevNet\Http\Client\Internal\HttpResponseParser;
14+
use DevNet\Http\Message\HttpRequest;
15+
use DevNet\Http\Message\HttpResponse;
16+
use DevNet\System\Net\Socket;
17+
18+
use function DevNet\System\async;
19+
use function DevNet\System\await;
20+
21+
abstract class HttpClientHandler
22+
{
23+
protected HttpClientOptions $Options;
24+
25+
abstract public function __construct(HttpClientOptions $options);
26+
27+
public function send(HttpRequest $request): HttpResponse
28+
{
29+
return $this->sendAsync($request)->getAwaiter()->getResult();
30+
}
31+
32+
public function sendAsync(HttpRequest $request): Task
33+
{
34+
$sendAsync = async(function ($request) {
35+
$socket = new Socket($request->Host->Name, $request->Host->Port, $this->Options->Timeout);
36+
$socket->write(HttpRequestRawBuilder::build($request));
37+
$responseHeaderRaw = '';
38+
do {
39+
$responseHeaderRaw .= await($socket->readLineAsync());
40+
} while (strpos($responseHeaderRaw, "\r\n\r\n") === false);
41+
42+
$response = HttpResponseParser::parse($responseHeaderRaw);
43+
while (!$socket->EndOfStream) {
44+
$responseBodyChunk = await($socket->readAsync(1024 * 4));
45+
$response->Body->write($responseBodyChunk);
46+
}
47+
48+
return $response;
49+
});
50+
51+
return $sendAsync($request);
52+
}
53+
}

lib/Client/HttpClientOptions.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/**
4+
* @author Mohammed Moussaoui
5+
* @license MIT license. For more license information, see the LICENSE file in the root directory.
6+
* @link https://github.com/DevNet-Framework
7+
*/
8+
9+
namespace DevNet\Http\Client;
10+
11+
class HttpClientOptions
12+
{
13+
/**
14+
* The host name of the url address.
15+
*/
16+
public string $BaseAddress = '';
17+
18+
/**
19+
* The HTTP version.
20+
*/
21+
public string $HttpVersion = 'HTTP/1.0';
22+
23+
/**
24+
* The max times to wait in seconds.
25+
*/
26+
public ?float $Timeout = null;
27+
}

lib/Client/HttpRequestContent.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/**
4+
* @author Mohammed Moussaoui
5+
* @license MIT license. For more license information, see the LICENSE file in the root directory.
6+
* @link https://github.com/DevNet-Framework
7+
*/
8+
9+
namespace DevNet\Http\Client;
10+
11+
class HttpRequestContent
12+
{
13+
public string $Content;
14+
public string $ContentType;
15+
public int $ContentLength;
16+
17+
public function __construct(string $contentType, string $content)
18+
{
19+
$this->Content = $content;
20+
$this->ContentType = $contentType;
21+
$this->ContentLength = strlen($content);
22+
}
23+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/**
4+
* @author Mohammed Moussaoui
5+
* @license MIT license. For more license information, see the LICENSE file in the root directory.
6+
* @link https://github.com/DevNet-Framework
7+
*/
8+
9+
namespace DevNet\Http\Client\Internal;
10+
11+
use DevNet\System\Text\StringBuilder;
12+
use DevNet\Http\Message\HttpRequest;
13+
14+
class HttpRequestRawBuilder
15+
{
16+
public static function build(HttpRequest $request): string
17+
{
18+
$requestRaw = new StringBuilder();
19+
$requestRaw->append($request->Method);
20+
$requestRaw->append(' ');
21+
$requestRaw->append($request->Path);
22+
$requestRaw->append(' ');
23+
$requestRaw->append($request->Protocol);
24+
$requestRaw->append("\r\n");
25+
26+
foreach ($request->Headers->getAll() as $key => $values) {
27+
foreach ($values as $value) {
28+
$requestRaw->append($key);
29+
$requestRaw->append(': ');
30+
$requestRaw->append($value);
31+
$requestRaw->append("\r\n");
32+
}
33+
}
34+
35+
$requestRaw->append("\r\n");
36+
if ($request->Body->IsReadable) {
37+
if ($request->Body->Length > 0) {
38+
$requestRaw->appendLine($request->Body->read($request->Body->Length));
39+
}
40+
}
41+
42+
return $requestRaw;
43+
}
44+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/**
4+
* @author Mohammed Moussaoui
5+
* @license MIT license. For more license information, see the LICENSE file in the root directory.
6+
* @link https://github.com/DevNet-Framework
7+
*/
8+
9+
namespace DevNet\Http\Client\Internal;
10+
11+
use DevNet\Http\Message\Headers;
12+
use DevNet\Http\Message\HttpResponse;
13+
14+
class HttpResponseParser
15+
{
16+
public static function parse(string $responseHeaderRaw): HttpResponse
17+
{
18+
$headers = explode(PHP_EOL, $responseHeaderRaw);
19+
$responseLine = array_shift($headers);
20+
$responseLine = explode(' ', $responseLine);
21+
22+
foreach ($headers as $header) {
23+
explode(":", $header);
24+
}
25+
26+
$response = new HttpResponse(new Headers($headers));
27+
$response->setProtocol($responseLine[0]);
28+
$response->setStatusCode($responseLine[1]);
29+
30+
return $response;
31+
}
32+
}

lib/Message/ContentType.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
/**
4+
* @author Mohammed Moussaoui
5+
* @license MIT license. For more license information, see the LICENSE file in the root directory.
6+
* @link https://github.com/DevNet-Framework
7+
*/
8+
9+
namespace DevNet\Http\Message;
10+
11+
class ContentType
12+
{
13+
public static $Text = 'text/plain';
14+
public static $Html = 'text/html';
15+
public static $Png = 'image/png';
16+
public static $Pdf = 'application/pdf';
17+
public static $Json = 'application/json';
18+
public static $Form = 'application/x-www-form-urlencoded';
19+
public static $Data = 'multipart/form-data';
20+
}

0 commit comments

Comments
 (0)