$data);
$url = url($this->getAbsoluteUrl($url) . '.php', $options);
$headers = array();
$content = $this->curlExec(array(
CURLOPT_HTTPGET => TRUE,
CURLOPT_URL => $url,
CURLOPT_NOBODY => FALSE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_HEADER => TRUE,
CURLOPT_HTTPHEADER => $headers
));
// Parse response.
list($info, $header, $status, $code, $body) = $this->parseHeader($content);
$this->verbose('GET request to: ' . $url .
'
Arguments: ' . highlight_string('Response: ' . highlight_string('Raw response: ' . $content);
return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
}
protected function servicesPost($url, $data = array(), $headers = array()) {
$options = array();
// Add .php to get serialized response.
$url = $this->getAbsoluteUrl($url) . '.php';
// Otherwise Services will reject arguments.
$headers = array("Content-type: application/x-www-form-urlencoded");
// Prepare arguments.
$post = http_build_query($data, '', '&');
$content = $this->curlExec(array(
CURLOPT_URL => $url,
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => $post,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_HEADER => TRUE,
CURLOPT_RETURNTRANSFER => TRUE
));
// Parse response.
list($info, $header, $status, $code, $body) = $this->parseHeader($content);
$this->verbose('POST request to: ' . $url .
'
Arguments: ' . highlight_string('Response: ' . highlight_string('Curl info: ' . highlight_string('Raw response: ' . $content);
return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
}
protected function servicesPut($url, $data = NULL, $headers = array()) {
$options = array();
$url = $this->getAbsoluteUrl($url) . '.php';
$serialize_args = serialize($data);
// Set up headers so arguments will be unserialized.
$headers = array("Content-type: application/vnd.php.serialized; charset=iso-8859-1");
// Emulate file.
$putData = fopen('php://memory', 'rw+');
fwrite($putData, $serialize_args);
fseek($putData, 0);
$content = $this->curlExec(array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_PUT => TRUE,
CURLOPT_HEADER => TRUE,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_INFILE => $putData,
CURLOPT_INFILESIZE => strlen($serialize_args)
));
fclose($putData);
// Parse response.
list($info, $header, $status, $code, $body) = $this->parseHeader($content);
$this->verbose('PUT request to: ' . $url .
'
Arguments: ' . highlight_string('Response: ' . highlight_string('Curl info: ' . highlight_string('Raw response: ' . $content);
return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
}
protected function servicesDelete($url, $data = NULL, $headers = array()) {
$options = array('query' => $data);
$url = url($this->getAbsoluteUrl($url) . '.php', $options);
$content = $this->curlExec(array(
CURLOPT_URL => $url,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => $headers,
CURLOPT_RETURNTRANSFER => TRUE
));
// Parse response.
list($info, $header, $status, $code, $body) = $this->parseHeader($content);
$this->verbose('DELETE request to: ' . $url .
'
Arguments: ' . highlight_string('Response: ' . highlight_string('Curl info: ' . highlight_string('Raw response: ' . $content);
return array('header' => $header, 'status' => $status, 'code' => $code, 'body' => $body);
}
/*
------------------------------------
HELPER METHODS
------------------------------------
*/
/**
* Parse header.
*
* @param type $content
* @return type
*/
function parseHeader($content) {
$info = curl_getinfo($this->curlHandle);
$header = substr($content, 0, $info['header_size']);
$header = str_replace("HTTP/1.1 100 Continue\r\n\r\n", '', $header);
$status = strtok($header, "\r\n");
$code = $info['http_code'];
$body = unserialize(substr($content, $info['header_size'], strlen($content) - $info['header_size']));
return array($info, $header, $status, $code, $body);
}
/**
* Creates a data array for populating an endpoint creation form.
*
* @return
* An array of fields for fully populating an endpoint creation form.
*/
public function populateEndpointFAPI() {
return array(
'name' => 'machinename',
'title' => $this->randomName(20),
'path' => $this->randomName(10),
'server' => 'rest_server',
);
}
public function saveNewEndpoint() {
$edit = $this->populateEndpointFAPI() ;
$endpoint = new stdClass;
$endpoint->disabled = FALSE; /* Edit this to true to make a default endpoint disabled initially */
$endpoint->api_version = 3;
$endpoint->name = $edit['name'];
$endpoint->title = $edit['title'];
$endpoint->server = $edit['server'];
$endpoint->path = $edit['path'];
$endpoint->authentication = array();
$endpoint->resources = array(
'node' => array(
'alias' => '',
'operations' => array(
'create' => array(
'enabled' => 1,
),
'retrieve' => array(
'enabled' => 1,
),
'update' => array(
'enabled' => 1,
),
'delete' => array(
'enabled' => 1,
),
'index' => array(
'enabled' => 1,
),
),
),
'system' => array(
'alias' => '',
'actions' => array(
'connect' => array(
'enabled' => 1,
),
'get_variable' => array(
'enabled' => 1,
),
'set_variable' => array(
'enabled' => 1,
),
),
),
'taxonomy_term' => array(
'alias' => '',
'operations' => array(
'create' => array(
'enabled' => 1,
),
'retrieve' => array(
'enabled' => 1,
),
'update' => array(
'enabled' => 1,
),
'delete' => array(
'enabled' => 1,
),
),
'actions' => array(
'selectNodes' => array(
'enabled' => 1,
),
),
),
'taxonomy_vocabulary' => array(
'alias' => '',
'operations' => array(
'create' => array(
'enabled' => 1,
),
'retrieve' => array(
'enabled' => 1,
),
'update' => array(
'enabled' => 1,
),
'delete' => array(
'enabled' => 1,
),
),
'actions' => array(
'getTree' => array(
'enabled' => 1,
),
),
),
'user' => array(
'alias' => '',
'operations' => array(
'create' => array(
'enabled' => 1,
),
'retrieve' => array(
'enabled' => 1,
),
'update' => array(
'enabled' => 1,
),
'delete' => array(
'enabled' => 1,
),
'index' => array(
'enabled' => 1,
),
),
'actions' => array(
'login' => array(
'enabled' => 1,
),
'logout' => array(
'enabled' => 1,
),
),
),
'comment' => array(
'alias' => '',
'operations' => array(
'create' => array(
'enabled' => 1,
),
'retrieve' => array(
'enabled' => 1,
),
'update' => array(
'enabled' => 1,
),
'delete' => array(
'enabled' => 1,
),
),
'actions' => array(
'loadNodeComments' => array(
'enabled' => 1,
),
'countAll' => array(
'enabled' => 1,
),
'countNew' => array(
'enabled' => 1,
),
),
),
'file' => array(
'alias' => '',
'operations' => array(
'create' => array(
'enabled' => 1,
),
'retrieve' => array(
'enabled' => 1,
),
'delete' => array(
'enabled' => 1,
),
),
'actions' => array(
'nodeFiles' => array(
'enabled' => 1,
),
),
),
'echo' => array(
'alias' => '',
'operations' => array(
'index' => array(
'enabled' => 1,
),
),
),
);
$endpoint->debug = 1;
services_endpoint_save($endpoint);
$endpoint = services_endpoint_load($endpoint->name);
$this->assertTrue($endpoint->name == $edit['name'], t('Endpoint successfully created'));
return $endpoint;
}
/**
* Performs a cURL exec with the specified options after calling curlConnect().
*
* @param $curl_options
* Custom cURL options.
* @return
* Content returned from the exec.
*/
protected function curlExec($curl_options, $redirect = FALSE) {
$this->curlInitialize();
// cURL incorrectly handles URLs with a fragment by including the
// fragment in the request to the server, causing some web servers
// to reject the request citing "400 - Bad Request". To prevent
// this, we strip the fragment from the request.
// TODO: Remove this for Drupal 8, since fixed in curl 7.20.0.
if (!empty($curl_options[CURLOPT_URL]) && strpos($curl_options[CURLOPT_URL], '#')) {
$original_url = $curl_options[CURLOPT_URL];
$curl_options[CURLOPT_URL] = strtok($curl_options[CURLOPT_URL], '#');
}
$url = empty($curl_options[CURLOPT_URL]) ? curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL) : $curl_options[CURLOPT_URL];
if (!empty($curl_options[CURLOPT_POST])) {
// This is a fix for the Curl library to prevent Expect: 100-continue
// headers in POST requests, that may cause unexpected HTTP response
// codes from some webservers (like lighttpd that returns a 417 error
// code). It is done by setting an empty "Expect" header field that is
// not overwritten by Curl.
$curl_options[CURLOPT_HTTPHEADER][] = 'Expect:';
}
curl_setopt_array($this->curlHandle, $this->additionalCurlOptions + $curl_options);
if (!$redirect) {
// Reset headers, the session ID and the redirect counter.
$this->session_id = NULL;
$this->headers = array();
$this->redirect_count = 0;
}
$content = curl_exec($this->curlHandle);
$status = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE);
// cURL incorrectly handles URLs with fragments, so instead of
// letting cURL handle redirects we take of them ourselves to
// to prevent fragments being sent to the web server as part
// of the request.
// TODO: Remove this for Drupal 8, since fixed in curl 7.20.0.
if (in_array($status, array(300, 301, 302, 303, 305, 307)) && $this->redirect_count < variable_get('simpletest_maximum_redirects', 5)) {
if ($this->drupalGetHeader('location')) {
$this->redirect_count++;
$curl_options = array();
$curl_options[CURLOPT_URL] = $this->drupalGetHeader('location');
$curl_options[CURLOPT_HTTPGET] = TRUE;
return $this->curlExec($curl_options, TRUE);
}
}
$this->drupalSetContent($content, isset($original_url) ? $original_url : curl_getinfo($this->curlHandle, CURLINFO_EFFECTIVE_URL));
// Analyze the method for log message.
$method = '';
if (!empty($curl_options[CURLOPT_NOBODY])) {
$method = 'HEAD';
}
if (empty($method) && !empty($curl_options[CURLOPT_PUT])) {
$method = 'PUT';
}
if (empty($method) && !empty($curl_options[CURLOPT_CUSTOMREQUEST])) {
$method = $curl_options[CURLOPT_CUSTOMREQUEST];
}
if (empty($method)) {
$method = empty($curl_options[CURLOPT_POSTFIELDS]) ? 'GET' : 'POST';
}
$message_vars = array(
'!method' => $method,
'@url' => isset($original_url) ? $original_url : $url,
'@status' => $status,
'!length' => format_size(strlen($this->drupalGetContent()))
);
$message = t('!method @url returned @status (!length).', $message_vars);
$this->assertTrue($this->drupalGetContent() !== FALSE, $message, t('Browser'));
return $this->drupalGetContent();
}
}