librespot-org / librespot-java

The most up-to-date open source Spotify client

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Hitting uncaught com.google.gson.stream.MalformedJsonException when trying to connect.

breadsander opened this issue · comments

I'm trying to get librespot-java up and running on a fresh Raspberry Pi 4B. I'm using librespot-player-1.6.3.jar with the default config.

When running I am able to discover the Spotify Connect device from Spotify, but hitting a malformed JSON exception

2023-10-04 23:37:05,273 ERROR Log4JUncaughtExceptionHandler:31 - [zeroconf-client-241783884]
com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 10 path $
        at com.google.gson.JsonParser.parseReader(JsonParser.java:76) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.core.ApResolver.request(ApResolver.java:88) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.core.ApResolver.fillPool(ApResolver.java:56) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.core.ApResolver.<init>(ApResolver.java:52) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.core.Session.<init>(Session.java:136) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.core.Session.<init>(Session.java:77) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.core.Session$Builder.create(Session.java:1055) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.ZeroconfServer.handleAddUser(ZeroconfServer.java:367) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.ZeroconfServer.access$200(ZeroconfServer.java:56) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.ZeroconfServer$HttpRunner.handleRequest(ZeroconfServer.java:499) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.ZeroconfServer$HttpRunner.handle(ZeroconfServer.java:574) ~[librespot-player-1.6.3.jar:1.6.3]
        at xyz.gianlu.librespot.ZeroconfServer$HttpRunner.lambda$run$1(ZeroconfServer.java:482) ~[librespot-player-1.6.3.jar:1.6.3]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[?:?]
        at java.lang.Thread.run(Thread.java:829) [?:?]
Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 10 path $
        at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1659) ~[librespot-player-1.6.3.jar:1.6.3]
        at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1465) ~[librespot-player-1.6.3.jar:1.6.3]
        at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:551) ~[librespot-player-1.6.3.jar:1.6.3]
        at com.google.gson.stream.JsonReader.peek(JsonReader.java:433) ~[librespot-player-1.6.3.jar:1.6.3]
        at com.google.gson.JsonParser.parseReader(JsonParser.java:71) ~[librespot-player-1.6.3.jar:1.6.3]
        ... 14 more

This occurs regardless of the device I'm using to connect.

I toyed around with the source a little bit and changed the ApResolver.request() code:

    private void request(@NotNull String... types) throws IOException {
        if (types.length == 0) throw new IllegalArgumentException();

        StringBuilder url = new StringBuilder(BASE_URL + "?");
        for (int i = 0; i < types.length; i++) {
            if (i != 0) url.append("&");
            url.append("type=").append(types[i]);
        }

        Request request = new Request.Builder()
                .url(url.toString())
                .build();
        try (Response response = client.newCall(request).execute()) {
            ResponseBody body = response.body();
            if (body == null) throw new IOException("No body");
            LOGGER.info("Body\n" + body.string());
            JsonReader reader = new JsonReader(body.charStream());
            reader.setLenient(true);
            JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();

Where I am now printing the body of the response. Turns out what I'm getting back in response is the following:

2023-10-05 11:32:07,877 INFO  ZeroconfServer:345 - Accepted new user from BreadPod. {deviceId: 60977a5b889569647cdf05c7083de2a18054e102}
2023-10-05 11:32:08,023 DEBUG TimeProvider:90 - Loaded time offset from NTP: 2ms
2023-10-05 11:32:08,738 INFO  ApResolver:89 - Body
Invalid IP address provided

So rather than any Json whatsoever I'm just getting "Invalid IP address provided" as a response. I'm unsure what IP is being used here. Hmm.

Alright, so I'm almost 100% sure this is a result of my pihole blocking the Spotify API URL http://apresolve.spotify.com/?type=accesspoint&type=dealer&type=spclient.

When accessing this URL from within my network I am getting "Invalid IP address provided", however when out of my network (such as 5g on my phone) I get back the right JSON.

Going to see if I can unblock this and see.

Well, I'm not sure what's happening. For some reason my network will not allow http:// and instead will only allow https:// for this apresolve URL. When I use http:// I get a response body of "Invalid IP address provided".

I am able to access plenty of http (not https) sites normally on my network, so it's not like port 80 or some other security measure is in place. And in fact, if I remove DNS entirely and use: http://34.98.74.57/?type=accesspoint&type=dealer&type=spclient I still receive this Invalid IP body. So, it's not DNS.

However, over my phone off network (5g) I'm able to get to the unsecured page.

Will keep digging. That said, when I changed the BASE_URL within ApResolver.java to use https rather than http then librespot-java is working fine. So good news is I'm unblocked, but bad news is I still don't know why http would not work.

Marking this CLOSED.

Turns out the issue with http/https was a webproxy setting on my network's router from long ago. This altered the HTTP header just slightly to cause Spotify to reject the request. Everything works out of the box now. Thanks!