Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Complex HTTP Errors #213

Merged
merged 8 commits into from
Jun 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions Corona-Warn-App/config/detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ complexity:
active: true
threshold: 15
ignoreSingleWhenExpression: false
ignoreSimpleWhenEntries: false
ignoreSimpleWhenEntries: true
ignoreNestingFunctions: false
nestingFunctions: [run, let, apply, with, also, use, forEach, isNotNull, ifNull]
LabeledExpression:
Expand Down Expand Up @@ -514,7 +514,15 @@ style:
maxJumpCount: 1
MagicNumber:
active: true
excludes: ['**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt']
excludes: [
'**/test/**',
'**/androidTest/**',
'**/*.Test.kt',
'**/*.Spec.kt',
'**/*.Spek.kt',
'**/CwaWebException.kt',
'**/HttpErrorParser.kt'
]
ignoreNumbers: ['-1', '0', '1', '2']
ignoreHashCodeFunction: true
ignorePropertyDeclaration: false
Expand All @@ -523,7 +531,7 @@ style:
ignoreCompanionObjectPropertyDeclaration: true
ignoreAnnotation: false
ignoreNamedArgument: true
ignoreEnums: false
ignoreEnums: true
ignoreRanges: false
MandatoryBracesIfStatements:
active: false
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package de.rki.coronawarnapp.exception.http

import java.io.IOException

open class CwaWebException(statusCode: Int) : IOException(
"error during web request, http status $statusCode"
)

open class CwaServerError(val statusCode: Int) : CwaWebException(statusCode) {
init {
if (statusCode !in 500..599)
throw IllegalArgumentException("a server error has to have code 5xx")
}
}

open class CwaClientError(val statusCode: Int) : CwaWebException(statusCode) {
init {
if (statusCode !in 400..499)
throw IllegalArgumentException("a client error has to have code 4xx")
}
}

open class CwaSuccessResponseWithCodeMismatchNotSupportedError(val statusCode: Int) : CwaWebException(statusCode)
open class CwaInformationalNotSupportedError(val statusCode: Int) : CwaWebException(statusCode)
open class CwaRedirectNotSupportedError(val statusCode: Int) : CwaWebException(statusCode)

class BadRequestException : CwaClientError(400)
class UnauthorizedException : CwaClientError(401)
class ForbiddenException : CwaClientError(403)
class NotFoundException : CwaClientError(404)
class ConflictException : CwaClientError(409)
class GoneException : CwaClientError(410)
class UnsupportedMediaTypeException : CwaClientError(415)
class TooManyRequestsException : CwaClientError(429)

class InternalServerErrorException : CwaServerError(500)
class NotImplementedException : CwaServerError(501)
class BadGatewayException : CwaServerError(502)
class ServiceUnavailableException : CwaServerError(503)
class GatewayTimeoutException : CwaServerError(504)
class HTTPVersionNotSupported : CwaServerError(505)
class NetworkAuthenticationRequiredException : CwaServerError(511)
class NetworkReadTimeoutException : CwaServerError(598)
class NetworkConnectTimeoutException : CwaServerError(599)
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package de.rki.coronawarnapp.http

import de.rki.coronawarnapp.exception.http.BadGatewayException
import de.rki.coronawarnapp.exception.http.CwaWebException
import de.rki.coronawarnapp.exception.http.BadRequestException
import de.rki.coronawarnapp.exception.http.ConflictException
import de.rki.coronawarnapp.exception.http.CwaClientError
import de.rki.coronawarnapp.exception.http.CwaInformationalNotSupportedError
import de.rki.coronawarnapp.exception.http.CwaRedirectNotSupportedError
import de.rki.coronawarnapp.exception.http.CwaServerError
import de.rki.coronawarnapp.exception.http.CwaSuccessResponseWithCodeMismatchNotSupportedError
import de.rki.coronawarnapp.exception.http.ForbiddenException
import de.rki.coronawarnapp.exception.http.GatewayTimeoutException
import de.rki.coronawarnapp.exception.http.GoneException
import de.rki.coronawarnapp.exception.http.HTTPVersionNotSupported
import de.rki.coronawarnapp.exception.http.InternalServerErrorException
import de.rki.coronawarnapp.exception.http.NetworkAuthenticationRequiredException
import de.rki.coronawarnapp.exception.http.NetworkConnectTimeoutException
import de.rki.coronawarnapp.exception.http.NetworkReadTimeoutException
import de.rki.coronawarnapp.exception.http.NotFoundException
import de.rki.coronawarnapp.exception.http.NotImplementedException
import de.rki.coronawarnapp.exception.http.ServiceUnavailableException
import de.rki.coronawarnapp.exception.http.TooManyRequestsException
import de.rki.coronawarnapp.exception.http.UnauthorizedException
import de.rki.coronawarnapp.exception.http.UnsupportedMediaTypeException
import okhttp3.Interceptor
import okhttp3.Response

class HttpErrorParser : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val response = chain.proceed(chain.request())
return when (val code = response.code) {
200 -> response
201 -> response
202 -> response
204 -> response
400 -> throw BadRequestException()
401 -> throw UnauthorizedException()
403 -> throw ForbiddenException()
404 -> throw NotFoundException()
409 -> throw ConflictException()
410 -> throw GoneException()
415 -> throw UnsupportedMediaTypeException()
429 -> throw TooManyRequestsException()
500 -> throw InternalServerErrorException()
501 -> throw NotImplementedException()
502 -> throw BadGatewayException()
503 -> throw ServiceUnavailableException()
504 -> throw GatewayTimeoutException()
505 -> throw HTTPVersionNotSupported()
511 -> throw NetworkAuthenticationRequiredException()
598 -> throw NetworkReadTimeoutException()
599 -> throw NetworkConnectTimeoutException()
else -> {
if (code in 100..199) throw CwaInformationalNotSupportedError(code)
if (code in 200..299) throw CwaSuccessResponseWithCodeMismatchNotSupportedError(code)
if (code in 300..399) throw CwaRedirectNotSupportedError(code)
if (code in 400..499) throw CwaClientError(code)
if (code in 500..599) throw CwaServerError(code)
throw CwaWebException(code)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class ServiceFactory {
if (BuildConfig.DEBUG) it.setLevel(HttpLoggingInterceptor.Level.BODY)
},
OfflineCacheInterceptor(CoronaWarnApplication.getAppContext()),
RetryInterceptor()
RetryInterceptor(),
HttpErrorParser()
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ import KeyExportFormat
import android.util.Log
import de.rki.coronawarnapp.exception.DiagnosisKeyRetrievalException
import de.rki.coronawarnapp.exception.DiagnosisKeySubmissionException
import de.rki.coronawarnapp.exception.SubmissionTanInvalidException
import de.rki.coronawarnapp.http.WebRequestBuilder
import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants.SERVER_ERROR_CODE_403
import retrofit2.HttpException

/**
* The Diagnosis Key Service is used to interact with the Server to submit and retrieve keys through
Expand All @@ -50,21 +47,11 @@ object DiagnosisKeyService {
* @param keysToReport - KeyList in the Server Format to submit to the Server
*/
suspend fun asyncSubmitKeys(authCode: String, keysToReport: List<KeyExportFormat.TemporaryExposureKey>) {
try {
Log.d(TAG, "Diagnosis Keys will be submitted.")
WebRequestBuilder.asyncSubmitKeysToServer(
authCode,
false,
keysToReport
)
} catch (e: HttpException) {
if (e.code() == SERVER_ERROR_CODE_403) {
throw SubmissionTanInvalidException(
"the test paring to the device is invalid",
e
)
}
throw e
}
Log.d(TAG, "Diagnosis Keys will be submitted.")
WebRequestBuilder.asyncSubmitKeysToServer(
authCode,
false,
keysToReport
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,24 @@ package de.rki.coronawarnapp.service.submission

import de.rki.coronawarnapp.exception.NoGUIDOrTANSetException
import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
import de.rki.coronawarnapp.exception.TestAlreadyPairedException
import de.rki.coronawarnapp.exception.TestPairingInvalidException
import de.rki.coronawarnapp.http.WebRequestBuilder
import de.rki.coronawarnapp.service.submission.SubmissionConstants.QR_CODE_KEY_TYPE
import de.rki.coronawarnapp.service.submission.SubmissionConstants.SERVER_ERROR_CODE_400
import de.rki.coronawarnapp.service.submission.SubmissionConstants.TELE_TAN_KEY_TYPE
import de.rki.coronawarnapp.storage.LocalData
import de.rki.coronawarnapp.transaction.SubmitDiagnosisKeysTransaction
import de.rki.coronawarnapp.util.formatter.TestResult
import retrofit2.HttpException

object SubmissionService {
suspend fun asyncRegisterDevice() {
try {
val testGUID = LocalData.testGUID()
val testTAN = LocalData.teletan()

when {
testGUID != null -> asyncRegisterDeviceViaGUID(testGUID)
testTAN != null -> asyncRegisterDeviceViaTAN(testTAN)
else -> throw NoGUIDOrTANSetException()
}
LocalData.devicePairingSuccessfulTimestamp(System.currentTimeMillis())
} catch (err: HttpException) {
if (err.code() == SERVER_ERROR_CODE_400) {
throw TestAlreadyPairedException(
"the test was already paired to a different device",
err
)
}
throw err
val testGUID = LocalData.testGUID()
val testTAN = LocalData.teletan()

when {
testGUID != null -> asyncRegisterDeviceViaGUID(testGUID)
testTAN != null -> asyncRegisterDeviceViaTAN(testTAN)
else -> throw NoGUIDOrTANSetException()
}
LocalData.devicePairingSuccessfulTimestamp(System.currentTimeMillis())
}

private suspend fun asyncRegisterDeviceViaGUID(guid: String) {
Expand All @@ -59,17 +45,7 @@ object SubmissionService {
}

suspend fun asyncRequestAuthCode(registrationToken: String): String {
try {
return WebRequestBuilder.asyncGetTan(registrationToken)
} catch (err: HttpException) {
if (err.code() == SERVER_ERROR_CODE_400) {
throw TestPairingInvalidException(
"the test paring to the device is invalid",
err
)
}
throw err
}
return WebRequestBuilder.asyncGetTan(registrationToken)
}

suspend fun asyncSubmitExposureKeys() {
Expand Down
Loading