public function _fetch ($url, $method, $params) {
		if (! extension_loaded ('curl')) {
			$this->error = 'cURL extension not loaded.';
			return false;
		}

		$ch = curl_init ();
		curl_setopt ($ch, CURLOPT_URL, $url);
		curl_setopt ($ch, CURLOPT_MAXREDIRS, 3);
		curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 0);
		curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt ($ch, CURLOPT_VERBOSE, 0);
		curl_setopt ($ch, CURLOPT_HEADER, 1);
		curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 10);
		curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
		curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);

		/* HTTP Basic Authentication */
		if ($this->user && $this->password) {
			curl_setopt ($ch, CURLOPT_USERPWD, $this->user . ":" . $this->password);	
		}

		if ($this->request_format == 'xml') {
			$this->request_headers = array_merge ($this->request_headers, array ("Expect:", "Content-Type: text/xml", "Length: " . strlen ($params)));
		}
		switch ($method) {
			case 'POST':
				curl_setopt ($ch, CURLOPT_POST, 1);
				curl_setopt ($ch, CURLOPT_POSTFIELDS, $params);
				break;
			case 'DELETE':
				curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
				break;
			case 'PUT':
				curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
				curl_setopt ($ch, CURLOPT_POSTFIELDS, $params);
				break;
			case 'GET':
			default:
				break;
		}

		if (count ($this->request_headers)) {
			curl_setopt ($ch, CURLOPT_HTTPHEADER, $this->request_headers);
		}

		$res = curl_exec ($ch);

		$http_code = curl_getinfo ($ch, CURLINFO_HTTP_CODE);

		// Check HTTP status code for denied access
		if ($http_code == 401) {
			$this->errno = $http_code;
			$this->error = "HTTP Basic: Access denied.";
			curl_close ($ch);
			return false;
		}

		// Check HTTP status code for rate limit
		if ($http_code == 429) {
			if (preg_match ('/Retry-After: ([0-9]+)/', $res, $retry_after)) {
			  sleep(intval($retry_after[1]));
			  return $this->_fetch ($url, $method, $params);
			}
			$this->errno = $http_code;
			$this->error = "Too Many Requests";
			curl_close ($ch);
			return false;
		}

		if (! $res) {
			$this->errno = curl_errno ($ch);
			$this->error = curl_error ($ch);
			curl_close ($ch);
			return false;
		}

		curl_close ($ch);
		return $res;
	}