prismicio-community / java-kit

Community maintained development kit for Prismic and the Java language
https://prismic.io
15 stars 38 forks source link

Prismic 403 error #44

Open ghost opened 7 years ago

ghost commented 7 years ago

Hello.

We're developing an app that runs on Android and on iOS. On iOS we use a "manual" implementation written by our devs, on Android we use the java-kit. And lately we've been getting a 403 error A LOT when making calls to prismic on both versions of the app (140k times on production in the last 90 days, including that day when "Amazon broke the internet" (70k errors on that day)).

Unfortunately, I don't have a solid reproduction scenario other than just "Open the app, make a call to prismic and wait a couple hours". But after a thorough investigation we came up with a solution.

====================== So, the Api object is stored in an instanced class which gets initialized the first time a call to prismic is made. The calls themselves were made like this (I omit boring catches and the pagination here)

final Response response = api.getForm("everything")
                        .ref(api.getMaster())
                        .query(predicates)
                        .page(page)
                        .submit();

We had to tweak things a bit, now when we create the Api object we store the master reference id in a separate field: masterReferenceId = api.getMaster().getRef(); And the calls now look like this

try {
    final Response response = api.getForm("everything")
        .ref(masterReferenceId)
        .query(predicates)
        .page(page)
        .submit();
} catch (Exception exception) {
    //blame io.prismic.core.HttpClient line 70
    //prismic throws a usual RuntimeException and briefly mentions its cause in the message
    //and we have to deal with it to handle the HTTP 403 error
    if (exception.getMessage().contains("403")) {
        log.error("need to update reference id");
        updatePrismicReferenceId(predicates);
        return;
    }
        log.error("Error occurred.", exception);
}

What we do here is we catch the 403 HTTP error and try updating the master reference ID by calling (it's best to present this with curl, it should be shorter) curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET https://hey-article.prismic.io/api We parse the response, find a new master ref and then try retrieving the articles using the new ID. To avoid running into an infinite retry loop we also manage a retry counter.

Voila, the error is gone, articles are retrieved normally.

====================== Here are the questions: 1) Is this solution viable? Or does it goes against the very idea of java-kit on some fundamental level? 2) Can this mechanism be implemented in the java-kit itself? 3) Can you at least provide us with a nicer way to intercept the 403 error (like by expanding Api.Error.Code)? I mean, it hurts me to write exception.getMessage().contains("403")

srenault commented 7 years ago

Hi @AlexeyLitvinov

I just answered to a related issue here: https://github.com/prismicio/java-kit/issues/46

Note: You shouldn't be afraid of calling: Api api = Api.get("https://<your-repo>.prismic.io/api");

By default, the java-kit puts in cache theApi response for 5 seconds.

ghost commented 7 years ago

@srenault hey. Oh, great to know, thanks :)

So it's either create an Api instance for every call or manage the master ref the way we do it?

Can I create a pull request fixing this?

Can you at least provide us with a nicer way to intercept the 403 error (like by expanding Api.Error.Code)? I mean, it hurts me to write exception.getMessage().contains("403")