Skip to content

Move Response extraction logic out of init of DavException #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions src/main/kotlin/at/bitfire/dav4jvm/DavResource.kt
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ open class DavResource @JvmOverloads constructor(
*/
fun assertMultiStatus(response: Response) {
if (response.code != HTTP_MULTISTATUS)
throw DavException("Expected 207 Multi-Status, got ${response.code} ${response.message}", httpResponse = response)
throw DavException("Expected 207 Multi-Status, got ${response.code} ${response.message}").populateHttpResponse(response)

response.peekBody(XML_SIGNATURE.size.toLong()).use { body ->
body.contentType()?.let { mimeType ->
Expand All @@ -760,7 +760,7 @@ open class DavResource @JvmOverloads constructor(
logger.log(Level.WARNING, "Couldn't scan for XML signature", e)
}

throw DavException("Received non-XML 207 Multi-Status", httpResponse = response)
throw DavException("Received non-XML 207 Multi-Status").populateHttpResponse(response)
}
} ?: logger.warning("Received 207 Multi-Status without Content-Type, assuming XML")
}
Expand Down
77 changes: 36 additions & 41 deletions src/main/kotlin/at/bitfire/dav4jvm/exception/DavException.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,25 @@ import java.util.logging.Logger
* received, but also an explicit HTTP error.
*/
open class DavException @JvmOverloads constructor(
message: String,
ex: Throwable? = null,

/**
* An associated HTTP [Response]. Will be closed after evaluation.
*/
httpResponse: Response? = null
): Exception(message, ex), Serializable {
message: String,
ex: Throwable? = null,
) : Exception(message, ex), Serializable {

companion object {

const val MAX_EXCERPT_SIZE = 10*1024 // don't dump more than 20 kB
const val MAX_EXCERPT_SIZE = 10 * 1024 // don't dump more than 20 kB

fun isPlainText(type: MediaType) =
type.type == "text" ||
(type.type == "application" && type.subtype in arrayOf("html", "xml"))
type.type == "text" ||
(type.type == "application" && type.subtype in arrayOf("html", "xml"))

}

private val logger
get() = Logger.getLogger(javaClass.name)

var request: String? = null
private set

/**
* Body excerpt of [request] (up to [MAX_EXCERPT_SIZE] characters). Only available
Expand All @@ -64,7 +60,8 @@ open class DavException @JvmOverloads constructor(
var requestBody: String? = null
private set

val response: String?
var response: String? = null
private set

/**
* Body excerpt of [response] (up to [MAX_EXCERPT_SIZE] characters). Only available
Expand All @@ -80,7 +77,7 @@ open class DavException @JvmOverloads constructor(
private set


init {
fun populateHttpResponse(httpResponse: Response?): DavException {
if (httpResponse != null) {
response = httpResponse.toString()

Expand All @@ -106,35 +103,30 @@ open class DavException @JvmOverloads constructor(
}

try {
// save response body excerpt
if (httpResponse.body?.source() != null) {
// response body has a source

httpResponse.peekBody(MAX_EXCERPT_SIZE.toLong()).let { body ->
body.contentType()?.let { mimeType ->
if (isPlainText(mimeType))
responseBody = body.string()
}
httpResponse.peekBody(MAX_EXCERPT_SIZE.toLong()).let { body ->
body.contentType()?.let { mimeType ->
if (isPlainText(mimeType))
responseBody = body.string()
}
}

httpResponse.body?.use { body ->
body.contentType()?.let {
if (it.type in arrayOf("application", "text") && it.subtype == "xml") {
// look for precondition/postcondition XML elements
try {
val parser = XmlUtils.newPullParser()
parser.setInput(body.charStream())

var eventType = parser.eventType
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG && parser.depth == 1)
if (parser.propertyName() == Error.NAME)
errors = Error.parseError(parser)
eventType = parser.next()
}
} catch (e: XmlPullParserException) {
logger.log(Level.WARNING, "Couldn't parse XML response", e)
httpResponse.body.use { body ->
body.contentType()?.let {
if (it.type in arrayOf("application", "text") && it.subtype == "xml") {
// look for precondition/postcondition XML elements
try {
val parser = XmlUtils.newPullParser()
parser.setInput(body.charStream())

var eventType = parser.eventType
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG && parser.depth == 1)
if (parser.propertyName() == Error.NAME)
errors = Error.parseError(parser)
eventType = parser.next()
}
} catch (e: XmlPullParserException) {
logger.log(Level.WARNING, "Couldn't parse XML response", e)
}
}
}
Expand All @@ -143,10 +135,13 @@ open class DavException @JvmOverloads constructor(
logger.log(Level.WARNING, "Couldn't read HTTP response", e)
responseBody = "Couldn't read HTTP response: ${e.message}"
} finally {
httpResponse.body?.close()
httpResponse.body.close()
}
} else
} else {
response = null
}

return this
}

}
4 changes: 2 additions & 2 deletions src/main/kotlin/at/bitfire/dav4jvm/exception/HttpException.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ open class HttpException: DavException {
var code: Int

constructor(response: Response): super(
"HTTP ${response.code} ${response.message}",
httpResponse = response
"HTTP ${response.code} ${response.message}"
) {
code = response.code
populateHttpResponse(response)
}

constructor(code: Int, message: String?): super("HTTP $code $message") {
Expand Down
21 changes: 12 additions & 9 deletions src/test/kotlin/at/bitfire/dav4jvm/exception/DavExceptionTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,18 @@ class DavExceptionTest {
builder.append(CharArray(DavException.MAX_EXCERPT_SIZE+100) { '*' })
val body = builder.toString()

val e = DavException("Error with large request body", null, Response.Builder()
.request(Request.Builder()
.url("http://example.com")
.post(body.toRequestBody("text/plain".toMediaType()))
.build())
.protocol(Protocol.HTTP_1_1)
.code(204)
.message("No Content")
.build())
val e = DavException("Error with large request body", null)
.populateHttpResponse(
Response.Builder()
.request(Request.Builder()
.url("http://example.com")
.post(body.toRequestBody("text/plain".toMediaType()))
.build())
.protocol(Protocol.HTTP_1_1)
.code(204)
.message("No Content")
.build()
)

assertTrue(e.errors.isEmpty())
assertEquals(
Expand Down
Loading