Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Issue #6314: Support fetching non base64 encoded data URIs
Browse files Browse the repository at this point in the history
  • Loading branch information
csadilek committed Apr 7, 2020
1 parent 0c4fc12 commit 40a09a2
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import mozilla.components.concept.fetch.Response.Companion.CONTENT_LENGTH_HEADER
import mozilla.components.concept.fetch.Response.Companion.CONTENT_TYPE_HEADER
import java.io.ByteArrayInputStream
import java.io.IOException
import java.net.URLDecoder
import java.nio.charset.Charset

/**
* A generic [Client] for fetching resources via HTTP/s.
Expand Down Expand Up @@ -45,25 +47,33 @@ abstract class Client {
abstract fun fetch(request: Request): Response

/**
* Generates a [Response] by decoding a base64 encoded data URI.
* Generates a [Response] based on the provided [Request] for a data URI.
*
* @param request The [Request] for the data URI.
* @return The generated [Response] including the decoded bytes as body.
*/
@Suppress("ThrowsCount", "TooGenericExceptionCaught")
@Suppress("ComplexMethod", "TooGenericExceptionCaught")
protected fun fetchDataUri(request: Request): Response {
if (!request.isDataUri()) {
throw IOException("Not a data URI")
}
return try {
val dataUri = request.url

val dataUri = request.url
if (!dataUri.contains(DATA_URI_BASE64_EXT)) {
throw IOException("Data URI must be base64 encoded")
}
val (contentType, bytes) = if (dataUri.contains(DATA_URI_BASE64_EXT)) {
dataUri.substringAfter(DATA_URI_SCHEME).substringBefore(DATA_URI_BASE64_EXT) to
Base64.decode(dataUri.substring(dataUri.lastIndexOf(',') + 1), Base64.DEFAULT)
} else {
val contentType = dataUri.substringAfter(DATA_URI_SCHEME).substringBefore(",")
val charset = if (contentType.contains(DATA_URI_CHARSET)) {
Charset.forName(contentType.substringAfter(DATA_URI_CHARSET).substringBefore(","))
} else {
Charsets.UTF_8
}
contentType to
URLDecoder.decode(dataUri.substring(dataUri.lastIndexOf(',') + 1), charset.name()).toByteArray()
}

return try {
val contentType = dataUri.substringAfter(DATA_URI_SCHEME).substringBefore(DATA_URI_BASE64_EXT)
val bytes = Base64.decode(dataUri.substring(dataUri.lastIndexOf(',') + 1), Base64.DEFAULT)
val headers = MutableHeaders().apply {
set(CONTENT_LENGTH_HEADER, bytes.size.toString())
if (contentType.isNotEmpty()) {
Expand Down Expand Up @@ -107,5 +117,6 @@ abstract class Client {
companion object {
const val DATA_URI_BASE64_EXT = ";base64"
const val DATA_URI_SCHEME = "data:"
const val DATA_URI_CHARSET = "charset="
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,11 @@ abstract class FetchTestCases {
assertEquals("13", responseNoContentType.headers["Content-Length"])
assertNull(responseNoContentType.headers["Content-Type"])
assertEquals("Hello, World!", responseNoContentType.body.string())

val responseNoBase64 = client.fetch(Request(url = "data:text/plain;charset=utf-8,Hello%2C%20World%21"))
assertEquals("13", responseNoBase64.headers["Content-Length"])
assertEquals("text/plain;charset=utf-8", responseNoBase64.headers["Content-Type"])
assertEquals("Hello, World!", responseNoBase64.body.string())
}

private inline fun withServerResponding(
Expand Down

0 comments on commit 40a09a2

Please sign in to comment.