server/src/app/Libraries/Sparql/TimeoutSparqlClient.php
changeset 387 7fba86fa8604
equal deleted inserted replaced
386:c731ab9b934d 387:7fba86fa8604
       
     1 <?php
       
     2 namespace CorpusParole\Libraries\Sparql;
       
     3 
       
     4 use EasyRdf\Sparql\Client;
       
     5 use EasyRdf\Exception;
       
     6 use EasyRdf\Format;
       
     7 use EasyRdf\Http;
       
     8 
       
     9 class TimeoutSparqlClient extends Client {
       
    10 
       
    11     public function query($query, $timeout=0)
       
    12     {
       
    13         return $this->request('query', $query, $timeout);
       
    14     }
       
    15 
       
    16     protected function request($type, $query, $timeout=0)
       
    17     {
       
    18         $processed_query = $this->preprocessQuery($query);
       
    19         $response = $this->executeQuery($processed_query, $type, $timeout);
       
    20         if (!$response->isSuccessful()) {
       
    21             throw new Http\Exception("HTTP request for SPARQL query failed", 0, null, $response->getBody());
       
    22         }
       
    23         if ($response->getStatus() == 204) {
       
    24             // No content
       
    25             return $response;
       
    26         }
       
    27         return $this->parseResponseToQuery($response);
       
    28     }
       
    29 
       
    30     /**
       
    31      * Build http-client object, execute request and return a response
       
    32      *
       
    33      * @param string $processed_query
       
    34      * @param string $type            Should be either "query" or "update"
       
    35      *
       
    36      * @return Http\Response|\Zend\Http\Response
       
    37      * @throws Exception
       
    38      */
       
    39     protected function executeQuery($processed_query, $type, $timeout=0)
       
    40     {
       
    41         $client = Http::getDefaultHttpClient();
       
    42         $client->resetParameters();
       
    43         // Tell the server which response formats we can parse
       
    44         $sparql_results_types = array(
       
    45             'application/sparql-results+json' => 1.0,
       
    46             'application/sparql-results+xml' => 0.8
       
    47         );
       
    48         if ($type == 'update') {
       
    49             // accept anything, as "response body of a […] update request is implementation defined"
       
    50             // @see http://www.w3.org/TR/sparql11-protocol/#update-success
       
    51             $accept = Format::getHttpAcceptHeader($sparql_results_types);
       
    52             $client->setHeaders('Accept', $accept);
       
    53             $client->setMethod('POST');
       
    54             $client->setUri($this->updateUri);
       
    55             $client->setRawData($processed_query);
       
    56             $client->setHeaders('Content-Type', 'application/sparql-update');
       
    57         } elseif ($type == 'query') {
       
    58             $re = '(?:(?:\s*BASE\s*<.*?>\s*)|(?:\s*PREFIX\s+.+:\s*<.*?>\s*))*'.
       
    59                 '(CONSTRUCT|SELECT|ASK|DESCRIBE)[\W]';
       
    60             $result = null;
       
    61             $matched = mb_eregi($re, $processed_query, $result);
       
    62             if (false === $matched or count($result) !== 2) {
       
    63                 // non-standard query. is this something non-standard?
       
    64                 $query_verb = null;
       
    65             } else {
       
    66                 $query_verb = strtoupper($result[1]);
       
    67             }
       
    68             if ($query_verb === 'SELECT' or $query_verb === 'ASK') {
       
    69                 // only "results"
       
    70                 $accept = Format::formatAcceptHeader($sparql_results_types);
       
    71             } elseif ($query_verb === 'CONSTRUCT' or $query_verb === 'DESCRIBE') {
       
    72                 // only "graph"
       
    73                 $accept = Format::getHttpAcceptHeader();
       
    74             } else {
       
    75                 // both
       
    76                 $accept = Format::getHttpAcceptHeader($sparql_results_types);
       
    77             }
       
    78             $client->setHeaders('Accept', $accept);
       
    79             $encodedQuery = 'query=' . urlencode($processed_query).(($timeout>0)?"&timeout=$timeout":"");
       
    80             // Use GET if the query is less than 2kB
       
    81             // 2046 = 2kB minus 1 for '?' and 1 for NULL-terminated string on server
       
    82             if (strlen($encodedQuery) + strlen($this->queryUri) <= 2046) {
       
    83                 $delimiter = $this->queryUri_has_params ? '&' : '?';
       
    84                 $client->setMethod('GET');
       
    85                 $client->setUri($this->queryUri . $delimiter . $encodedQuery);
       
    86             } else {
       
    87                 // Fall back to POST instead (which is un-cacheable)
       
    88                 $client->setMethod('POST');
       
    89                 $client->setUri($this->queryUri);
       
    90                 $client->setRawData($encodedQuery);
       
    91                 $client->setHeaders('Content-Type', 'application/x-www-form-urlencoded');
       
    92             }
       
    93         } else {
       
    94             throw new Exception('unexpected request-type: '.$type);
       
    95         }
       
    96         return $client->request();
       
    97     }
       
    98 
       
    99 
       
   100 }