-
Notifications
You must be signed in to change notification settings - Fork 91
Expand file tree
/
Copy pathDemoProxy.php
More file actions
111 lines (94 loc) · 3.19 KB
/
DemoProxy.php
File metadata and controls
111 lines (94 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace helpers;
/**
* Proxy for demo.matomo.cloud, allows us to make single origin requests by doing them through this class
*/
class DemoProxy
{
private const MATOMO_SWAGGER_PROXY_TARGET = 'https://demo.matomo.cloud';
private const DEMO_AUTHORIZATION_HEADER = 'Bearer anonymous';
/**
* Fetches a demo API GET response and returns the body and status code.
*
* @param string $url Demo API URL to request.
* @return array{body: string, statusCode: int}
*/
public static function get(string $url): array
{
$context = self::createContext();
$proxiedResponse = self::fetchResponse($url, $context);
$statusCode = self::parseStatusCode($proxiedResponse['responseHeaders']);
return [
'body' => $proxiedResponse['body'],
'statusCode' => $statusCode,
];
}
/**
* Builds a validated demo API URL for proxying.
*
* @param string $path Relative request path.
* @param array $queryParams Query parameters to append to the URL.
* @return string The validated absolute demo API URL.
* @throws \InvalidArgumentException If the path is not index.php.
* @throws \InvalidArgumentException If the module query parameter is not API.
*/
public static function buildValidatedApiUrl(string $path, array $queryParams): string
{
$normalizedPath = trim($path, '/');
if ($normalizedPath !== 'index.php') {
throw new \InvalidArgumentException('Path must be index.php');
}
if (($queryParams['module'] ?? null) !== 'API') {
throw new \InvalidArgumentException('Module must be API');
}
$targetUrl = rtrim(self::MATOMO_SWAGGER_PROXY_TARGET, '/') . '/' . $normalizedPath;
$query = http_build_query($queryParams);
if ($query !== '') {
$targetUrl .= '?' . $query;
}
return $targetUrl;
}
private static function createContext()
{
return stream_context_create([
'http' => [
'method' => 'GET',
'header' => self::buildHeaders(),
'ignore_errors' => true,
'timeout' => 30,
],
]);
}
private static function buildHeaders(): string
{
return 'Authorization: ' . self::DEMO_AUTHORIZATION_HEADER;
}
/**
* @return array{body: string, responseHeaders: array}
*/
private static function fetchResponse(string $url, $context): array
{
$body = @file_get_contents($url, false, $context);
if ($body === false) {
throw new \RuntimeException('Could not proxy HTTP request');
}
return [
'body' => $body,
'responseHeaders' => $http_response_header ?? [],
];
}
private static function parseStatusCode(array $responseHeaders): int
{
$statusLine = $responseHeaders[0] ?? '';
if (preg_match('#^HTTP/\S+\s+(\d{3})#', $statusLine, $matches)) {
return (int) $matches[1];
}
return 200;
}
}