diff -r c731ab9b934d -r 7fba86fa8604 server/src/app/Libraries/Sparql/TimeoutSparqlClient.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/app/Libraries/Sparql/TimeoutSparqlClient.php Thu Nov 03 01:52:26 2016 +0100 @@ -0,0 +1,100 @@ +request('query', $query, $timeout); + } + + protected function request($type, $query, $timeout=0) + { + $processed_query = $this->preprocessQuery($query); + $response = $this->executeQuery($processed_query, $type, $timeout); + if (!$response->isSuccessful()) { + throw new Http\Exception("HTTP request for SPARQL query failed", 0, null, $response->getBody()); + } + if ($response->getStatus() == 204) { + // No content + return $response; + } + return $this->parseResponseToQuery($response); + } + + /** + * Build http-client object, execute request and return a response + * + * @param string $processed_query + * @param string $type Should be either "query" or "update" + * + * @return Http\Response|\Zend\Http\Response + * @throws Exception + */ + protected function executeQuery($processed_query, $type, $timeout=0) + { + $client = Http::getDefaultHttpClient(); + $client->resetParameters(); + // Tell the server which response formats we can parse + $sparql_results_types = array( + 'application/sparql-results+json' => 1.0, + 'application/sparql-results+xml' => 0.8 + ); + if ($type == 'update') { + // accept anything, as "response body of a […] update request is implementation defined" + // @see http://www.w3.org/TR/sparql11-protocol/#update-success + $accept = Format::getHttpAcceptHeader($sparql_results_types); + $client->setHeaders('Accept', $accept); + $client->setMethod('POST'); + $client->setUri($this->updateUri); + $client->setRawData($processed_query); + $client->setHeaders('Content-Type', 'application/sparql-update'); + } elseif ($type == 'query') { + $re = '(?:(?:\s*BASE\s*<.*?>\s*)|(?:\s*PREFIX\s+.+:\s*<.*?>\s*))*'. + '(CONSTRUCT|SELECT|ASK|DESCRIBE)[\W]'; + $result = null; + $matched = mb_eregi($re, $processed_query, $result); + if (false === $matched or count($result) !== 2) { + // non-standard query. is this something non-standard? + $query_verb = null; + } else { + $query_verb = strtoupper($result[1]); + } + if ($query_verb === 'SELECT' or $query_verb === 'ASK') { + // only "results" + $accept = Format::formatAcceptHeader($sparql_results_types); + } elseif ($query_verb === 'CONSTRUCT' or $query_verb === 'DESCRIBE') { + // only "graph" + $accept = Format::getHttpAcceptHeader(); + } else { + // both + $accept = Format::getHttpAcceptHeader($sparql_results_types); + } + $client->setHeaders('Accept', $accept); + $encodedQuery = 'query=' . urlencode($processed_query).(($timeout>0)?"&timeout=$timeout":""); + // Use GET if the query is less than 2kB + // 2046 = 2kB minus 1 for '?' and 1 for NULL-terminated string on server + if (strlen($encodedQuery) + strlen($this->queryUri) <= 2046) { + $delimiter = $this->queryUri_has_params ? '&' : '?'; + $client->setMethod('GET'); + $client->setUri($this->queryUri . $delimiter . $encodedQuery); + } else { + // Fall back to POST instead (which is un-cacheable) + $client->setMethod('POST'); + $client->setUri($this->queryUri); + $client->setRawData($encodedQuery); + $client->setHeaders('Content-Type', 'application/x-www-form-urlencoded'); + } + } else { + throw new Exception('unexpected request-type: '.$type); + } + return $client->request(); + } + + +}