MediaWiki  1.34.0
SwiftVirtualRESTService.php
Go to the documentation of this file.
1 <?php
30  protected $authCreds;
32  protected $authSessionTimestamp = 0;
34  protected $authErrorTimestamp = null;
36  protected $authCachedStatus = null;
38  protected $authCachedReason = null;
39 
47  public function __construct( array $params ) {
48  // set up defaults and merge them with the given params
49  $mparams = array_merge( [
50  'name' => 'swift'
51  ], $params );
52  parent::__construct( $mparams );
53  }
54 
58  protected function needsAuthRequest() {
59  if ( !$this->authCreds ) {
60  return true;
61  }
62  if ( $this->authErrorTimestamp !== null ) {
63  if ( ( time() - $this->authErrorTimestamp ) < 60 ) {
64  return $this->authCachedStatus; // failed last attempt; don't bother
65  } else { // actually retry this time
66  $this->authErrorTimestamp = null;
67  }
68  }
69  // Session keys expire after a while, so we renew them periodically
70  return ( ( time() - $this->authSessionTimestamp ) > $this->params['swiftAuthTTL'] );
71  }
72 
73  protected function applyAuthResponse( array $req ) {
74  $this->authSessionTimestamp = 0;
75  list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $req['response'];
76  if ( $rcode >= 200 && $rcode <= 299 ) { // OK
77  $this->authCreds = [
78  'auth_token' => $rhdrs['x-auth-token'],
79  'storage_url' => $rhdrs['x-storage-url']
80  ];
81  $this->authSessionTimestamp = time();
82  return true;
83  } elseif ( $rcode === 403 ) {
84  $this->authCachedStatus = 401;
85  $this->authCachedReason = 'Authorization Required';
86  $this->authErrorTimestamp = time();
87  return false;
88  } else {
89  $this->authCachedStatus = $rcode;
90  $this->authCachedReason = $rdesc;
91  $this->authErrorTimestamp = time();
92  return null;
93  }
94  }
95 
96  public function onRequests( array $reqs, Closure $idGeneratorFunc ) {
97  $result = [];
98  $firstReq = reset( $reqs );
99  if ( $firstReq && count( $reqs ) == 1 && isset( $firstReq['isAuth'] ) ) {
100  // This was an authentication request for work requests...
101  $result = $reqs; // no change
102  } else {
103  // These are actual work requests...
104  $needsAuth = $this->needsAuthRequest();
105  if ( $needsAuth === true ) {
106  // These are work requests and we don't have any token to use.
107  // Replace the work requests with an authentication request.
108  $result = [
109  $idGeneratorFunc() => [
110  'method' => 'GET',
111  'url' => $this->params['swiftAuthUrl'] . "/v1.0",
112  'headers' => [
113  'x-auth-user' => $this->params['swiftUser'],
114  'x-auth-key' => $this->params['swiftKey'] ],
115  'isAuth' => true,
116  'chain' => $reqs
117  ]
118  ];
119  } elseif ( $needsAuth !== false ) {
120  // These are work requests and authentication has previously failed.
121  // It is most efficient to just give failed pseudo responses back for
122  // the original work requests.
123  foreach ( $reqs as $key => $req ) {
124  $req['response'] = [
125  'code' => $this->authCachedStatus,
126  'reason' => $this->authCachedReason,
127  'headers' => [],
128  'body' => '',
129  'error' => ''
130  ];
131  $result[$key] = $req;
132  }
133  } else {
134  // These are work requests and we have a token already.
135  // Go through and mangle each request to include a token.
136  foreach ( $reqs as $key => $req ) {
137  // The default encoding treats the URL as a REST style path that uses
138  // forward slash as a hierarchical delimiter (and never otherwise).
139  // Subclasses can override this, and should be documented in any case.
140  $parts = array_map( 'rawurlencode', explode( '/', $req['url'] ) );
141  $req['url'] = $this->authCreds['storage_url'] . '/' . implode( '/', $parts );
142  $req['headers']['x-auth-token'] = $this->authCreds['auth_token'];
143  $result[$key] = $req;
144  // @TODO: add ETag/Content-Length and such as needed
145  }
146  }
147  }
148  return $result;
149  }
150 
151  public function onResponses( array $reqs, Closure $idGeneratorFunc ) {
152  $firstReq = reset( $reqs );
153  if ( $firstReq && count( $reqs ) == 1 && isset( $firstReq['isAuth'] ) ) {
154  $result = [];
155  // This was an authentication request for work requests...
156  if ( $this->applyAuthResponse( $firstReq ) ) {
157  // If it succeeded, we can subsitute the work requests back.
158  // Call this recursively in order to munge and add headers.
159  $result = $this->onRequests( $firstReq['chain'], $idGeneratorFunc );
160  } else {
161  // If it failed, it is most efficient to just give failing
162  // pseudo-responses back for the actual work requests.
163  foreach ( $firstReq['chain'] as $key => $req ) {
164  $req['response'] = [
165  'code' => $this->authCachedStatus,
166  'reason' => $this->authCachedReason,
167  'headers' => [],
168  'body' => '',
169  'error' => ''
170  ];
171  $result[$key] = $req;
172  }
173  }
174  } else {
175  $result = $reqs; // no change
176  }
177  return $result;
178  }
179 }
SwiftVirtualRESTService\onRequests
onRequests(array $reqs, Closure $idGeneratorFunc)
Prepare virtual HTTP(S) requests (for this service) for execution.
Definition: SwiftVirtualRESTService.php:96
SwiftVirtualRESTService\$authCachedStatus
int $authCachedStatus
Definition: SwiftVirtualRESTService.php:36
SwiftVirtualRESTService\$authCachedReason
string $authCachedReason
Definition: SwiftVirtualRESTService.php:38
SwiftVirtualRESTService\needsAuthRequest
needsAuthRequest()
Definition: SwiftVirtualRESTService.php:58
SwiftVirtualRESTService\applyAuthResponse
applyAuthResponse(array $req)
Definition: SwiftVirtualRESTService.php:73
SwiftVirtualRESTService\$authErrorTimestamp
int $authErrorTimestamp
UNIX timestamp.
Definition: SwiftVirtualRESTService.php:34
SwiftVirtualRESTService\onResponses
onResponses(array $reqs, Closure $idGeneratorFunc)
Mangle or replace virtual HTTP(S) requests which have been responded to.
Definition: SwiftVirtualRESTService.php:151
SwiftVirtualRESTService\__construct
__construct(array $params)
Definition: SwiftVirtualRESTService.php:47
SwiftVirtualRESTService
Example virtual rest service for OpenStack Swift.
Definition: SwiftVirtualRESTService.php:28
SwiftVirtualRESTService\$authCreds
array $authCreds
Definition: SwiftVirtualRESTService.php:30
VirtualRESTService
Virtual HTTP service instance that can be mounted on to a VirtualRESTService.
Definition: VirtualRESTService.php:36
SwiftVirtualRESTService\$authSessionTimestamp
int $authSessionTimestamp
UNIX timestamp.
Definition: SwiftVirtualRESTService.php:32
VirtualRESTService\$params
array $params
Key/value map.
Definition: VirtualRESTService.php:38