class AcquiaSearchSolrService in Acquia Connector 7.3
Class AcquiaSearchSolrService.
Hierarchy
- class \DrupalApacheSolrService implements DrupalApacheSolrServiceInterface
- class \AcquiaSearchSolrService
Expanded class hierarchy of AcquiaSearchSolrService
File
- acquia_search/
includes/ AcquiaSearchSolrService.php, line 6
View source
class AcquiaSearchSolrService extends DrupalApacheSolrService {
/**
* {@inheritdoc}
*/
public function makeServletRequest($servlet, $params = [], $options = []) {
$params += [
'wt' => 'json',
];
$nonce = AcquiaSearchSolrCrypt::randomBytes(24);
$url = $this
->_constructUrl($servlet, $params);
$this
->prepareRequest($url, $options, $nonce);
$response = $this
->_makeHttpRequest($url, $options);
$response = $this
->checkResponse($response);
return $this
->authenticateResponse($response, $nonce, $url);
}
/**
* {@inheritdoc}
*/
protected function _sendRawGet($url, $options = []) {
// phpcs:ignore
$nonce = AcquiaSearchSolrCrypt::randomBytes(24);
$this
->prepareRequest($url, $options, $nonce);
$response = $this
->_makeHttpRequest($url, $options);
$response = $this
->checkResponse($response);
return $this
->authenticateResponse($response, $nonce, $url);
}
/**
* {@inheritdoc}
*/
protected function _sendRawPost($url, $options = []) {
// phpcs:ignore
$options['method'] = 'POST';
if (!isset($options['headers']['Content-Type'])) {
$options['headers']['Content-Type'] = 'text/xml; charset=UTF-8';
}
$nonce = AcquiaSearchSolrCrypt::randomBytes(24);
$this
->prepareRequest($url, $options, $nonce);
$response = $this
->_makeHttpRequest($url, $options);
$response = $this
->checkResponse($response);
return $this
->authenticateResponse($response, $nonce, $url);
}
/**
* Prepares request before send.
*
* @param string $url
* Request URL.
* @param array $options
* Request options.
* @param string $nonce
* Nonce.
*
* @throws \Exception
*/
protected function prepareRequest(&$url, array &$options, $nonce) {
$url = $this
->adjustUrl($url);
if (!isset($options['headers'])) {
$options['headers'] = [];
}
$string = !empty($options['data']) ? $options['data'] : NULL;
$options['headers']['Cookie'] = $this
->createAuthCookie($url, $nonce, $string);
$options['headers'] += $this
->addUserAgentHeader();
}
/**
* Prepares URL parameters before request.
*
* @param string $url
* URL.
*
* @return string
* Adjusted URL.
*/
protected function adjustUrl($url) {
$url_components = parse_url($url);
if (isset($url_components['scheme'])) {
$url_components['scheme'] = sprintf('%s://', $url_components['scheme']);
}
if (!isset($url_components['query'])) {
$url_components['query'] = '';
}
$query_pieces = drupal_get_query_array($url_components['query']);
$query_pieces['request_id'] = uniqid();
$query_string = drupal_http_build_query($query_pieces);
$url_components['query'] = sprintf('?%s', $query_string);
$url = implode('', $url_components);
return $url;
}
/**
* Builds user-agent header.
*
* @return array
* User-agent header.
*/
protected function addUserAgentHeader() {
$acquia_search_version = variable_get('acquia_search_solr_version', DRUPAL_CORE_COMPATIBILITY);
$agent = sprintf('acquia_search_solr/%s', $acquia_search_version);
return [
'User-Agent' => $agent,
];
}
/**
* Makes authentication checks.
*
* @param object $response
* Response object.
* @param string $nonce
* Nonce.
* @param string $url
* Request URL.
*
* @return mixed
* Throws exception in case of authentication check fail.
*
* @throws \Exception
*/
protected function authenticateResponse($response, $nonce, $url) {
$hmac = $this
->extractHmac($response->headers);
if (!$this
->isValidResponse($hmac, $nonce, $response->data, NULL, $this->env_id)) {
throw new Exception('Authentication of search content failed url: ' . $url);
}
return $response;
}
/**
* Creates auth cookie.
*
* @param string $url
* Request URL.
* @param string $nonce
* Nonce.
* @param string $string
* Payload.
*
* @return string
* Cookie.
*/
private function createAuthCookie($url, $nonce, $string = '') {
if (!empty($string)) {
$auth_string = $this
->buildAuthString($string, $nonce);
return $auth_string;
}
$uri = parse_url($url);
$path = isset($uri['path']) ? $uri['path'] : '/';
$query = isset($uri['query']) ? '?' . $uri['query'] : '';
$auth_string = $this
->buildAuthString($path . $query, $nonce);
return $auth_string;
}
/**
* Builds auth string.
*
* @param string $string
* Payload.
* @param string $nonce
* Nonce.
*
* @return string
* Auth string.
*/
private function buildAuthString($string, $nonce) {
$api = _acquia_search_solr_get_api();
if (empty($api)) {
return '';
}
$preferredIndexService = $api
->getPreferredIndexService();
if (empty($preferredIndexService
->isPreferredIndexAvailable())) {
return '';
}
$index = $preferredIndexService
->getPreferredIndex();
$derived_key = $this
->createDerivedKey($index['data']['product_policies']['salt'], $index['data']['key'], $index['data']['secret_key']);
$hmac = hash_hmac('sha1', REQUEST_TIME . $nonce . $string, $derived_key);
return sprintf('acquia_solr_time=%s; acquia_solr_nonce=%s; acquia_solr_hmac=%s;', REQUEST_TIME, $nonce, $hmac);
}
/**
* Creates derived key.
*
* @param string $salt
* Key salt.
* @param string $index_id
* Index ID.
* @param string $key
* Secret key.
*
* @return string
* Derived key.
*/
private function createDerivedKey($salt, $index_id, $key) {
$pad_length = 80;
$derivation_string = sprintf('%ssolr%s', $index_id, $salt);
$data = str_pad($derivation_string, $pad_length, $derivation_string);
$hmac = hash_hmac('sha1', $data, $key);
return $hmac;
}
/**
* Extracts HMAC value from headers.
*
* @param array $headers
* Headers list.
*
* @return string
* HMAC string.
*/
private function extractHmac(array $headers) {
$reg = [];
if (is_array($headers)) {
foreach ($headers as $name => $value) {
if (strtolower($name) === 'pragma' && preg_match('/hmac_digest=([^;]+);/i', $value, $reg)) {
return trim($reg[1]);
}
}
}
return '';
}
/**
* Validates response.
*
* @param string $hmac
* HMAC string.
* @param string $nonce
* Nonce.
* @param string $string
* Payload.
* @param string|null $derived_key
* Derived key.
* @param string|null $env_id
* Search environment ID.
*
* @return bool
* TRUE if request is valid, otherwise - FALSE.
*/
private function isValidResponse($hmac, $nonce, $string, $derived_key = NULL, $env_id = NULL) {
if (empty($env_id)) {
$env_id = apachesolr_default_environment();
}
if (empty($derived_key)) {
$environment = apachesolr_environment_load($env_id);
if (empty($environment['url'])) {
return FALSE;
}
$index_id = substr($environment['url'], strrpos($environment['url'], '/') + 1);
$api = _acquia_search_solr_get_api();
if (empty($api)) {
return FALSE;
}
$indexes = $api
->getIndexes();
if (empty($indexes[$index_id]['data'])) {
return FALSE;
}
$derived_key = $this
->createDerivedKey($indexes[$index_id]['data']['product_policies']['salt'], $indexes[$index_id]['data']['key'], $indexes[$index_id]['data']['secret_key']);
}
return $hmac === hash_hmac('sha1', $nonce . $string, $derived_key);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
AcquiaSearchSolrService:: |
protected | function | Builds user-agent header. | |
AcquiaSearchSolrService:: |
protected | function | Prepares URL parameters before request. | |
AcquiaSearchSolrService:: |
protected | function | Makes authentication checks. | |
AcquiaSearchSolrService:: |
private | function | Builds auth string. | |
AcquiaSearchSolrService:: |
private | function | Creates auth cookie. | |
AcquiaSearchSolrService:: |
private | function | Creates derived key. | |
AcquiaSearchSolrService:: |
private | function | Extracts HMAC value from headers. | |
AcquiaSearchSolrService:: |
private | function | Validates response. | |
AcquiaSearchSolrService:: |
public | function |
Make a request to a servlet (a path) that's not a standard path. Overrides DrupalApacheSolrService:: |
|
AcquiaSearchSolrService:: |
protected | function | Prepares request before send. | |
AcquiaSearchSolrService:: |
protected | function |
Central method for making a GET operation against this Solr Server Overrides DrupalApacheSolrService:: |
|
AcquiaSearchSolrService:: |
protected | function |
Central method for making a POST operation against this Solr Server Overrides DrupalApacheSolrService:: |
|
DrupalApacheSolrService:: |
protected | property | ||
DrupalApacheSolrService:: |
protected | property | ||
DrupalApacheSolrService:: |
protected | property | Server url | |
DrupalApacheSolrService:: |
protected | property | Flag that denotes whether to use soft commits for Solr 4.x, defaults to FALSE. | |
DrupalApacheSolrService:: |
protected | property | ||
DrupalApacheSolrService:: |
protected | property | ||
DrupalApacheSolrService:: |
protected | property | Constructed servlet full path URLs | |
DrupalApacheSolrService:: |
protected | property | Default HTTP timeout when one is not specified (initialized to default_socket_timeout ini setting) | |
DrupalApacheSolrService:: |
public | function |
Add an array of Solr Documents to the index all at once Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
protected | function | Check the reponse code and thow an exception if it's not 200. | |
DrupalApacheSolrService:: |
public | function |
Clear cached Solr data. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public | function |
Send a commit command. Will be synchronous unless both wait parameters are set to false. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public | function |
Create a delete document based on document ID Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public | function |
Create and post a delete document based on multiple document IDs. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public | function |
Create a delete document based on a query and submit it Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public static | function | Escape a value for special query characters such as ':', '(', ')', '*', '?', etc. | |
DrupalApacheSolrService:: |
public static | function | Escape a value meant to be contained in a phrase for special query characters | |
DrupalApacheSolrService:: |
public | function | Determine the routine that called this query. | |
DrupalApacheSolrService:: |
public | function |
Get just the field meta-data about the index. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
function |
Overrides DrupalApacheSolrServiceInterface:: |
||
DrupalApacheSolrService:: |
public | function |
Get meta-data about the index. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public | function | Returns the flag that denotes whether to use soft commits for Solr 4.x. | |
DrupalApacheSolrService:: |
public | function |
Get the current solr version. This could be 1, 3 or 4 Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public | function |
Get information about the Solr Core. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public | function |
Get summary information about the Solr Core. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public | function |
Get information about the Solr Core. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public | function |
Get the Solr url Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
protected | function | Like PHP's built in http_build_query(), but uses rawurlencode() and no [] for repeated params. | |
DrupalApacheSolrService:: |
constant | |||
DrupalApacheSolrService:: |
constant | How NamedLists should be formatted in the output. This specifically effects facet counts. Valid values are 'map' (default) or 'flat'. | ||
DrupalApacheSolrService:: |
public | function |
Send an optimize command. Will be synchronous unless both wait parameters are set
to false. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
public static | function | Convenience function for creating phrase syntax from a value | |
DrupalApacheSolrService:: |
public | function |
Call the /admin/ping servlet, to test the connection to the server. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
constant | Servlet mappings | ||
DrupalApacheSolrService:: |
public | function |
Simple Search interface Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
constant | |||
DrupalApacheSolrService:: |
protected | function | Sets $this->luke with the meta-data about the index from admin/luke. | |
DrupalApacheSolrService:: |
public | function | Flags whether to use soft commits for Solr 4.x. | |
DrupalApacheSolrService:: |
protected | function | Sets $this->stats with the information about the Solr Core form | |
DrupalApacheSolrService:: |
protected | function | Call the /admin/system servlet | |
DrupalApacheSolrService:: |
public | function |
Set the Solr url. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
constant | |||
DrupalApacheSolrService:: |
constant | |||
DrupalApacheSolrService:: |
constant | |||
DrupalApacheSolrService:: |
public | function |
Raw update Method. Takes a raw post body and sends it to the update service. Post body
should be a complete and well formed xml document. Overrides DrupalApacheSolrServiceInterface:: |
|
DrupalApacheSolrService:: |
constant | |||
DrupalApacheSolrService:: |
protected | function | ||
DrupalApacheSolrService:: |
protected | function | Return a valid http URL given this server's host, port and path and a provided servlet name | |
DrupalApacheSolrService:: |
protected | function | Central method for making the actual http request to the Solr Server | |
DrupalApacheSolrService:: |
public | function |
Constructor Overrides DrupalApacheSolrServiceInterface:: |