3 use Psr\Http\Message\ResponseInterface
;
4 use Psr\Http\Message\RequestInterface
;
7 * Additional helpers/utilities for use as Guzzle middleware.
9 class CRM_Utils_GuzzleMiddleware
{
12 * Add this as a Guzzle handler/middleware if you wish to simplify
13 * the construction of Civi-related URLs. It enables URL schemes for:
15 * - route://ROUTE_NAME (aka) route:ROUTE_NAME
16 * - var://PATH_EXPRESSION (aka) var:PATH_EXPRESSION
17 * - ext://EXTENSION/FILE (aka) ext:EXTENSION/FILE
18 * - assetBuilder://ASSET_NAME?PARAMS (aka) assetBuilder:ASSET_NAME?PARAMS
22 * $http->get(CRM_Utils_System::url('civicrm/dashboard', NULL, TRUE, NULL, FALSE))
23 * $http->get('route:civicrm/dashboard')
25 * $http->get(Civi::paths()->getUrl('[civicrm.files]/foo.txt'))
26 * $http->get('var:[civicrm.files]/foo.txt')
28 * $http->get(Civi::resources()->getUrl('my.other.ext', 'foo.js'))
29 * $http->get('ext:my.other.ext/foo.js')
31 * $http->get(Civi::service('asset_builder')->getUrl('my-asset.css', ['a'=>1, 'b'=>2]))
32 * $http->get('assetBuilder:my-asset.css?a=1&b=2')
34 * Note: To further simplify URL expressions, Guzzle allows you to set a 'base_uri'
35 * option (which is applied as a prefix to any relative URLs). Consider using
36 * `base_uri=auto:`. This allows you to implicitly use the most common types
39 * $http->get('civicrm/dashboard')
40 * $http->get('[civicrm.files]/foo.txt')
44 public static function url() {
45 return function(callable
$handler) {
46 return function (RequestInterface
$request, array $options) use ($handler) {
47 $newUri = self
::filterUri($request->getUri());
48 if ($newUri !== NULL) {
49 $request = $request->withUri(\CRM_Utils_Url
::parseUrl($newUri));
52 return $handler($request, $options);
58 * @param \Psr\Http\Message\UriInterface $oldUri
61 * The string formation of the new URL, or NULL for unchanged URLs.
63 protected static function filterUri(\Psr\Http\Message\UriInterface
$oldUri) {
64 // Copy the old ?query-params and #fragment-params on top of $newBase.
65 $copyParams = function ($newBase) use ($oldUri) {
66 if ($oldUri->getQuery()) {
67 $newBase .= strpos($newBase, '?') !== FALSE ?
'&' : '?';
68 $newBase .= $oldUri->getQuery();
70 if ($oldUri->getFragment()) {
71 $newBase .= '#' . $oldUri->getFragment();
76 $hostPath = urldecode($oldUri->getHost() . $oldUri->getPath());
77 $scheme = $oldUri->getScheme();
78 if ($scheme === 'auto') {
79 // Ex: 'auto:civicrm/my-page' ==> Router
80 // Ex: 'auto:[civicrm.root]/js/foo.js' ==> Resource file
81 $scheme = ($hostPath[0] === '[') ?
'var' : 'route';
86 // Ex: 'assetBuilder:dynamic.css' or 'assetBuilder://dynamic.css?foo=bar'
87 // Note: It's more useful to pass params to the asset-builder than to the final HTTP request.
89 parse_str('' . $oldUri->getQuery(), $assetParams);
90 return \Civi
::service('asset_builder')->getUrl($hostPath, $assetParams);
93 // Ex: 'ext:other.ext.name/file.js' or 'ext://other.ext.name/file.js'
94 [$ext, $file] = explode('/', $hostPath, 2);
95 return $copyParams(\Civi
::resources()->getUrl($ext, $file));
98 // Ex: 'var:[civicrm.files]/foo.txt' or 'var://[civicrm.files]/foo.txt'
99 return $copyParams(\Civi
::paths()->getUrl($hostPath, 'absolute'));
102 // Ex: 'route:civicrm/my-page' or 'route://civicrm/my-page'
103 return $copyParams(\CRM_Utils_System
::url($hostPath, NULL, TRUE, NULL, FALSE));
111 * This logs the list of outgoing requests in curl format.
113 public static function curlLog(\Psr\Log\LoggerInterface
$logger) {
115 $curlFmt = new class() extends \GuzzleHttp\MessageFormatter
{
117 public function format(RequestInterface
$request, ResponseInterface
$response = NULL, \Exception
$error = NULL) {
119 if ($request->getMethod() !== 'GET') {
120 $cmd .= ' -X ' . escapeshellarg($request->getMethod());
122 foreach ($request->getHeaders() as $header => $lines) {
123 foreach ($lines as $line) {
124 $cmd .= ' -H ' . escapeshellarg("$header: $line");
127 $body = (string) $request->getBody();
129 $cmd .= ' -d ' . escapeshellarg($body);
131 $cmd .= ' ' . escapeshellarg((string) $request->getUri());
137 return \GuzzleHttp\Middleware
::log($logger, $curlFmt);