Skip to content

Extending The Datasource

tenebrousedge edited this page Dec 26, 2012 · 2 revisions

Refreshing Expired Tokens

In the Database Config page you may have noticed a suggestion that using static OAuth 2.0 credentials was a bad idea. You may also have noticed that expired tokens are refreshed when they are retrieved from storage. The ApisSource datasource provides no methods for detecting token expiration. Additionally, it is highly unlikely that any methods could be implemented, as the behavior of the API at that point is not defined. Most APIs will return a 403 error, but this might also be returned for other reasons.

When using static OAuth 2.0 credentials, it is highly likely that you will end up using an expired token, whereas most other implementations should be able to avoid this. It will therefore be imperative that you detect this error and recover from it.

This guide can only offer a general guideline to how token refreshing might be implemented. Do not use the example; write your own version. That goes double if you're using static OAuth 2.0 credentials.

<?php
	#filename: Plugin/Example/Model/Datasource/ExampleSource.php

	class ExampleSource extends ApisSource {
		public function afterRequest(Model $model, HttpSocketResponse $response){
			if($response->code == 403 && !(strpos($response->body, 'Expired Token') === false)){
				$id = AuthComponent::user('id');
				$model->authorize($model, $id);
				return $this->request($model);
			}
			return parent::afterRequest($model, $response);
	}

Last Minute Changes

The other big reason for extending the APIs datasource is to implement the beforeRequest() callback. Changing the behavior of decode() and the logging functions may also be advisable.
	#filename: Plugin/Example/Model/Datasource/ExampleSource.php

	<?php
	App::uses('ApisSource', 'Copula.Model/Datasource');
	class ExampleSource extends ApisSource {
		// Key => Values substitutions in the uri-path right before the request is made. Scans uri-path for :keyname
		public $tokens = array();
		// Last minute tweaks
		public function beforeRequest(Model $model) {
			$model->request['header']['x-li-format'] = $this->options['format'];
			return $model->request;
		}
	}

It should be noted that the beforeRequest() callback should return the request array. Similarly, afterRequest() should return the (possibly processed) results.