server/src/app/Libraries/Sparql/TimeoutSparqlClient.php
changeset 387 7fba86fa8604
--- /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 @@
+<?php
+namespace CorpusParole\Libraries\Sparql;
+
+use EasyRdf\Sparql\Client;
+use EasyRdf\Exception;
+use EasyRdf\Format;
+use EasyRdf\Http;
+
+class TimeoutSparqlClient extends Client {
+
+    public function query($query, $timeout=0)
+    {
+        return $this->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();
+    }
+
+
+}