diff --git a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.kt b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.kt index 0b42137e7..b18c343e0 100644 --- a/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.kt +++ b/app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.kt @@ -43,7 +43,7 @@ class MediaDataExtractor @Inject constructor(private val mediaClient: MediaClien return Single.ambArray( mediaClient.getMediaById(PAGE_ID_PREFIX + media.pageId) .onErrorResumeNext { Single.never() }, - mediaClient.getMedia(media.filename) + mediaClient.getMediaSuppressingErrors(media.filename) .onErrorResumeNext { Single.never() } ) diff --git a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java index 89264f18d..b475b3995 100644 --- a/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java +++ b/app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java @@ -67,6 +67,8 @@ public final class OkHttpConnectionFactory { } public static class UnsuccessfulResponseInterceptor implements Interceptor { + private static final String SUPPRESS_ERROR_LOG = "x-commons-suppress-error-log"; + public static final String SUPPRESS_ERROR_LOG_HEADER = SUPPRESS_ERROR_LOG+": true"; private static final List DO_NOT_INTERCEPT = Collections.singletonList( "api.php?format=json&formatversion=2&errorformat=plaintext&action=upload&ignorewarnings=1"); @@ -75,7 +77,16 @@ public final class OkHttpConnectionFactory { @Override @NonNull public Response intercept(@NonNull final Chain chain) throws IOException { - final Response rsp = chain.proceed(chain.request()); + final Request rq = chain.request(); + + // If the request contains our special "suppress errors" header, make note of it + // but don't pass that on to the server. + final boolean suppressErrors = rq.headers().names().contains(SUPPRESS_ERROR_LOG); + final Request request = rq.newBuilder() + .removeHeader(SUPPRESS_ERROR_LOG) + .build(); + + final Response rsp = chain.proceed(request); // Do not intercept certain requests and let the caller handle the errors if(isExcludedUrl(chain.request())) { @@ -89,7 +100,12 @@ public final class OkHttpConnectionFactory { } } } catch (final IOException e) { - Timber.e(e); + // Log the error as debug (and therefore, "expected") or at error level + if (suppressErrors) { + Timber.d(e, "Suppressed (known / expected) error"); + } else { + Timber.e(e); + } } return rsp; } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt index a34882922..72ec08924 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt @@ -130,6 +130,17 @@ class MediaClient @Inject constructor( .map { it.first() } } + /** + * Fetches Media object from the imageInfo API but suppress (known) errors + * + * @param titles the tiles to be searched for. Can be filename or template name + * @return + */ + fun getMediaSuppressingErrors(titles: String?): Single { + return responseMapper(mediaInterface.getMediaSuppressingErrors(titles)) + .map { it.first() } + } + /** * The method returns the picture of the day * diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java b/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java index 058cb68ae..902a99ffb 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaInterface.java @@ -1,9 +1,12 @@ package fr.free.nrw.commons.media; +import static fr.free.nrw.commons.OkHttpConnectionFactory.UnsuccessfulResponseInterceptor.SUPPRESS_ERROR_LOG_HEADER; + import io.reactivex.Single; import java.util.Map; import fr.free.nrw.commons.wikidata.mwapi.MwQueryResponse; import retrofit2.http.GET; +import retrofit2.http.Headers; import retrofit2.http.Query; import retrofit2.http.QueryMap; @@ -103,6 +106,17 @@ public interface MediaInterface { MEDIA_PARAMS_WITH_CATEGORY_DETAILS) Single getMedia(@Query("titles") String title); + /** + * Fetches Media object from the imageInfo API but suppress (known) errors + * + * @param title the tiles to be searched for. Can be filename or template name + * @return + */ + @GET("w/api.php?action=query&format=json&formatversion=2" + + MEDIA_PARAMS_WITH_CATEGORY_DETAILS) + @Headers(SUPPRESS_ERROR_LOG_HEADER) + Single getMediaSuppressingErrors(@Query("titles") String title); + /** * Fetches Media object from the imageInfo API * @@ -111,6 +125,7 @@ public interface MediaInterface { */ @GET("w/api.php?action=query&format=json&formatversion=2" + MEDIA_PARAMS) + @Headers(SUPPRESS_ERROR_LOG_HEADER) Single getMediaById(@Query("pageids") String pageIds); /** @@ -125,6 +140,7 @@ public interface MediaInterface { Single getMediaWithGenerator(@Query("titles") String title); @GET("w/api.php?format=json&action=parse&prop=text") + @Headers(SUPPRESS_ERROR_LOG_HEADER) Single getPageHtml(@Query("page") String title); /**