Skip to content

Commit 1ddc5a8

Browse files
committed
feat: add curl() method test cases to RequestTest for generating cURL commands
1 parent dfbbc8a commit 1ddc5a8

File tree

2 files changed

+119
-9
lines changed

2 files changed

+119
-9
lines changed

okhttp/src/commonJvmAndroid/kotlin/okhttp3/Request.kt

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ class Request internal constructor(
423423

424424
open fun build(): Request = Request(this)
425425
}
426-
426+
427427
/**
428428
* Returns a cURL command equivalent to this request, useful for debugging and reproducing requests.
429429
*
@@ -442,20 +442,39 @@ class Request internal constructor(
442442
if (method != "GET") {
443443
curl.append(" -X ").append(method)
444444
}
445-
445+
446446
for ((name, value) in headers) {
447-
curl.append(" -H ")
448-
.append("\"").append(name).append(": ").append(value).append("\"")
447+
curl
448+
.append(" -H ")
449+
.append("\"")
450+
.append(name)
451+
.append(": ")
452+
.append(value)
453+
.append("\"")
449454
}
450-
455+
451456
body?.let { requestBody ->
452457
val buffer = okio.Buffer()
453458
requestBody.writeTo(buffer)
454-
val bodyString = buffer.readUtf8()
455-
curl.append(" --data ")
456-
.append("\"").append(bodyString.replace("\"", "\\\"")).append("\"")
459+
460+
val contentType = requestBody.contentType()?.toString() ?: ""
461+
462+
if (contentType.startsWith("text/") ||
463+
contentType.contains("json") ||
464+
contentType.contains("xml") ||
465+
contentType.contains("form-urlencoded")
466+
) {
467+
val bodyString = buffer.readUtf8()
468+
curl
469+
.append(" --data ")
470+
.append("\"")
471+
.append(bodyString.replace("\"", "\\\""))
472+
.append("\"")
473+
} else {
474+
curl.append(" --data-binary \"[binary body omitted]\"")
475+
}
457476
}
458-
477+
459478
curl.append(" \"").append(url).append("\"")
460479
return curl.toString()
461480
}

okhttp/src/jvmTest/kotlin/okhttp3/RequestTest.kt

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,97 @@ class RequestTest {
643643
}
644644
}
645645

646+
@Test
647+
fun curlGet() {
648+
val request =
649+
Request
650+
.Builder()
651+
.url("https://example.com")
652+
.header("Authorization", "Bearer abc123")
653+
.build()
654+
val curl = request.curl()
655+
assertThat(curl).isEqualTo("curl -H \"Authorization: Bearer abc123\" \"https://example.com/\"")
656+
}
657+
658+
@Test
659+
fun curlPostWithBody() {
660+
val mediaType = "application/json".toMediaType()
661+
val body = "{\"key\":\"value\"}".toRequestBody(mediaType)
662+
val request =
663+
Request
664+
.Builder()
665+
.url("https://api.example.com/data")
666+
.post(body)
667+
.addHeader("Content-Type", "application/json")
668+
.addHeader("Authorization", "Bearer abc123")
669+
.build()
670+
val curl = request.curl()
671+
assertThat(
672+
curl,
673+
).isEqualTo(
674+
"curl -X POST -H \"Content-Type: application/json\" -H \"Authorization: Bearer abc123\" --data \"{\\\"key\\\":\\\"value\\\"}\" \"https://api.example.com/data\"",
675+
)
676+
}
677+
678+
@Test
679+
fun curlPostWithComplexBody() {
680+
val mediaType = "application/json".toMediaType()
681+
val jsonBody =
682+
"""
683+
{
684+
"user": {
685+
"id": 123,
686+
"name": "John Doe"
687+
},
688+
"roles": ["admin", "editor"],
689+
"active": true
690+
}
691+
""".trimIndent()
692+
val body = jsonBody.toRequestBody(mediaType)
693+
val request =
694+
Request
695+
.Builder()
696+
.url("https://api.example.com/users")
697+
.post(body)
698+
.addHeader("Content-Type", "application/json")
699+
.addHeader("Authorization", "Bearer xyz789")
700+
.build()
701+
val curl = request.curl()
702+
assertThat(curl).isEqualTo(
703+
"curl -X POST -H \"Content-Type: application/json\" -H \"Authorization: Bearer xyz789\" --data \"{\n" +
704+
" \\\"user\\\": {\n" +
705+
" \\\"id\\\": 123,\n" +
706+
" \\\"name\\\": \\\"John Doe\\\"\n" +
707+
" },\n" +
708+
" \\\"roles\\\": [\\\"admin\\\", \\\"editor\\\"],\n" +
709+
" \\\"active\\\": true\n" +
710+
"}\" \"https://api.example.com/users\"",
711+
)
712+
}
713+
714+
@Test
715+
fun curlPostWithBinaryBody() {
716+
val mediaType = "application/octet-stream".toMediaType()
717+
val binaryData = byteArrayOf(0x00, 0x01, 0x02, 0x03, 0x04)
718+
719+
val body = RequestBody.create(mediaType, binaryData)
720+
721+
val request =
722+
Request
723+
.Builder()
724+
.url("https://api.example.com/upload")
725+
.post(body)
726+
.addHeader("Content-Type", "application/octet-stream")
727+
.build()
728+
729+
val curl = request.curl()
730+
assertThat(
731+
curl,
732+
).isEqualTo(
733+
"curl -X POST -H \"Content-Type: application/octet-stream\" --data-binary \"[binary body omitted]\" \"https://api.example.com/upload\"",
734+
)
735+
}
736+
646737
private fun bodyToHex(body: RequestBody): String {
647738
val buffer = Buffer()
648739
body.writeTo(buffer)

0 commit comments

Comments
 (0)