[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Virtual HTTP service client for Swift 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * http://www.gnu.org/copyleft/gpl.html 19 * 20 * @file 21 */ 22 23 /** 24 * Example virtual rest service for OpenStack Swift 25 * @TODO: caching support (APC/memcached) 26 * @since 1.23 27 */ 28 class SwiftVirtualRESTService extends VirtualRESTService { 29 /** @var array */ 30 protected $authCreds; 31 /** @var int UNIX timestamp */ 32 protected $authSessionTimestamp = 0; 33 /** @var int UNIX timestamp */ 34 protected $authErrorTimestamp = null; 35 /** @var int */ 36 protected $authCachedStatus = null; 37 /** @var string */ 38 protected $authCachedReason = null; 39 40 /** 41 * @param array $params Key/value map 42 * - swiftAuthUrl : Swift authentication server URL 43 * - swiftUser : Swift user used by MediaWiki (account:username) 44 * - swiftKey : Swift authentication key for the above user 45 * - swiftAuthTTL : Swift authentication TTL (seconds) 46 */ 47 public function __construct( array $params ) { 48 parent::__construct( $params ); 49 } 50 51 /** 52 * @return int|bool HTTP status on cached failure 53 */ 54 protected function needsAuthRequest() { 55 if ( !$this->authCreds ) { 56 return true; 57 } 58 if ( $this->authErrorTimestamp !== null ) { 59 if ( ( time() - $this->authErrorTimestamp ) < 60 ) { 60 return $this->authCachedStatus; // failed last attempt; don't bother 61 } else { // actually retry this time 62 $this->authErrorTimestamp = null; 63 } 64 } 65 // Session keys expire after a while, so we renew them periodically 66 return ( ( time() - $this->authSessionTimestamp ) > $this->params['swiftAuthTTL'] ); 67 } 68 69 protected function applyAuthResponse( array $req ) { 70 $this->authSessionTimestamp = 0; 71 list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $req['response']; 72 if ( $rcode >= 200 && $rcode <= 299 ) { // OK 73 $this->authCreds = array( 74 'auth_token' => $rhdrs['x-auth-token'], 75 'storage_url' => $rhdrs['x-storage-url'] 76 ); 77 $this->authSessionTimestamp = time(); 78 return true; 79 } elseif ( $rcode === 403 ) { 80 $this->authCachedStatus = 401; 81 $this->authCachedReason = 'Authorization Required'; 82 $this->authErrorTimestamp = time(); 83 return false; 84 } else { 85 $this->authCachedStatus = $rcode; 86 $this->authCachedReason = $rdesc; 87 $this->authErrorTimestamp = time(); 88 return null; 89 } 90 } 91 92 public function onRequests( array $reqs, Closure $idGeneratorFunc ) { 93 $result = array(); 94 $firstReq = reset( $reqs ); 95 if ( $firstReq && count( $reqs ) == 1 && isset( $firstReq['isAuth'] ) ) { 96 // This was an authentication request for work requests... 97 $result = $reqs; // no change 98 } else { 99 // These are actual work requests... 100 $needsAuth = $this->needsAuthRequest(); 101 if ( $needsAuth === true ) { 102 // These are work requests and we don't have any token to use. 103 // Replace the work requests with an authentication request. 104 $result = array( 105 $idGeneratorFunc() => array( 106 'method' => 'GET', 107 'url' => $this->params['swiftAuthUrl'] . "/v1.0", 108 'headers' => array( 109 'x-auth-user' => $this->params['swiftUser'], 110 'x-auth-key' => $this->params['swiftKey'] ), 111 'isAuth' => true, 112 'chain' => $reqs 113 ) 114 ); 115 } elseif ( $needsAuth !== false ) { 116 // These are work requests and authentication has previously failed. 117 // It is most efficient to just give failed pseudo responses back for 118 // the original work requests. 119 foreach ( $reqs as $key => $req ) { 120 $req['response'] = array( 121 'code' => $this->authCachedStatus, 122 'reason' => $this->authCachedReason, 123 'headers' => array(), 124 'body' => '', 125 'error' => '' 126 ); 127 $result[$key] = $req; 128 } 129 } else { 130 // These are work requests and we have a token already. 131 // Go through and mangle each request to include a token. 132 foreach ( $reqs as $key => $req ) { 133 // The default encoding treats the URL as a REST style path that uses 134 // forward slash as a hierarchical delimiter (and never otherwise). 135 // Subclasses can override this, and should be documented in any case. 136 $parts = array_map( 'rawurlencode', explode( '/', $req['url'] ) ); 137 $req['url'] = $this->authCreds['storage_url'] . '/' . implode( '/', $parts ); 138 $req['headers']['x-auth-token'] = $this->authCreds['auth_token']; 139 $result[$key] = $req; 140 // @TODO: add ETag/Content-Length and such as needed 141 } 142 } 143 } 144 return $result; 145 } 146 147 public function onResponses( array $reqs, Closure $idGeneratorFunc ) { 148 $firstReq = reset( $reqs ); 149 if ( $firstReq && count( $reqs ) == 1 && isset( $firstReq['isAuth'] ) ) { 150 $result = array(); 151 // This was an authentication request for work requests... 152 if ( $this->applyAuthResponse( $firstReq ) ) { 153 // If it succeeded, we can subsitute the work requests back. 154 // Call this recursively in order to munge and add headers. 155 $result = $this->onRequests( $firstReq['chain'], $idGeneratorFunc ); 156 } else { 157 // If it failed, it is most efficient to just give failing 158 // pseudo-responses back for the actual work requests. 159 foreach ( $firstReq['chain'] as $key => $req ) { 160 $req['response'] = array( 161 'code' => $this->authCachedStatus, 162 'reason' => $this->authCachedReason, 163 'headers' => array(), 164 'body' => '', 165 'error' => '' 166 ); 167 $result[$key] = $req; 168 } 169 } 170 } else { 171 $result = $reqs; // no change 172 } 173 return $result; 174 } 175 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |