dydra / support

4 stars 1 forks source link

rdf4j 3.1.0 unable to report endpoint errors #59

Open knoan opened 4 years ago

knoan commented 4 years ago

how to reproduce

Attempt to submit a malformed query to a dydra endpoint using rdf4j 3.1.0, e.g.

final Repository repository=new SPARQLRepository("https://dydra.com/{user}/{repository}/sparql");

repository.init();

try (final RepositoryConnection connection=repository.getConnection()) {

    connection.prepareBooleanQuery("malformed").evaluate();

} finally {

    repository.shutDown();

}

expected result

An exception detailing the syntax error.

actual results

An exception complaining about the premature end of chunk.

Exception in thread "main" org.eclipse.rdf4j.query.QueryEvaluationException: Unable to retrieve error info from server
    at org.eclipse.rdf4j.repository.sparql.query.SPARQLBooleanQuery.evaluate(SPARQLBooleanQuery.java:40)
    at com.example.com.Work.main(Work.java:22)
Caused by: org.eclipse.rdf4j.repository.RepositoryException: Unable to retrieve error info from server
    at org.eclipse.rdf4j.http.client.SPARQLProtocolSession.getErrorInfo(SPARQLProtocolSession.java:1061)
    at org.eclipse.rdf4j.http.client.SPARQLProtocolSession.execute(SPARQLProtocolSession.java:1000)
    at org.eclipse.rdf4j.http.client.SPARQLProtocolSession.executeOK(SPARQLProtocolSession.java:950)
    at org.eclipse.rdf4j.http.client.SPARQLProtocolSession.sendBooleanQueryViaHttp(SPARQLProtocolSession.java:938)
    at org.eclipse.rdf4j.http.client.SPARQLProtocolSession.getBoolean(SPARQLProtocolSession.java:888)
    at org.eclipse.rdf4j.http.client.SPARQLProtocolSession.sendBooleanQuery(SPARQLProtocolSession.java:438)
    at org.eclipse.rdf4j.repository.sparql.query.SPARQLBooleanQuery.evaluate(SPARQLBooleanQuery.java:37)
    ... 1 more
Caused by: org.apache.http.ConnectionClosedException: Premature end of chunk coded message body: closing chunk expected
    at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:263)
    at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:222)
    at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:183)
    at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:135)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.Reader.read(Reader.java:140)
    at org.apache.http.util.EntityUtils.toString(EntityUtils.java:227)
    at org.apache.http.util.EntityUtils.toString(EntityUtils.java:308)
    at org.eclipse.rdf4j.http.client.SPARQLProtocolSession.getErrorInfo(SPARQLProtocolSession.java:1056)
    ... 7 more
lisp commented 4 years ago

in some regards, this is a deficiency in rdf4j.

on the occurrence of an error, the server reports the error and closes the connection with prejudice. while this does yield an incomplete message, the error is reported:

` ~ jamesanderson$ curl -H "Content-Type: application/sparql-query" -H "Accept: application/sparql-results+json" -X POST --data-binary @- -k https://public.dydra.com/james/foaf/sparql <<EOF

xxx EOF

HTTP Status: 400 (Bad Request): While processing query #<QUERY-ERROR-TASK [c1745596-548e-11ea-91ed-2c4d5446686d/NIL, SELECT@INITIALIZE, james/foaf@HEAD] {1026172613}>, an error was signaled: task 'c1745596-548e-11ea-91ed-2c4d5446686d': repository 'james/foaf': Invalid message received : failed to parse after 'xxx' at offset 0 on line 1. xxx

curl: (18) transfer closed with outstanding read data remaining `

knoan commented 4 years ago

Delving into the code, it seems that rdf4j is actually trying to read the error message, only to have org.apache.http.impl.io.ChunkedInputStream.getChunkSize() thrown off by the premature end of input.

// org.eclipse.rdf4j.http.client.SPARQLProtocolSession.getErrorInfo(SPARQLProtocolSession.java:1054)

protected ErrorInfo getErrorInfo(HttpResponse response) throws RepositoryException {
    try {
        ErrorInfo errInfo = ErrorInfo.parse(EntityUtils.toString(response.getEntity()));
        logger.warn("Server reports problem: {}", errInfo.getErrorMessage());
        return errInfo;
    } catch ( IOException e) {
        logger.warn("Unable to retrieve error info from server");
        throw new RepositoryException("Unable to retrieve error info from server", e);
    }
}

FWIW, https://public.dydra.com/james/foaf/sparql?query=x appears to cause trouble also to Chrome…

Screenshot 2020-02-21 at 15 30 19

Screenshot 2020-02-21 at 15 30 29

dydra commented 4 years ago

under which circumstance it should report that the content is incomplete, but should still report the content.

On Fri, Feb 21, 2020, 15:32 AB notifications@github.com wrote:

Delving into the code, it seems that rdf4j is actually trying to read the error message, only to have org.apache.http.impl.io.ChunkedInputStream.getChunkSize() thrown off by the premature end of input.

// org.eclipse.rdf4j.http.client.SPARQLProtocolSession.getErrorInfo(SPARQLProtocolSession.java:1054)

protected ErrorInfo getErrorInfo(HttpResponse response) throws RepositoryException {

try {

  ErrorInfo errInfo = ErrorInfo.parse(EntityUtils.toString(response.getEntity()));

  logger.warn("Server reports problem: {}", errInfo.getErrorMessage());

  return errInfo;

} catch ( IOException e) {

  logger.warn("Unable to retrieve error info from server");

  throw new RepositoryException("Unable to retrieve error info from server", e);

}

}

FWIW, https://public.dydra.com/james/foaf/sparql?query=x appears to cause truble also to Chrome…

[image: Screenshot 2020-02-21 at 15 30 19] https://user-images.githubusercontent.com/6105462/75042693-1ec5fd00-54bf-11ea-97b0-c25a0047e2a0.png

[image: Screenshot 2020-02-21 at 15 30 29] https://user-images.githubusercontent.com/6105462/75042706-24bbde00-54bf-11ea-8944-65c9de798863.png

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/dydra/support/issues/59?email_source=notifications&email_token=AAEEX2D2337QFQJXO6TJZSLRD7QZHA5CNFSM4KY6Q5VKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEMS4NZY#issuecomment-589678311, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEEX2E7B2UORGKVKVZA5ODRD7QZHANCNFSM4KY6Q5VA .

lisp commented 4 years ago

note that, the server endeavours to delay the headers until has a degree of confidence as to the disposition and, in this case, does respond with a complete header set, which even in the absence of a complete body, the client should have some means to retrieve:

~ jamesanderson$ curl -v -H "Content-Type: application/sparql-query" -H "Accept: application/sparql-results+json" -X POST --data-binary @- -k https://public.dydra.com/james/foaf/sparql <<EOF
> xxx
> EOF
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 94.130.163.224:443...
* TCP_NODELAY set
* Connected to public.dydra.com (94.130.163.224) port 443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: //anaconda3/ssl/cacert.pem
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.dydra.com
*  start date: Jul  4 00:00:00 2018 GMT
*  expire date: Jul 12 23:59:59 2020 GMT
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
> POST /james/foaf/sparql HTTP/1.1
> Host: public.dydra.com
> User-Agent: curl/7.65.3
> Content-Type: application/sparql-query
> Accept: application/sparql-results+json
> Content-Length: 4
> 
* upload completely sent off: 4 out of 4 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
< Server: nginx/1.10.3 (Ubuntu)
< Date: Fri, 21 Feb 2020 15:20:21 GMT
< Content-Type: text/plain; charset=ISO-8859-1
< Transfer-Encoding: chunked
< Connection: keep-alive
< Strict-Transport-Security: max-age=31536000
< 

HTTP Status: 400 (Bad Request): While processing query #<QUERY-ERROR-TASK [acb30c54-54bd-11ea-91ed-2c4d5446686d/NIL, SELECT@INITIALIZE, james/foaf@HEAD] {101C4D81E3}>, an error was signaled: task 'acb30c54-54bd-11ea-91ed-2c4d5446686d': repository 'james/foaf': Invalid message received :
failed to parse after 'xxx' at offset 0 on line 1.
xxx

* transfer closed with outstanding read data remaining
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, close notify (256):
curl: (18) transfer closed with outstanding read data remaining
(base) berlintoo:~ jamesanderson$