Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]

   1  <?php
   2  
   3  namespace IMSGlobal\LTI;
   4  
   5  global $CFG;
   6  require_once($CFG->libdir . '/filelib.php');
   7  
   8  /**
   9   * Class to represent an HTTP message
  10   *
  11   * @author  Stephen P Vickers <svickers@imsglobal.org>
  12   * @copyright  IMS Global Learning Consortium Inc
  13   * @date  2016
  14   * @version 3.0.0
  15   * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  16   */
  17  #[\AllowDynamicProperties]
  18  class HTTPMessage
  19  {
  20  
  21  /**
  22   * True if message was sent successfully.
  23   *
  24   * @var boolean $ok
  25   */
  26      public $ok = false;
  27  
  28  /**
  29   * Request body.
  30   *
  31   * @var request $request
  32   */
  33      public $request = null;
  34  
  35  /**
  36   * Request headers.
  37   *
  38   * @var request_headers $requestHeaders
  39   */
  40      public $requestHeaders = '';
  41  
  42  /**
  43   * Response body.
  44   *
  45   * @var response $response
  46   */
  47      public $response = null;
  48  
  49  /**
  50   * Response headers.
  51   *
  52   * @var response_headers $responseHeaders
  53   */
  54      public $responseHeaders = '';
  55  
  56  /**
  57   * Status of response (0 if undetermined).
  58   *
  59   * @var status $status
  60   */
  61      public $status = 0;
  62  
  63  /**
  64   * Error message
  65   *
  66   * @var error $error
  67   */
  68      public $error = '';
  69  
  70  /**
  71   * Request URL.
  72   *
  73   * @var url $url
  74   */
  75      private $url = null;
  76  
  77  /**
  78   * Request method.
  79   *
  80   * @var method $method
  81   */
  82      private $method = null;
  83  
  84  /**
  85   * Class constructor.
  86   *
  87   * @param string $url     URL to send request to
  88   * @param string $method  Request method to use (optional, default is GET)
  89   * @param mixed  $params  Associative array of parameter values to be passed or message body (optional, default is none)
  90   * @param string $header  Values to include in the request header (optional, default is none)
  91   */
  92      function __construct($url, $method = 'GET', $params = null, $header = null)
  93      {
  94  
  95          $this->url = $url;
  96          $this->method = strtoupper($method);
  97          if (is_array($params)) {
  98              $this->request = http_build_query($params);
  99          } else {
 100              $this->request = $params;
 101          }
 102          if (!empty($header)) {
 103              $this->requestHeaders = explode("\n", $header);
 104          }
 105  
 106      }
 107  
 108  /**
 109   * Send the request to the target URL.
 110   *
 111   * @return boolean True if the request was successful
 112   */
 113      public function send()
 114      {
 115  
 116          $this->ok = false;
 117          // Try using curl if available
 118          if (function_exists('curl_init')) {
 119              $resp = '';
 120              $chResp = '';
 121  
 122              $curl = new \curl();
 123              $options = [
 124                  'CURLOPT_HEADER' => true,
 125                  'CURLINFO_HEADER_OUT' => true,
 126              ];
 127              if (!empty($this->requestHeaders)) {
 128                  $options['CURLOPT_HTTPHEADER'] = $this->requestHeaders;
 129              } else {
 130                  $options['CURLOPT_HEADER'] = 0;
 131              }
 132              if ($this->method === 'POST') {
 133                  $chResp = $curl->post($this->url, $this->request, $options);
 134              } else if ($this->method !== 'GET') {
 135                  if (!is_null($this->request)) {
 136                      $chResp = $curl->post($this->url, $this->request, $options);
 137                  }
 138              } else {
 139                  $chResp = $curl->get($this->url, null, $options);
 140              }
 141              $info = $curl->get_info();
 142  
 143              if (!$curl->get_errno() && !$curl->error) {
 144                  $chResp = str_replace("\r\n", "\n", $chResp);
 145                  $chRespSplit = explode("\n\n", $chResp, 2);
 146                  if ((count($chRespSplit) > 1) && (substr($chRespSplit[1], 0, 5) === 'HTTP/')) {
 147                      $chRespSplit = explode("\n\n", $chRespSplit[1], 2);
 148                  }
 149                  $this->responseHeaders = $chRespSplit[0];
 150                  $resp = $chRespSplit[1];
 151                  $this->status = $info['http_code'];
 152                  $this->ok = $this->status < 400;
 153                  if (!$this->ok) {
 154                      $this->error = $curl->error;
 155                  }
 156              } else {
 157                  $this->error = $curl->error;
 158                  $resp = $chResp;
 159              }
 160  
 161              $this->response = $resp;
 162              $this->requestHeaders = !empty($info['request_header']) ? str_replace("\r\n", "\n", $info['request_header']) : '';
 163          } else {
 164              // Try using fopen if curl was not available
 165              $opts = array('method' => $this->method,
 166                            'content' => $this->request
 167                           );
 168              if (!empty($this->requestHeaders)) {
 169                  $opts['header'] = $this->requestHeaders;
 170              }
 171              try {
 172                  $ctx = stream_context_create(array('http' => $opts));
 173                  $fp = @fopen($this->url, 'rb', false, $ctx);
 174                  if ($fp) {
 175                      $resp = @stream_get_contents($fp);
 176                      $this->ok = $resp !== false;
 177                  }
 178              } catch (\Exception $e) {
 179                  $this->ok = false;
 180              }
 181          }
 182  
 183          return $this->ok;
 184  
 185      }
 186  
 187  }