23478c0487cab6dafa0adb0fd3715437db965a3c
[core.git] / framework / main / classes / client / http / class_HttpClient.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Client\Http;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Client\BaseClient;
8 use Org\Mxchange\CoreFramework\Client\Client;
9
10 /**
11  * A HTTP client class
12  *
13  * @author              Roland Haeder <webmaster@ship-simu.org>
14  * @version             0.0.0
15  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2021 Core Developer Team
16  * @license             GNU GPL 3.0 or any newer version
17  * @link                http://www.ship-simu.org
18  *
19  * This program is free software: you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation, either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  */
32 class HttpClient extends BaseClient implements Client {
33         // Constants
34         const HTTP_EOL = "\r\n";
35         const HTTP_USER_AGENT = 'HttpClient-Core/1.0';
36
37         /**
38          * Protected constructor
39          *
40          * @return      void
41          */
42         private function __construct () {
43                 // Set default user agent string (to allow other classes to override this)
44                 $this->setUserAgent(self::HTTP_USER_AGENT);
45
46                 // Call parent constructor
47                 parent::__construct(__CLASS__);
48         }
49
50         /**
51          * Creates an instance of this Client class and prepares it for usage
52          *
53          * @param       $socketResource         Resource of a socket (optional)
54          * @return      $clientInstance         An instance of a Client class
55          */
56         public final static function createHttpClient ($socketResouce = FALSE) {
57                 // Get a new instance
58                 $clientInstance = new HttpClient();
59
60                 // Set socket resource
61                 $clientInstance->setSocketResource($socketResource);
62
63                 // Return the prepared instance
64                 return $clientInstance;
65         }
66
67         /**
68          * Checks wether proxy configuration is used
69          *
70          * @return      $isUsed         Wether proxy is used
71          */
72         protected function isProxyUsed () {
73                 // Do we have cache?
74                 if (!isset($GLOBALS[__METHOD__])) {
75                         // Determine it
76                         $GLOBALS[__METHOD__] = ((FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('proxy_host') != '') && (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('proxy_port') > 0));
77                 } // END - if
78
79                 // Return cache
80                 return $GLOBALS[__METHOD__];
81         }
82
83         /**
84          * Sets up a proxy tunnel for given hostname and through resource
85          *
86          * @param       $host           Host to connect to
87          * @param       $port           Port number to connect to
88          * @return      $response       Response array
89          */
90         protected function setupProxyTunnel ($host, $port) {
91                 // Initialize array
92                 $response = array('', '', '');
93
94                 // Do the connect
95                 $respArray = $this->doConnectRequest($host, $port);
96
97                 // Analyze first header line
98                 if (((strtolower($respArray[0]) !== 'http/1.0') && (strtolower($respArray[0]) !== 'http/1.1')) || ($respArray[1] != '200')) {
99                         // Response code is not 200
100                         return $response;
101                 } // END - if
102
103                 // All fine!
104                 return $respArray;
105         }
106
107         /**
108          * Sends a raw HTTP request out to given IP/host and port number
109          *
110          * @param       $method                 Request method (GET, POST, HEAD, CONNECT, ...)
111          * @param       $host                   Host to connect to
112          * @param       $port                   Port number to connect to
113          * @return      $responseArray  Array with raw response
114          */
115         private function sendRawHttpRequest ($method, $host, $port, array $header = []) {
116                 // Minimum raw HTTP/1.1 request
117                 $rawRequest  = $method . ' ' . $host . ':' . $port . ' HTTP/1.1' . self::HTTP_EOL;
118                 $rawRequest .= 'Host: ' . $host . ':' . $port . self::HTTP_EOL;
119
120                 // Use login data to proxy? (username at least)
121                 if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('proxy_username') != '') {
122                         // Add it as well
123                         $encodedAuth = base64_encode(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('proxy_username') . ':' . FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('proxy_password'));
124                         $rawRequest .= 'Proxy-Authorization: Basic ' . $encodedAuth . self::HTTP_EOL;
125                 } // END - if
126
127                 // Add last new-line
128                 $rawRequest .= self::HTTP_EOL;
129                 //* DEBUG: */ self::createDebugInstance(__CLASS__)->debugOutput('HTTP-CLIENT: rawRequest=' . $rawRequest);
130
131                 // Write request
132                 fwrite($this->getSocketResource(), $rawRequest);
133
134                 // Got response?
135                 if (feof($this->getSocketResource())) {
136                         // No response received
137                         return $response;
138                 } // END - if
139
140                 // Read the first line
141                 $resp = trim(fgets($this->getSocketResource(), 10240));
142
143                 // "Explode" the string to an array
144                 $responseArray = explode(' ', $resp);
145
146                 // And return it
147                 return $responseArray;
148         }
149
150         /**
151          * A HTTP/1.1 CONNECT request
152          *
153          * @param       $host   Host to connect to
154          * @param       $port   Port number to connect to
155          * @return      $responseArray  An array with the read response
156          */
157         public function doConnectRequest ($host, $port) {
158                 // Prepare extra header(s)
159                 $headers = array(
160                         'Proxy-Connection' => 'Keep-Alive'
161                 );
162
163                 // Prepare raw request
164                 $responseArray = $this->sendRawHttpRequest('CONNECT', $host, $port, $headers);
165
166                 // Return response array
167                 return $responseArray;
168         }
169
170 }