Skip to content

Commit

Permalink
1.优化通过请求头获取文件名的逻辑。
Browse files Browse the repository at this point in the history
2.新增动态url的拦截器和相关注解。
  • Loading branch information
xiazunyang committed Jun 22, 2022
1 parent 2785f60 commit 15105d3
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 30 deletions.
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,39 @@ implementation 'cn.numeron:http:latest_version'
* 其实就是`HttpLoggingInterceptor`,但是解决了在传输非文本数据时,日志输出乱码的问题。
* 解决了`HttpLoggingInterceptor`导致的上传、下载文件时无法触发回调的问题。
* 使用方法:在构建`OkHttpClient`实例时,添加`TextLogInterceptor`实例即可。

### Retrofit Url方案
* 使用`Port``Url`注解为Api指定访问端口或地址。
* 在初始化`OkHttpClient`时,添加`RespecifyUrlInterceptor`拦截器,并放在靠前的位置。
* 示例1:
```kotlin
interface LoginApi {

/** 指定此方法在调用时,访问服务器的8080端口 */
@Port(8080)
@POST("api/user/login")
suspend fun login(@Body payload: LoginPayload): LoginResponse

/** 指定此方法在调用时,访问指定url地址 */
@Url("http://192.168.1.111:8081/")
@POST("api/user/login")
suspend fun logout(@Body payload: LoginPayload): LogoutResponse

}
```

* 示例2
```kotlin
/** 此接口下所有的方法均访问指定的url地址,优先级低于方法上的注解 */
@Url("http://192.168.1.111:8081/")
interface LoginApi {

@POST("api/user/login")
suspend fun login(@Body payload: LoginPayload): LoginResponse

@POST("api/user/login")
suspend fun logout(@Body payload: LoginPayload): LogoutResponse

}
```

56 changes: 31 additions & 25 deletions http/src/main/kotlin/cn/numeron/okhttp/InternalUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,42 @@ package cn.numeron.okhttp
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.Request
import java.io.UnsupportedEncodingException
import java.net.URLDecoder

/** 从请求实例中获取用[retrofit2.http.Tag]注解标记的参数 */
internal inline fun <reified T> Request.getTag(): T? {
return tag(T::class.java)
}

/** 从请求头中获取文件名 */
internal fun Headers.getFileName(): String? {
return get("Content-Disposition")
?.split(';')
?.let { list ->
list.find {
it.contains("filename*")
} ?: list.find {
it.contains("filename")
}
fun Headers.getFileName(): String? {
val contentDisposition = get("Content-Disposition") ?: return null
val properties = contentDisposition
.splitToList(';')
.associate {
it.splitToList('=').toPair()
}
?.split('=')
?.component2()
?.removeSurrounding("\"")
?.let {
if (it.contains('\'')) {
//如果有'字符,则取出编码格式与字符串,解码后返回
val split = it.split('\'').filter(String::isNotBlank)
URLDecoder.decode(split.component2(), split.component1())
} else {
it //否则直接返回字符串
}
val encodedFilename = properties["filename*"]
if (!encodedFilename.isNullOrEmpty()) {
var (coding, fileName) = encodedFilename.splitToList('\'').toPair()
if (fileName == null) {
fileName = coding
coding = "utf-8"
}
try {
return URLDecoder.decode(fileName, coding)
} catch (_: UnsupportedEncodingException) {
}
}
val filename = properties["filename"]
if (!filename.isNullOrEmpty()) {
return filename
}
return null
}

internal fun <T> List<T>.toPair(): Pair<T, T?> {
return get(0) to getOrNull(1)
}

internal fun String.splitToList(char: Char): List<String> {
return split(char).map(String::trim).filter(String::isNotEmpty)
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cn.numeron.okhttp.file

import cn.numeron.okhttp.getFileName
import cn.numeron.okhttp.getTag
import com.j256.simplemagic.ContentType
import okhttp3.Interceptor
import okhttp3.Request
Expand All @@ -17,7 +16,7 @@ class BreakpointResumeInterceptor : Interceptor {
//获取原始请求
var request = chain.request()
//取出文件参数
val fileOrDir = request.getTag<File>()
val fileOrDir = request.tag(File::class.java)
//获取原请求
var response = chain.proceed(request)
if (fileOrDir == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package cn.numeron.okhttp.file

import cn.numeron.okhttp.getTag
import okhttp3.*
import java.io.File

Expand Down Expand Up @@ -39,8 +38,8 @@ class ProgressInterceptor : Interceptor {
//获取原始请求
var request = chain.request()
//取出进度回调参数
val upProgressCallback = request.getTag<UpProgressCallback>()
val dlProgressCallback = request.getTag<DlProgressCallback>()
val upProgressCallback = request.tag(UpProgressCallback::class.java)
val dlProgressCallback = request.tag(DlProgressCallback::class.java)
if (upProgressCallback != null && request.body != null) {
//如果有上传进度回调,并且有请求体,则构建新的请求体实例,以监听进度回调
val progressRequestBody = ProgressRequestBody(request.body!!, upProgressCallback)
Expand Down
5 changes: 5 additions & 0 deletions http/src/main/kotlin/cn/numeron/retrofit/Port.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package cn.numeron.retrofit

@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Port(val value: Int)
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cn.numeron.retrofit

import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor
import okhttp3.Response
import retrofit2.Invocation

class RespecifyUrlInterceptor : Interceptor {

override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val invocation = request.tag(Invocation::class.java)
if (invocation != null) {
val httpUrl = getNewHttpUrl(invocation, request.url)
request = request.newBuilder().url(httpUrl).build()
}
return chain.proceed(request)
}

private fun getNewHttpUrl(invocation: Invocation, originalHttpUrl: HttpUrl): HttpUrl {
val method = invocation.method()
var urlAnnotation = method.getAnnotation(Url::class.java)
var portAnnotation = method.getAnnotation(Port::class.java)
if (urlAnnotation == null && portAnnotation == null) {
val klass = method.declaringClass
urlAnnotation = klass.getAnnotation(Url::class.java)
portAnnotation = klass.getAnnotation(Port::class.java)
}
return when {
urlAnnotation != null -> {
val url = urlAnnotation.value.toHttpUrl()
originalHttpUrl.newBuilder().host(url.host).port(url.port).build()
}
portAnnotation != null -> {
val port = portAnnotation.value
originalHttpUrl.newBuilder().port(port).build()
}
else -> {
originalHttpUrl
}
}
}

}
5 changes: 5 additions & 0 deletions http/src/main/kotlin/cn/numeron/retrofit/Url.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package cn.numeron.retrofit

@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class Url(val value: String)

0 comments on commit 15105d3

Please sign in to comment.