Skip to content

Commit fa173ab

Browse files
authored
Added post method to DavResource (#47)
Signed-off-by: Arnau Mora <[email protected]>
1 parent ffdfc56 commit fa173ab

File tree

3 files changed

+115
-33
lines changed

3 files changed

+115
-33
lines changed

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

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ import at.bitfire.dav4jvm.exception.DavException
1111
import at.bitfire.dav4jvm.exception.HttpException
1212
import at.bitfire.dav4jvm.property.webdav.NS_WEBDAV
1313
import at.bitfire.dav4jvm.property.webdav.SyncToken
14+
import java.io.StringWriter
15+
import java.util.logging.Logger
1416
import okhttp3.HttpUrl
1517
import okhttp3.OkHttpClient
1618
import okhttp3.Request
17-
import okhttp3.RequestBody
1819
import okhttp3.RequestBody.Companion.toRequestBody
19-
import java.io.IOException
20-
import java.io.StringWriter
21-
import java.util.logging.Logger
2220

2321
/**
2422
* Represents a WebDAV collection.
@@ -36,27 +34,6 @@ open class DavCollection @JvmOverloads constructor(
3634
val NRESULTS = Property.Name(NS_WEBDAV, "nresults")
3735
}
3836

39-
/**
40-
* Sends a POST request. Primarily intended to be used with an Add-Member URL (RFC 5995).
41-
*/
42-
@Throws(IOException::class, HttpException::class)
43-
fun post(body: RequestBody, ifNoneMatch: Boolean = false, callback: ResponseCallback) {
44-
followRedirects {
45-
val builder = Request.Builder()
46-
.post(body)
47-
.url(location)
48-
49-
if (ifNoneMatch)
50-
// don't overwrite anything existing
51-
builder.header("If-None-Match", "*")
52-
53-
httpClient.newCall(builder.build()).execute()
54-
}.use { response ->
55-
checkStatus(response)
56-
callback.onResponse(response)
57-
}
58-
}
59-
6037
/**
6138
* Sends a REPORT sync-collection request.
6239
*

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

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ import at.bitfire.dav4jvm.property.caldav.NS_CALDAV
2020
import at.bitfire.dav4jvm.property.carddav.NS_CARDDAV
2121
import at.bitfire.dav4jvm.property.webdav.NS_WEBDAV
2222
import at.bitfire.dav4jvm.property.webdav.SyncToken
23+
import java.io.EOFException
24+
import java.io.IOException
25+
import java.io.Reader
26+
import java.io.StringWriter
27+
import java.net.HttpURLConnection
28+
import java.util.logging.Level
29+
import java.util.logging.Logger
2330
import okhttp3.Headers
2431
import okhttp3.HttpUrl
2532
import okhttp3.MediaType.Companion.toMediaType
@@ -30,13 +37,6 @@ import okhttp3.RequestBody.Companion.toRequestBody
3037
import okhttp3.Response
3138
import org.xmlpull.v1.XmlPullParser
3239
import org.xmlpull.v1.XmlPullParserException
33-
import java.io.EOFException
34-
import java.io.IOException
35-
import java.io.Reader
36-
import java.io.StringWriter
37-
import java.net.HttpURLConnection
38-
import java.util.logging.Level
39-
import java.util.logging.Logger
4040
import at.bitfire.dav4jvm.Response as DavResponse
4141

4242
/**
@@ -417,6 +417,30 @@ open class DavResource @JvmOverloads constructor(
417417
}
418418
}
419419

420+
/**
421+
* Sends a GET request to the resource. Follows up to [MAX_REDIRECTS] redirects.
422+
*/
423+
@Throws(IOException::class, HttpException::class)
424+
fun post(body: RequestBody, ifNoneMatch: Boolean = false, headers: Headers? = null, callback: ResponseCallback) {
425+
followRedirects {
426+
val builder = Request.Builder()
427+
.post(body)
428+
.url(location)
429+
430+
if (ifNoneMatch)
431+
// don't overwrite anything existing
432+
builder.header("If-None-Match", "*")
433+
434+
if (headers != null)
435+
builder.headers(headers)
436+
437+
httpClient.newCall(builder.build()).execute()
438+
}.use { response ->
439+
checkStatus(response)
440+
callback.onResponse(response)
441+
}
442+
}
443+
420444
/**
421445
* Sends a PUT request to the resource. Follows up to [MAX_REDIRECTS] redirects.
422446
*

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

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import at.bitfire.dav4jvm.property.webdav.DisplayName
1313
import at.bitfire.dav4jvm.property.webdav.GetContentType
1414
import at.bitfire.dav4jvm.property.webdav.GetETag
1515
import at.bitfire.dav4jvm.property.webdav.ResourceType
16+
import java.net.HttpURLConnection
1617
import okhttp3.HttpUrl.Companion.toHttpUrl
1718
import okhttp3.MediaType.Companion.toMediaType
1819
import okhttp3.OkHttpClient
@@ -30,7 +31,6 @@ import org.junit.Assert.assertTrue
3031
import org.junit.Assert.fail
3132
import org.junit.Before
3233
import org.junit.Test
33-
import java.net.HttpURLConnection
3434

3535
class DavResourceTest {
3636

@@ -310,6 +310,87 @@ class DavResourceTest {
310310
assertTrue(called)
311311
}
312312

313+
@Test
314+
fun testPost() {
315+
val url = sampleUrl()
316+
val dav = DavResource(httpClient, url)
317+
318+
/* POSITIVE TEST CASES */
319+
320+
// 200 OK
321+
mockServer.enqueue(
322+
MockResponse()
323+
.setResponseCode(HttpURLConnection.HTTP_OK)
324+
.setHeader("ETag", "W/\"My Weak ETag\"")
325+
.setHeader("Content-Type", "application/x-test-result")
326+
.setBody(sampleText)
327+
)
328+
var called = false
329+
dav.post(
330+
body = "body".toRequestBody("application/x-test-result".toMediaType())
331+
) { response ->
332+
called = true
333+
assertEquals(sampleText, response.body!!.string())
334+
335+
val eTag = GetETag.fromResponse(response)
336+
assertEquals("My Weak ETag", eTag!!.eTag)
337+
assertTrue(eTag.weak)
338+
assertEquals("application/x-test-result".toMediaType(), GetContentType(response.body!!.contentType()!!).type)
339+
}
340+
assertTrue(called)
341+
342+
var rq = mockServer.takeRequest()
343+
assertEquals("POST", rq.method)
344+
assertEquals(url.encodedPath, rq.path)
345+
assertTrue(rq.getHeader("Content-Type")?.contains("application/x-test-result") == true)
346+
assertEquals("body", rq.body.readUtf8())
347+
348+
// 302 Moved Temporarily + 200 OK
349+
mockServer.enqueue(
350+
MockResponse()
351+
.setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)
352+
.setHeader("Location", "/target")
353+
.setBody("This resource was moved.")
354+
)
355+
mockServer.enqueue(
356+
MockResponse()
357+
.setResponseCode(HttpURLConnection.HTTP_OK)
358+
.setHeader("ETag", "\"StrongETag\"")
359+
.setBody(sampleText)
360+
)
361+
called = false
362+
dav.post(
363+
body = "body".toRequestBody("application/x-test-result".toMediaType())
364+
) { response ->
365+
called = true
366+
assertEquals(sampleText, response.body!!.string())
367+
val eTag = GetETag(response.header("ETag")!!)
368+
assertEquals("StrongETag", eTag.eTag)
369+
assertFalse(eTag.weak)
370+
}
371+
assertTrue(called)
372+
373+
mockServer.takeRequest()
374+
rq = mockServer.takeRequest()
375+
assertEquals("POST", rq.method)
376+
assertEquals("/target", rq.path)
377+
378+
// 200 OK without ETag in response
379+
mockServer.enqueue(
380+
MockResponse()
381+
.setResponseCode(HttpURLConnection.HTTP_OK)
382+
.setBody(sampleText)
383+
)
384+
called = false
385+
dav.post(
386+
body = "body".toRequestBody("application/x-test-result".toMediaType())
387+
) { response ->
388+
called = true
389+
assertNull(response.header("ETag"))
390+
}
391+
assertTrue(called)
392+
}
393+
313394
@Test
314395
fun testMove() {
315396
val url = sampleUrl()

0 commit comments

Comments
 (0)