Skip to content
This repository has been archived by the owner on Jun 27, 2018. It is now read-only.

Commit

Permalink
Added support for using custom HTTP clients in a backward-compatible …
Browse files Browse the repository at this point in the history
…way.

Also added a test suite that covers the HTTPMessage and client classes.
  • Loading branch information
jeremeamia committed Nov 29, 2016
1 parent c9cbfdd commit 6c5a558
Show file tree
Hide file tree
Showing 12 changed files with 579 additions and 138 deletions.
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending for every file
# Indent with 4 spaces
[php]
end_of_line = lf
indent_style = space
indent_size = 4
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
phpunit.xml
composer.phar
composer.lock
vendor/
build/
.idea
.DS_STORE
16 changes: 15 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "imsglobal/lti",
"version" : "3.0.2",
"description": "LTI Tool Provider Library",
"keywords": ["lti"],
"keywords": ["lti", "ims", "content-item", "edtech", "education", "lms"],
"homepage": "https://www.imsglobal.org/lti",
"type": "library",
"license": "Apache-2.0",
Expand All @@ -19,5 +19,19 @@
"psr-4": {
"IMSGlobal\\LTI\\": "src/"
}
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^5.6"
},
"autoload-dev":{
"psr-4": {
"IMSGlobal\\LTI\\Test\\": "tests/"
}
},
"scripts": {
"test": "phpunit",
"coverage": "phpunit --coverage-html=build/coverage",
"coverage-text": "phpunit --coverage-text"
}
}
21 changes: 21 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./vendor/autoload.php"
forceCoversAnnotation="true">

<testsuites>
<testsuite>
<directory suffix="Test.php">tests/</directory>
</testsuite>
</testsuites>

<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>

<php>
<server name="TEST_SERVER_PORT" value="9999"/>
</php>

</phpunit>
27 changes: 27 additions & 0 deletions src/HTTP/Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace IMSGlobal\LTI\HTTP;

use IMSGlobal\LTI\HTTPMessage;

/**
* An HTTP client for sending the HTTP messages.
*
* @author Stephen P Vickers <[email protected]>
* @copyright IMS Global Learning Consortium Inc
* @date 2016
* @version 3.0.0
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
*/
interface Client
{

/**
* Send the provided HTTPMessage and then updates it with the response data.
*
* @param HTTPMessage $message The HTTP message to send
* @return bool If successful, returns true
*/
public function send(HTTPMessage $message);

}
69 changes: 69 additions & 0 deletions src/HTTP/CurlClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace IMSGlobal\LTI\HTTP;

use IMSGlobal\LTI\HTTPMessage;

/**
* Sends HTTP messages with cURL.
*
* @author Stephen P Vickers <[email protected]>
* @copyright IMS Global Learning Consortium Inc
* @date 2016
* @version 3.0.0
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
*/
class CurlClient implements Client
{

/**
* @inheritdoc
*/
public function send(HTTPMessage $message)
{
$message->ok = false;

$resp = '';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $message->url);
if (!empty($message->requestHeaders)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $message->requestHeaders);
} else {
curl_setopt($ch, CURLOPT_HEADER, 0);
}
if ($message->method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $message->request);
} else if ($message->method !== 'GET') {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $message->method);
if (!is_null($message->request)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $message->request);
}
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$chResp = curl_exec($ch);
$message->ok = $chResp !== false;
if ($message->ok) {
$chResp = str_replace("\r\n", "\n", $chResp);
$chRespSplit = explode("\n\n", $chResp, 2);
if ((count($chRespSplit) > 1) && (substr($chRespSplit[1], 0, 5) === 'HTTP/')) {
$chRespSplit = explode("\n\n", $chRespSplit[1], 2);
}
$message->responseHeaders = $chRespSplit[0];
$resp = $chRespSplit[1];
$message->status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$message->ok = $message->status < 400;
if (!$message->ok) {
$message->error = curl_error($ch);
}
}
$message->requestHeaders = str_replace("\r\n", "\n", curl_getinfo($ch, CURLINFO_HEADER_OUT));
curl_close($ch);
$message->response = $resp;

return $message->ok;
}

}
55 changes: 55 additions & 0 deletions src/HTTP/StreamClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace IMSGlobal\LTI\HTTP;

use IMSGlobal\LTI\HTTPMessage;

/**
* Sends HTTP messages with streams via fopen.
*
* @author Stephen P Vickers <[email protected]>
* @copyright IMS Global Learning Consortium Inc
* @date 2016
* @version 3.0.0
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
*/
class StreamClient implements Client
{

/**
* @inheritdoc
*/
public function send(HTTPMessage $message)
{
$message->ok = false;

// Prepare options for the HTTP context.
$opts = array(
'method' => $message->method,
'content' => $message->request
);
if (!empty($message->requestHeaders)) {
$opts['header'] = $message->requestHeaders;
}

// Send the request.
$http_response_header = null;
$context = stream_context_create(['http' => $opts]);
$stream = @fopen($message->url, 'rb', false, $context);
if ($stream) {
$message->response = @stream_get_contents($stream);
fclose($stream);
}

// Read the headers to get the status.
if ($http_response_header) {
$message->responseHeaders = implode("\n", $http_response_header);
$parts = explode(' ', $message->responseHeaders, 3);
$message->status = $parts[1];
$message->ok = $message->status < 400;
}

return $message->ok;
}

}
Loading

0 comments on commit 6c5a558

Please sign in to comment.