Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,15 @@ class UppercaseRequestInterceptor : Interceptor {

/** Returns a request that transforms `request` to be all uppercase. */
private fun uppercaseRequest(request: Request): Request {
val body = request.body ?: return request
val uppercaseBody: RequestBody =
object : ForwardingRequestBody(request.body) {
object : ForwardingRequestBody(delegate = body) {
@Throws(IOException::class)
override fun writeTo(sink: BufferedSink) {
delegate().writeTo(uppercaseSink(sink).buffer())
}
}
return request
.newBuilder()
.method(request.method, uppercaseBody)
.build()
return request.newBuilder().method(request.method, uppercaseBody).build()
}

private fun uppercaseSink(sink: Sink): Sink =
Expand Down
11 changes: 11 additions & 0 deletions okhttp/api/android/okhttp.api
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,17 @@ public final class okhttp3/FormBody$Builder {
public final class okhttp3/FormBody$Companion {
}

public class okhttp3/ForwardingRequestBody : okhttp3/RequestBody {
public fun <init> (Lokhttp3/RequestBody;)V
public fun contentLength ()J
public fun contentType ()Lokhttp3/MediaType;
public final fun delegate ()Lokhttp3/RequestBody;
public fun isDuplex ()Z
public fun isOneShot ()Z
public fun toString ()Ljava/lang/String;
public fun writeTo (Lokio/BufferedSink;)V
}

public final class okhttp3/Gzip : okhttp3/CompressionInterceptor$DecompressionAlgorithm {
public static final field INSTANCE Lokhttp3/Gzip;
public fun decompress (Lokio/BufferedSource;)Lokio/Source;
Expand Down
11 changes: 11 additions & 0 deletions okhttp/api/jvm/okhttp.api
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,17 @@ public final class okhttp3/FormBody$Builder {
public final class okhttp3/FormBody$Companion {
}

public class okhttp3/ForwardingRequestBody : okhttp3/RequestBody {
public fun <init> (Lokhttp3/RequestBody;)V
public fun contentLength ()J
public fun contentType ()Lokhttp3/MediaType;
public final fun delegate ()Lokhttp3/RequestBody;
public fun isDuplex ()Z
public fun isOneShot ()Z
public fun toString ()Ljava/lang/String;
public fun writeTo (Lokio/BufferedSink;)V
}

public final class okhttp3/Gzip : okhttp3/CompressionInterceptor$DecompressionAlgorithm {
public static final field INSTANCE Lokhttp3/Gzip;
public fun decompress (Lokio/BufferedSource;)Lokio/Source;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ import java.io.IOException
import okio.BufferedSink

open class ForwardingRequestBody(
delegate: RequestBody?,
private val delegate: RequestBody,
) : RequestBody() {
private val delegate: RequestBody

fun delegate(): RequestBody = delegate

override fun contentType(): MediaType? = delegate.contentType()
Expand All @@ -37,10 +35,7 @@ open class ForwardingRequestBody(

override fun isDuplex(): Boolean = delegate.isDuplex()

override fun toString(): String = javaClass.simpleName + "(" + delegate.toString() + ")"
override fun isOneShot(): Boolean = delegate.isOneShot()

init {
requireNotNull(delegate) { "delegate == null" }
this.delegate = delegate
}
override fun toString(): String = javaClass.simpleName + "(" + delegate.toString() + ")"
}
78 changes: 78 additions & 0 deletions okhttp/src/jvmTest/kotlin/okhttp3/ForwardingRequestBodyTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package okhttp3

import assertk.assertThat
import assertk.assertions.isEqualTo
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import okio.Buffer
import okio.BufferedSink
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import org.junit.jupiter.params.provider.NullSource
import org.junit.jupiter.params.provider.ValueSource

open class ForwardingRequestBodyTest {
/**
* Verifies that overriding the content type preserves the delegate's content,
* content length, and one-shot and duplex flags.
*/
@ParameterizedTest
@CsvSource(
"false, false",
"false, true",
"true, false",
"true, true",
)
fun overridingContentTypePreservesBodyBehavior(
oneShot: Boolean,
duplex: Boolean,
) {
val originalType = "text/plain".toMediaType()
val overriddenType = "application/octet-stream".toMediaType()

val delegate =
object : RequestBody() {
override fun contentType(): MediaType = originalType

override fun contentLength(): Long = 5L

override fun writeTo(sink: BufferedSink) {
sink.writeUtf8("hello")
}

override fun isOneShot(): Boolean = oneShot

override fun isDuplex(): Boolean = duplex
}

val forwardingBody =
object : ForwardingRequestBody(delegate) {
override fun contentType(): MediaType = overriddenType
}

assertThat(forwardingBody.contentType()).isEqualTo(overriddenType)
assertThat(delegate.contentType()).isEqualTo(originalType)
assertThat(forwardingBody.contentLength()).isEqualTo(5L)
assertThat(forwardingBody.isOneShot()).isEqualTo(oneShot)
assertThat(forwardingBody.isDuplex()).isEqualTo(duplex)

val sink = Buffer()
forwardingBody.writeTo(sink)
assertThat(sink.readUtf8()).isEqualTo("hello")
}

/**
* Verifies that the delegate's content type is forwarded, including null
* when the delegate does not specify one.
*/
@ParameterizedTest
@NullSource
@ValueSource(strings = ["text/plain"])
fun forwardsContentType(contentType: String?) {
val mediaType = contentType?.toMediaType()
val delegate = byteArrayOf(1, 2, 3).toRequestBody(mediaType)
val forwardingBody = ForwardingRequestBody(delegate)

assertThat(forwardingBody.contentType()).isEqualTo(mediaType)
}
}
Loading