Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

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