wtekiela / opensub4j

Java library for communicating with opensubtitles.org XML-RPC API
Other
47 stars 19 forks source link

Error while login when gzip compressing is set #17

Closed vprcic closed 4 years ago

vprcic commented 4 years ago

Using the opensub4j v0.2.3 from mvnrepository gets me this error when trying to login:

Exception in thread "Thread-0" java.lang.IllegalArgumentException: Can not set com.github.wtekiela.opensub4j.response.ResponseStatus field com.github.wtekiela.opensub4j.response.Response.status to java.lang.String
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.base/java.lang.reflect.Field.set(Field.java:780)
    at com.github.wtekiela.opensub4j.impl.ResponseParser.set(ResponseParser.java:147)
    at com.github.wtekiela.opensub4j.impl.ResponseParser.executeFieldBinding(ResponseParser.java:83)
    at com.github.wtekiela.opensub4j.impl.ResponseParser.bindField(ResponseParser.java:66)
    at com.github.wtekiela.opensub4j.impl.ResponseParser.bind(ResponseParser.java:45)
    at com.github.wtekiela.opensub4j.impl.AbstractOperation.execute(AbstractOperation.java:25)
    at com.github.wtekiela.opensub4j.impl.OpenSubtitlesClientImpl.login(OpenSubtitlesClientImpl.java:109)

This is my code:

URL serverUrl = new URL("https", "api.opensubtitles.org", 443, "/xml-rpc");

XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(serverUrl);
config.setConnectionTimeout(100);
config.setReplyTimeout(100);
config.setGzipCompressing(true);

osClient = new OpenSubtitlesClientImpl(config);

Response response = osClient.login(Program.USERNAME, Program.PASSWORD, "en", "TemporaryUserAgent");
wtekiela commented 4 years ago

Hi @vprcic thanks for raising this issue.

There is a bit of a strange behaviour in Apache XmlRpcClient that I think might be a bug.

When you set

config.setGzipCompressing(true);

it will properly send the Content-Encoding: gzip header in the HTTP request, however, it will not use proper writer when sending the actual request body - it will be sent uncompressed.

The logic for choosing the writer is in XmlRpcStreamTransport:

    protected boolean isCompressingRequest(XmlRpcStreamRequestConfig pConfig) {
        return pConfig.isEnabledForExtensions()
            && pConfig.isGzipCompressing();
    }

So, in order for gzip compressing to work, you need to have extensions enabled in your config:

config.setGzipCompressing(true);
config.setEnabledForExtensions(true);

After enabling extensions in your config, your code works fine.

P.S. Make sure to also enable gzip requesting (config.setGzipRequesting(true)) that will set the Accept-Encoding: gzip header, which is important if you want to have your responses also gzipped.

P.P.S. You can troubleshoot your code more easily, if you enable debug level logging in sfl4j (see simplelogger.properties in integTest) - in this case you will get detailed logs of the response, e.g. for the problem with gzip compressing, you'd get:

[DEBUG] RetryableXmlRpcClient - Calling method: ServerInfo, with params: []
[DEBUG] RetryableXmlRpcClient - Response: {seconds=0.002, status=parse error. not well formed}