Skip to content

Instantly share code, notes, and snippets.

@CodeK1988
Created September 3, 2019 02:04
Show Gist options
  • Select an option

  • Save CodeK1988/62a0315f6541b4189e7336c48d7b643b to your computer and use it in GitHub Desktop.

Select an option

Save CodeK1988/62a0315f6541b4189e7336c48d7b643b to your computer and use it in GitHub Desktop.
旧项目中使用Volley
移植入Okhttp Retrofit 如何同步cookie
1.之前的思路:
Volley 底层替换
class OkHttpStack(
private val okHttpClient: OkHttpClient
) : BaseHttpStack() {
@Throws(AuthFailureError::class)
private fun setConnectionParametersForRequest(builder: okhttp3.Request.Builder, request: Request<*>) {
when (request.method) {
Request.Method.DEPRECATED_GET_OR_POST -> {
// Ensure backwards compatibility. Volley assumes a request with a null body is a GET.
val postBody = request.body
if (postBody != null) {
builder.post(RequestBody.create(MediaType.parse(request.bodyContentType), postBody))
}
}
Request.Method.GET -> builder.get()
Request.Method.DELETE -> builder.delete(createRequestBody(request))
Request.Method.POST -> builder.post(createRequestBody(request))
Request.Method.PUT -> builder.put(createRequestBody(request))
Request.Method.HEAD -> builder.head()
Request.Method.OPTIONS -> builder.method("OPTIONS", null)
Request.Method.TRACE -> builder.method("TRPersistentCookieStoreACE", null)
Request.Method.PATCH -> builder.patch(createRequestBody(request))
else -> throw IllegalStateException("Unknown method type.")
}
}
@Throws(AuthFailureError::class)
private fun createRequestBody(r: Request<*>): RequestBody? {
val body = r.body ?: return null
return RequestBody.create(MediaType.parse(r.bodyContentType), body)
}
@Throws(IOException::class, AuthFailureError::class)
override fun executeRequest(request: Request<*>, additionalHeaders: Map<String, String>): HttpResponse {
val timeoutMs = request.timeoutMs
val clientBuilder = okHttpClient.newBuilder()
clientBuilder.connectTimeout(timeoutMs.toLong(), TimeUnit.MILLISECONDS)
clientBuilder.readTimeout(timeoutMs.toLong(), TimeUnit.MILLISECONDS)
clientBuilder.writeTimeout(timeoutMs.toLong(), TimeUnit.MILLISECONDS)
val okHttpRequestBuilder = okhttp3.Request.Builder()
okHttpRequestBuilder.url(request.url)
val headers = request.headers
headers.keys.forEach { name ->
headers[name]?.also { value ->
okHttpRequestBuilder.addHeader(name, value)
}
}
additionalHeaders.keys.forEach { name ->
additionalHeaders[name]?.also { value ->
okHttpRequestBuilder.addHeader(name, value)
}
}
setConnectionParametersForRequest(okHttpRequestBuilder, request)
val client = clientBuilder.build()
val okHttpRequest = okHttpRequestBuilder.build()
val okHttpCall = client.newCall(okHttpRequest)
val okHttpResponse = okHttpCall.execute()
val code = okHttpResponse.code()
val body = okHttpResponse.body()
val content = body?.byteStream()
val contentLength = body?.contentLength()?.toInt() ?: 0
val responseHeaders = mapHeaders(okHttpResponse.headers())
return HttpResponse(code, responseHeaders, contentLength, content)
}
private fun mapHeaders(responseHeaders: Headers): List<Header> {
val headers = ArrayList<Header>()
(0 until responseHeaders.size()).forEach {
headers.add(Header(responseHeaders.name(it), responseHeaders.value(it)))
}
return headers
}
}
CookieHandler.setDefault(new CookieManager(new SPCookieStore(context), CookiePolicy.ACCEPT_ALL));
Volley.newRequestQueue(context, new OkHttpStack(getClient()));
fun getClient(): OkHttpClient {
val cookieJar = JavaNetCookieJar(CookieManager(PersistentCookieStore(CETApplication.mcontext), CookiePolicy.ACCEPT_ALL))
return OkHttpClient.Builder()
// .cookieJar(CookieJarImpl(CookieHandler.getDefault()))
.cookieJar(cookieJar) // not working first time when login in
.addInterceptor(OnlineInterceptor())
.addNetworkInterceptor(OnlineInterceptor())
.addInterceptor(HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
})
.build()
}
not working first time when login in cookie没办法同步也可能我写的有问题。
2.Volley用Volley的一套 只保证新引入的Okhttp cookie能同步即可
Volley.newRequestQueue(context,new CustomHurlStack());
Okhttp .setOkHttpClient(getClient())
fun getClient(): OkHttpClient {
return OkHttpClient.Builder()
.cookieJar(CookieJarImpl(CookieHandler.getDefault()))
.addNetworkInterceptor(OnlineInterceptor())
.addInterceptor(HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
})
.build()
}
class CookieJarImpl(private val cookieHandler: CookieHandler?) : CookieJar {
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
if (cookieHandler != null) {
val cookieStrings = ArrayList<String>()
for (cookie in cookies) {
cookieStrings.add(cookie.toString().replace("; domain=".toRegex(), "; domain=."))
}
val multimap = Collections.singletonMap<String, List<String>>("Set-Cookie", cookieStrings)
try {
cookieHandler.put(url.uri(), multimap)
} catch (e: IOException) {
Platform.get().log(WARN, "Saving cookies failed for " + url.resolve("/...")!!, e)
}
}
}
override fun loadForRequest(url: HttpUrl): List<Cookie> {
val headers = emptyMap<String, List<String>>()
val cookieHeaders: Map<String, List<String>>
try {
cookieHeaders = cookieHandler!!.get(url.uri(), headers)
} catch (e: Exception) {
return emptyList()
}
var cookies: MutableList<Cookie>? = null
for ((key, value) in cookieHeaders) {
if (("Cookie".equals(key, ignoreCase = true) || "Cookie2".equals(
key,
ignoreCase = true
)) && !value.isEmpty()
) {
for (header in value) {
if (cookies == null) cookies = ArrayList()
cookies.addAll(decodeHeaderAsJavaNetCookies(url, header))
}
}
}
return if (cookies != null)
Collections.unmodifiableList(cookies)
else
emptyList()
}
private fun decodeHeaderAsJavaNetCookies(url: HttpUrl, header: String): List<Cookie> {
val result = ArrayList<Cookie>()
var pos = 0
val limit = header.length
var pairEnd: Int
while (pos < limit) {
pairEnd = delimiterOffset(header, pos, limit, ";,")
val equalsSign = delimiterOffset(header, pos, pairEnd, '=')
val name = trimSubstring(header, pos, equalsSign)
if (name.startsWith("$")) {
pos = pairEnd + 1
continue
}
val value = if (equalsSign < pairEnd)
trimSubstring(header, equalsSign + 1, pairEnd)
else
""
result.add(
Cookie.Builder()
.name(name)
.value(value)
.domain(url.host())
.build()
)
pos = pairEnd + 1
}
return result
}
}
这样是正常工作的~
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment