Android – okhttp NullPointerException в Cookie.name()Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Android – okhttp NullPointerException в Cookie.name()

Сообщение Anonymous »

В последнее время я начал получать исключение в рабочей среде, когда приложение жалуется на исключение NullPointerException при попытке доступа к экземпляру Cookie okhttp. Мы не можем воспроизвести его, и это довольно сбивает с толку, поскольку не только код написан на Kotlin и использует типы, не допускающие значения NULL, но и файлы cookie в основном управляются okhttp.
Вот начало трассировки стека :

Код: Выделить всё

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String okhttp3.Cookie.name()' on a null object reference
at okhttp3.internal.http.BridgeInterceptor.cookieHeader(SourceFile:39)
Проверив этот метод cookieHeader, мы видим, что он пытается получить доступ к свойству name файла cookie, как указано в трассировке стека ( код okhttp):

Код: Выделить всё

private fun cookieHeader(cookies: List): String = buildString {
cookies.forEachIndexed { index, cookie ->
if (index > 0) append("; ")
append(cookie.name).append('=').append(cookie.value) // here
}
}
Этот метод вызывается только в одном месте, в методе intercept BridgeInterceptor (перехватчик okhttp по умолчанию):

Код: Выделить всё

// ...

val cookies = cookieJar.loadForRequest(userRequest.url)
if (cookies.isNotEmpty()) {
requestBuilder.header("Cookie", cookieHeader(cookies)) // only called here
}
// ...
Файлы cookie поступают из этого экземпляра cookieJar посредством вызова loadForRequest. Я тот, кто внедряет экземпляр cookieJar в okhttp. Это соответствует следующему интерфейсу (из okhttp):

Код: Выделить всё

interface CookieJar {
/**
* Saves [cookies] from an HTTP response to this store according to this jar's policy.
*
* Note that this method may be called a second time for a single HTTP response if the response
* includes a trailer. For this obscure HTTP feature, [cookies] contains only the trailer's
* cookies.
*/
fun saveFromResponse(url: HttpUrl, cookies: List)

/**
* Load cookies from the jar for an HTTP request to [url]. This method returns a possibly
* empty list of cookies for the network request.
*
* Simple implementations will return the accepted cookies that have not yet expired and that
* [match][Cookie.matches] [url].
*/
fun loadForRequest(url: HttpUrl): List
Моя реализация начинается с 0 файлов cookie, и в конечном итоге некоторые из них сохраняются, когда okhttp вызывает метод saveFromResponse. Последующие запросы будут использовать все файлы cookie, сохраненные посредством вызова loadForRequest, который мы видели ранее. Вот моя реализация:

Код: Выделить всё

class OkHttpCookieJar() : CookieJar {

companion object {
var cookieStore = mutableMapOf()

fun clearCookies() {
cookieStore = mutableMapOf()
}
}

override fun saveFromResponse(url: HttpUrl, cookies: List) {
if (cookies.isEmpty()) {
return
}

val urlString = url.toString()

for (cookie in cookies) {
cookieStore[cookie.name] = cookie
}
}

override fun loadForRequest(url: HttpUrl): List {
return cookieStore.values.toList()
}
}
Для завершения, вот где вызывается saveFromResponse (код oktthp):

Код: Выделить всё

fun CookieJar.receiveHeaders(url: HttpUrl, headers: Headers) {
if (this === CookieJar.NO_COOKIES) return

val cookies = Cookie.parseAll(url, headers)
if (cookies.isEmpty()) return

saveFromResponse(url, cookies) // here
}
Этот вызов Cookie.parseAll внутренне вызывает метод анализа, который может вернуть нулевой файл cookie, но parseAll< /code> просто пропускает его, если оно равно нулю (код okhttp):

Код: Выделить всё

@JvmStatic
fun parseAll(url: HttpUrl, headers: Headers): List {
val cookieStrings = headers.values("Set-Cookie")
var cookies: MutableList? = null

for (i in 0 until cookieStrings.size) {
val cookie = parse(url, cookieStrings[i]) ?: continue // skips to next iteration if null
if (cookies == null) cookies = mutableListOf()
cookies.add(cookie)
}

return if (cookies != null) {
Collections.unmodifiableList(cookies)
} else {
emptyList()
}
}
Наконец, мой вопрос: учитывая, что я сохраняю и возвращаю только файлы cookie, которые дает мне okhttp, и у меня повсюду есть типы, не допускающие значения NULL, откуда могло взяться это исключение NullPointerException? Я также без проблем получаю доступ к экземпляру cookie в saveFromResponse, чтобы использовать его имя в качестве ключа для карты.
Моя первая теория заключалась в том, что какой-то Java-код в okhttp каким-то образом удалось проникнуть в нулевой файл cookie, но код в версии, которую я использую (4.10.0), полностью написан на Kotlin.
Заранее благодарен за любую предоставленную информацию.

Подробнее здесь: https://stackoverflow.com/questions/789 ... ookie-name
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»