Skip to content

Commit fda8229

Browse files
authored
Upgrade okhttp to 5.1.0 (#74)
* Upgrade okhttp to 5.1.0 Signed-off-by: Arnau Mora <[email protected]> * Using new mock web server functions Signed-off-by: Arnau Mora <[email protected]> * Removed print Signed-off-by: Arnau Mora <[email protected]> * Refactor Signed-off-by: Arnau Mora <[email protected]> * Refine check Signed-off-by: Arnau Mora <[email protected]> * Extract empty body check to individual function Signed-off-by: Arnau Mora <[email protected]> * Handle NPE Signed-off-by: Arnau Mora <[email protected]> * Fix check typo Signed-off-by: Arnau Mora <[email protected]> * Remove `isEmptyResponseBody` Signed-off-by: Arnau Mora <[email protected]> * Empty body doesn't throw any exception Signed-off-by: Arnau Mora <[email protected]> * Use `peekBody` Signed-off-by: Arnau Mora <[email protected]> --------- Signed-off-by: Arnau Mora <[email protected]>
1 parent b9445fb commit fda8229

File tree

6 files changed

+592
-470
lines changed

6 files changed

+592
-470
lines changed

gradle/libs.versions.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
dokka = "2.0.0"
33
junit4 = "4.13.2"
44
kotlin = "2.2.0"
5-
okhttpVersion = "4.12.0"
5+
okhttpVersion = "5.1.0"
66
xpp3Version = "1.1.6"
77

88
[libraries]
99
junit4 = { module = "junit:junit", version.ref = "junit4" }
1010
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttpVersion" }
11-
okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okhttpVersion" }
11+
okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver3", version.ref = "okhttpVersion" }
1212
xpp3 = { module = "org.ogce:xpp3", version.ref = "xpp3Version" }
1313

1414
[plugins]

src/main/kotlin/at/bitfire/dav4jvm/DavResource.kt

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -733,30 +733,29 @@ open class DavResource @JvmOverloads constructor(
733733
if (response.code != HTTP_MULTISTATUS)
734734
throw DavException("Expected 207 Multi-Status, got ${response.code} ${response.message}", httpResponse = response)
735735

736-
val body = response.body ?:
737-
throw DavException("Received 207 Multi-Status without body", httpResponse = response)
738-
739-
body.contentType()?.let { mimeType ->
740-
if (((mimeType.type != "application" && mimeType.type != "text")) || mimeType.subtype != "xml") {
741-
/* Content-Type is not application/xml or text/xml although that is expected here.
742-
Some broken servers return an XML response with some other MIME type. So we try to see
743-
whether the response is maybe XML although the Content-Type is something else. */
744-
try {
745-
val firstBytes = ByteArray(XML_SIGNATURE.size)
746-
body.source().peek().readFully(firstBytes)
747-
if (XML_SIGNATURE.contentEquals(firstBytes)) {
748-
logger.warning("Received 207 Multi-Status that seems to be XML but has MIME type $mimeType")
749-
750-
// response is OK, return and do not throw Exception below
751-
return
736+
response.peekBody(XML_SIGNATURE.size.toLong()).use { body ->
737+
body.contentType()?.let { mimeType ->
738+
if (((mimeType.type != "application" && mimeType.type != "text")) || mimeType.subtype != "xml") {
739+
/* Content-Type is not application/xml or text/xml although that is expected here.
740+
Some broken servers return an XML response with some other MIME type. So we try to see
741+
whether the response is maybe XML although the Content-Type is something else. */
742+
try {
743+
response.peekBody(XML_SIGNATURE.size.toLong()).use { body ->
744+
if (XML_SIGNATURE.contentEquals(body.bytes())) {
745+
logger.warning("Received 207 Multi-Status that seems to be XML but has MIME type $mimeType")
746+
747+
// response is OK, return and do not throw Exception below
748+
return
749+
}
750+
}
751+
} catch (e: Exception) {
752+
logger.log(Level.WARNING, "Couldn't scan for XML signature", e)
752753
}
753-
} catch (e: Exception) {
754-
logger.log(Level.WARNING, "Couldn't scan for XML signature", e)
755-
}
756754

757-
throw DavException("Received non-XML 207 Multi-Status", httpResponse = response)
758-
}
759-
} ?: logger.warning("Received 207 Multi-Status without Content-Type, assuming XML")
755+
throw DavException("Received non-XML 207 Multi-Status", httpResponse = response)
756+
}
757+
} ?: logger.warning("Received 207 Multi-Status without Content-Type, assuming XML")
758+
}
760759
}
761760

762761

@@ -778,8 +777,8 @@ open class DavResource @JvmOverloads constructor(
778777
protected fun processMultiStatus(response: Response, callback: MultiResponseCallback): List<Property> {
779778
checkStatus(response)
780779
assertMultiStatus(response)
781-
response.body!!.use {
782-
return processMultiStatus(it.charStream(), callback)
780+
return response.body.use {
781+
processMultiStatus(it.charStream(), callback)
783782
}
784783
}
785784

src/test/kotlin/at/bitfire/dav4jvm/DavCalendarTest.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111
package at.bitfire.dav4jvm
1212

13+
import mockwebserver3.MockResponse
14+
import mockwebserver3.MockWebServer
1315
import okhttp3.OkHttpClient
14-
import okhttp3.mockwebserver.MockResponse
15-
import okhttp3.mockwebserver.MockWebServer
1616
import org.junit.After
1717
import org.junit.Assert.assertEquals
1818
import org.junit.Before
@@ -33,14 +33,14 @@ class DavCalendarTest {
3333

3434
@After
3535
fun stopServer() {
36-
mockServer.shutdown()
36+
mockServer.close()
3737
}
3838

3939

4040
@Test
4141
fun calendarQuery_formatStartEnd() {
4242
val cal = DavCalendar(httpClient, mockServer.url("/"))
43-
mockServer.enqueue(MockResponse().setResponseCode(207).setBody("<multistatus xmlns=\"DAV:\"/>"))
43+
mockServer.enqueue(MockResponse.Builder().code(207).body("<multistatus xmlns=\"DAV:\"/>").build())
4444
cal.calendarQuery("VEVENT",
4545
start = Instant.ofEpochSecond(784111777),
4646
end = Instant.ofEpochSecond(1689324577)) { _, _ -> }
@@ -57,7 +57,7 @@ class DavCalendarTest {
5757
"</CAL:comp-filter>" +
5858
"</CAL:comp-filter>" +
5959
"</CAL:filter>" +
60-
"</CAL:calendar-query>", rq.body.readUtf8())
60+
"</CAL:calendar-query>", rq.body?.utf8())
6161
}
6262

6363
}

src/test/kotlin/at/bitfire/dav4jvm/DavCollectionTest.kt

Lines changed: 107 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,13 @@ import at.bitfire.dav4jvm.exception.HttpException
1414
import at.bitfire.dav4jvm.property.webdav.GetETag
1515
import at.bitfire.dav4jvm.property.webdav.NS_WEBDAV
1616
import at.bitfire.dav4jvm.property.webdav.SyncToken
17+
import mockwebserver3.MockResponse
18+
import mockwebserver3.MockWebServer
1719
import okhttp3.MediaType.Companion.toMediaType
1820
import okhttp3.OkHttpClient
1921
import okhttp3.RequestBody.Companion.toRequestBody
20-
import okhttp3.mockwebserver.MockResponse
21-
import okhttp3.mockwebserver.MockWebServer
2222
import org.junit.After
23-
import org.junit.Assert.assertEquals
24-
import org.junit.Assert.assertFalse
25-
import org.junit.Assert.assertTrue
26-
import org.junit.Assert.fail
23+
import org.junit.Assert.*
2724
import org.junit.Before
2825
import org.junit.Test
2926
import java.net.HttpURLConnection
@@ -42,7 +39,7 @@ class DavCollectionTest {
4239
fun startServer() = mockServer.start()
4340

4441
@After
45-
fun stopServer() = mockServer.shutdown()
42+
fun stopServer() = mockServer.close()
4643

4744

4845
/**
@@ -53,58 +50,62 @@ class DavCollectionTest {
5350
val url = sampleUrl()
5451
val collection = DavCollection(httpClient, url)
5552

56-
mockServer.enqueue(MockResponse()
57-
.setResponseCode(207)
53+
mockServer.enqueue(
54+
MockResponse.Builder()
55+
.code(207)
5856
.setHeader("Content-Type", "text/xml; charset=\"utf-8\"")
59-
.setBody("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
60-
" <D:multistatus xmlns:D=\"DAV:\">\n" +
61-
" <D:response>\n" +
62-
" <D:href\n" +
63-
" >${sampleUrl()}test.doc</D:href>\n" +
64-
" <D:propstat>\n" +
65-
" <D:prop>\n" +
66-
" <D:getetag>\"00001-abcd1\"</D:getetag>\n" +
67-
" <R:bigbox xmlns:R=\"urn:ns.example.com:boxschema\">\n" +
68-
" <R:BoxType>Box type A</R:BoxType>\n" +
69-
" </R:bigbox>\n" +
70-
" </D:prop>\n" +
71-
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
72-
" </D:propstat>\n" +
73-
" </D:response>\n" +
74-
" <D:response>\n" +
75-
" <D:href\n" +
76-
" >${sampleUrl()}vcard.vcf</D:href>\n" +
77-
" <D:propstat>\n" +
78-
" <D:prop>\n" +
79-
" <D:getetag>\"00002-abcd1\"</D:getetag>\n" +
80-
" </D:prop>\n" +
81-
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
82-
" </D:propstat>\n" +
83-
" <D:propstat>\n" +
84-
" <D:prop>\n" +
85-
" <R:bigbox xmlns:R=\"urn:ns.example.com:boxschema\"/>\n" +
86-
" </D:prop>\n" +
87-
" <D:status>HTTP/1.1 404 Not Found</D:status>\n" +
88-
" </D:propstat>\n" +
89-
" </D:response>\n" +
90-
" <D:response>\n" +
91-
" <D:href\n" +
92-
" >${sampleUrl()}calendar.ics</D:href>\n" +
93-
" <D:propstat>\n" +
94-
" <D:prop>\n" +
95-
" <D:getetag>\"00003-abcd1\"</D:getetag>\n" +
96-
" </D:prop>\n" +
97-
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
98-
" </D:propstat>\n" +
99-
" <D:propstat>\n" +
100-
" <D:prop>\n" +
101-
" <R:bigbox xmlns:R=\"urn:ns.example.com:boxschema\"/>\n" +
102-
" </D:prop>\n" +
103-
" <D:status>HTTP/1.1 404 Not Found</D:status>\n" +
104-
" </D:propstat>\n" +
105-
" </D:response>\n" +
106-
" <D:sync-token>http://example.com/ns/sync/1234</D:sync-token>\n" +
107-
" </D:multistatus>")
57+
.body(
58+
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
59+
" <D:multistatus xmlns:D=\"DAV:\">\n" +
60+
" <D:response>\n" +
61+
" <D:href\n" +
62+
" >${sampleUrl()}test.doc</D:href>\n" +
63+
" <D:propstat>\n" +
64+
" <D:prop>\n" +
65+
" <D:getetag>\"00001-abcd1\"</D:getetag>\n" +
66+
" <R:bigbox xmlns:R=\"urn:ns.example.com:boxschema\">\n" +
67+
" <R:BoxType>Box type A</R:BoxType>\n" +
68+
" </R:bigbox>\n" +
69+
" </D:prop>\n" +
70+
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
71+
" </D:propstat>\n" +
72+
" </D:response>\n" +
73+
" <D:response>\n" +
74+
" <D:href\n" +
75+
" >${sampleUrl()}vcard.vcf</D:href>\n" +
76+
" <D:propstat>\n" +
77+
" <D:prop>\n" +
78+
" <D:getetag>\"00002-abcd1\"</D:getetag>\n" +
79+
" </D:prop>\n" +
80+
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
81+
" </D:propstat>\n" +
82+
" <D:propstat>\n" +
83+
" <D:prop>\n" +
84+
" <R:bigbox xmlns:R=\"urn:ns.example.com:boxschema\"/>\n" +
85+
" </D:prop>\n" +
86+
" <D:status>HTTP/1.1 404 Not Found</D:status>\n" +
87+
" </D:propstat>\n" +
88+
" </D:response>\n" +
89+
" <D:response>\n" +
90+
" <D:href\n" +
91+
" >${sampleUrl()}calendar.ics</D:href>\n" +
92+
" <D:propstat>\n" +
93+
" <D:prop>\n" +
94+
" <D:getetag>\"00003-abcd1\"</D:getetag>\n" +
95+
" </D:prop>\n" +
96+
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
97+
" </D:propstat>\n" +
98+
" <D:propstat>\n" +
99+
" <D:prop>\n" +
100+
" <R:bigbox xmlns:R=\"urn:ns.example.com:boxschema\"/>\n" +
101+
" </D:prop>\n" +
102+
" <D:status>HTTP/1.1 404 Not Found</D:status>\n" +
103+
" </D:propstat>\n" +
104+
" </D:response>\n" +
105+
" <D:sync-token>http://example.com/ns/sync/1234</D:sync-token>\n" +
106+
" </D:multistatus>"
107+
)
108+
.build()
108109
)
109110
var nrCalled = 0
110111
val result = collection.reportChanges(null, false, null, GetETag.NAME) { response, relation ->
@@ -147,40 +148,44 @@ class DavCollectionTest {
147148
val url = sampleUrl()
148149
val collection = DavCollection(httpClient, url)
149150

150-
mockServer.enqueue(MockResponse()
151-
.setResponseCode(207)
151+
mockServer.enqueue(
152+
MockResponse.Builder()
153+
.code(207)
152154
.setHeader("Content-Type", "text/xml; charset=\"utf-8\"")
153-
.setBody("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
154-
" <D:multistatus xmlns:D=\"DAV:\">\n" +
155-
" <D:response>\n" +
156-
" <D:href>${sampleUrl()}test.doc</D:href>\n" +
157-
" <D:propstat>\n" +
158-
" <D:prop>\n" +
159-
" <D:getetag>\"00001-abcd1\"</D:getetag>\n" +
160-
" </D:prop>\n" +
161-
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
162-
" </D:propstat>\n" +
163-
" </D:response>\n" +
164-
" <D:response>\n" +
165-
" <D:href>${sampleUrl()}vcard.vcf</D:href>\n" +
166-
" <D:propstat>\n" +
167-
" <D:prop>\n" +
168-
" <D:getetag>\"00002-abcd1\"</D:getetag>\n" +
169-
" </D:prop>\n" +
170-
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
171-
" </D:propstat>\n" +
172-
" </D:response>\n" +
173-
" <D:response>\n" +
174-
" <D:href>${sampleUrl()}removed.txt</D:href>\n" +
175-
" <D:status>HTTP/1.1 404 Not Found</D:status>\n" +
176-
" </D:response>" +
177-
" <D:response>\n" +
178-
" <D:href>${sampleUrl()}</D:href>\n" +
179-
" <D:status>HTTP/1.1 507 Insufficient Storage</D:status>\n" +
180-
" <D:error><D:number-of-matches-within-limits/></D:error>\n" +
181-
" </D:response>" +
182-
" <D:sync-token>http://example.com/ns/sync/1233</D:sync-token>\n" +
183-
" </D:multistatus>")
155+
.body(
156+
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
157+
" <D:multistatus xmlns:D=\"DAV:\">\n" +
158+
" <D:response>\n" +
159+
" <D:href>${sampleUrl()}test.doc</D:href>\n" +
160+
" <D:propstat>\n" +
161+
" <D:prop>\n" +
162+
" <D:getetag>\"00001-abcd1\"</D:getetag>\n" +
163+
" </D:prop>\n" +
164+
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
165+
" </D:propstat>\n" +
166+
" </D:response>\n" +
167+
" <D:response>\n" +
168+
" <D:href>${sampleUrl()}vcard.vcf</D:href>\n" +
169+
" <D:propstat>\n" +
170+
" <D:prop>\n" +
171+
" <D:getetag>\"00002-abcd1\"</D:getetag>\n" +
172+
" </D:prop>\n" +
173+
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
174+
" </D:propstat>\n" +
175+
" </D:response>\n" +
176+
" <D:response>\n" +
177+
" <D:href>${sampleUrl()}removed.txt</D:href>\n" +
178+
" <D:status>HTTP/1.1 404 Not Found</D:status>\n" +
179+
" </D:response>" +
180+
" <D:response>\n" +
181+
" <D:href>${sampleUrl()}</D:href>\n" +
182+
" <D:status>HTTP/1.1 507 Insufficient Storage</D:status>\n" +
183+
" <D:error><D:number-of-matches-within-limits/></D:error>\n" +
184+
" </D:response>" +
185+
" <D:sync-token>http://example.com/ns/sync/1233</D:sync-token>\n" +
186+
" </D:multistatus>"
187+
)
188+
.build()
184189
)
185190
var nrCalled = 0
186191
val result = collection.reportChanges(null, false, null, GetETag.NAME) { response, relation ->
@@ -227,13 +232,17 @@ class DavCollectionTest {
227232
val url = sampleUrl()
228233
val collection = DavCollection(httpClient, url)
229234

230-
mockServer.enqueue(MockResponse()
231-
.setResponseCode(507)
235+
mockServer.enqueue(
236+
MockResponse.Builder()
237+
.code(507)
232238
.setHeader("Content-Type", "text/xml; charset=\"utf-8\"")
233-
.setBody("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
234-
" <D:error xmlns:D=\"DAV:\">\n" +
235-
" <D:number-of-matches-within-limits/>\n" +
236-
" </D:error>")
239+
.body(
240+
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
241+
" <D:error xmlns:D=\"DAV:\">\n" +
242+
" <D:number-of-matches-within-limits/>\n" +
243+
" </D:error>"
244+
)
245+
.build()
237246
)
238247

239248
try {
@@ -252,7 +261,7 @@ class DavCollectionTest {
252261
val dav = DavCollection(httpClient, url)
253262

254263
// 201 Created
255-
mockServer.enqueue(MockResponse().setResponseCode(HttpURLConnection.HTTP_CREATED))
264+
mockServer.enqueue(MockResponse.Builder().code(HttpURLConnection.HTTP_CREATED).build())
256265
var called = false
257266
dav.post(sampleText.toRequestBody("text/plain".toMediaType())) { response ->
258267
assertEquals("POST", mockServer.takeRequest().method)

0 commit comments

Comments
 (0)