重构 CommonParamInterceptor, 自动选择公共参数添加位置

This commit is contained in:
czp3009 2019-03-11 23:44:59 +08:00
parent bfa7a55c45
commit 4b2e2181fb
10 changed files with 49 additions and 67 deletions

View File

@ -11,7 +11,6 @@ import com.hiczp.bilibili.api.player.PlayerAPI
import com.hiczp.bilibili.api.player.PlayerInterceptor
import com.hiczp.bilibili.api.retrofit.Header
import com.hiczp.bilibili.api.retrofit.Param
import com.hiczp.bilibili.api.retrofit.ParamType
import com.hiczp.bilibili.api.retrofit.exception.BilibiliApiException
import com.hiczp.bilibili.api.retrofit.interceptor.CommonHeaderInterceptor
import com.hiczp.bilibili.api.retrofit.interceptor.CommonParamInterceptor
@ -90,7 +89,7 @@ class BilibiliClient(
Param.TIMESTAMP to { Instant.now().epochSecond.toString() }
)
private val defaultCommonQueryParamInterceptor = CommonParamInterceptor(ParamType.QUERY, *defaultCommonParamArray)
private val defaultCommonParamInterceptor = CommonParamInterceptor(*defaultCommonParamArray)
/**
* 用户鉴权相关的接口
@ -99,7 +98,7 @@ class BilibiliClient(
val passportAPI by lazy {
createAPI<PassportAPI>(BaseUrl.passport,
defaultCommonHeaderInterceptor,
CommonParamInterceptor(ParamType.FORM_URL_ENCODED,
CommonParamInterceptor(
Param.APP_KEY to { billingClientProperties.appKey },
Param.BUILD to { billingClientProperties.build },
Param.CHANNEL to { billingClientProperties.channel },
@ -117,7 +116,7 @@ class BilibiliClient(
val messageAPI by lazy {
createAPI<MessageAPI>(BaseUrl.message,
defaultCommonHeaderInterceptor,
CommonParamInterceptor(ParamType.QUERY, *defaultCommonParamArray,
CommonParamInterceptor(*defaultCommonParamArray,
Param.ACTION_KEY to { Param.APP_KEY },
"has_up" to { "1" }
)
@ -131,7 +130,7 @@ class BilibiliClient(
val appAPI by lazy {
createAPI<AppAPI>(BaseUrl.app,
defaultCommonHeaderInterceptor,
defaultCommonQueryParamInterceptor
defaultCommonParamInterceptor
)
}
@ -148,7 +147,7 @@ class BilibiliClient(
Header.USER_AGENT to { billingClientProperties.defaultUserAgent },
Header.DEVICE_ID to { billingClientProperties.hardwareId }
),
defaultCommonQueryParamInterceptor
defaultCommonParamInterceptor
)
}
@ -159,7 +158,7 @@ class BilibiliClient(
val vcAPI by lazy {
createAPI<VcAPI>(BaseUrl.vc,
defaultCommonHeaderInterceptor,
CommonParamInterceptor(ParamType.QUERY, *defaultCommonParamArray,
CommonParamInterceptor(*defaultCommonParamArray,
Param._DEVICE to { billingClientProperties.platform },
Param._HARDWARE_ID to { billingClientProperties.hardwareId },
Param.SOURCE to { billingClientProperties.channel },
@ -176,7 +175,7 @@ class BilibiliClient(
val memberAPI by lazy {
createAPI<MemberAPI>(BaseUrl.member,
defaultCommonHeaderInterceptor,
defaultCommonQueryParamInterceptor
defaultCommonParamInterceptor
)
}
@ -210,7 +209,7 @@ class BilibiliClient(
Header.ACCEPT_ENCODING to { "gzip, deflate" },
Header.USER_AGENT to { billingClientProperties.defaultUserAgent }
))
addInterceptor(defaultCommonQueryParamInterceptor)
addInterceptor(defaultCommonParamInterceptor)
addInterceptor(sortAndSignInterceptor)
addNetworkInterceptor(httpLoggingInterceptor)
}.build())

View File

@ -2,7 +2,6 @@ package com.hiczp.bilibili.api.app
import com.hiczp.bilibili.api.app.model.*
import com.hiczp.bilibili.api.retrofit.CommonResponse
import com.hiczp.bilibili.api.retrofit.Header
import kotlinx.coroutines.Deferred
import retrofit2.http.*
import java.time.Instant
@ -119,7 +118,6 @@ interface AppAPI {
*/
@POST("/x/v2/view/like")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun like(
@Field("aid") aid: Long,
@Field("like") like: Int = 0,
@ -136,7 +134,6 @@ interface AppAPI {
*/
@POST("/x/v2/view/dislike")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun dislike(
@Field("aid") aid: Long,
@Field("like") like: Int = 0,
@ -157,7 +154,6 @@ interface AppAPI {
@Suppress("SpellCheckingInspection")
@POST("/x/v2/view/coin/add")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun addCoin(
@Field("aid") aid: Long,
@Field("avtype") avType: Int = 1,

View File

@ -154,7 +154,6 @@ interface MainAPI {
*/
@POST("/x/v2/reply/add")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun sendReply(
@Field("from") from: Int? = null,
@Field("message") message: String,
@ -175,7 +174,6 @@ interface MainAPI {
@Suppress("SpellCheckingInspection")
@POST("/x/v2/reply/action")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun likeReply(
@Field("action") action: Int,
@Field("oid") oid: Long,
@ -193,7 +191,6 @@ interface MainAPI {
@Suppress("SpellCheckingInspection")
@POST("/x/v2/reply/hate")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun dislikeReply(
@Field("action") action: Int,
@Field("oid") oid: Long,
@ -225,7 +222,6 @@ interface MainAPI {
*/
@POST("/x/relation/modify")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun modifyRelation(
@Field("act") action: Int,
@Field("fid") followId: Long,
@ -246,7 +242,6 @@ interface MainAPI {
*/
@POST("/x/relation/tag/create")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun createRelationTag(@Field("tag") tag: String): Deferred<CreateRelationTagResponse>
/**
@ -259,7 +254,6 @@ interface MainAPI {
@Suppress("SpellCheckingInspection")
@POST("/x/relation/tags/addUsers")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun relationAddUsers(
@Field("fids") followIds: String,
@Field("tagids") tagIds: String
@ -272,7 +266,6 @@ interface MainAPI {
*/
@POST("/x/article/favorites/add")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun addFavoriteArticle(@Field("id") id: Long): Deferred<CommonResponse>
/**
@ -283,7 +276,6 @@ interface MainAPI {
*/
@POST("/x/article/like")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun articleLike(@Field("id") id: Long, @Field("type") type: Int): Deferred<CommonResponse>
/**
@ -307,7 +299,6 @@ interface MainAPI {
*/
@POST("/x/v2/fav/folder/add")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun createFavoriteFolder(
@Field("name") name: String,
@Field("public") public: Int = 0
@ -320,7 +311,6 @@ interface MainAPI {
*/
@POST("/x/v2/fav/video/add")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun addFavoriteVideo(
@Field("aid") aid: Long,
@Field("fid") fid: String,
@ -336,7 +326,6 @@ interface MainAPI {
*/
@POST("/x/v2/fav/video/del")
@FormUrlEncoded
@Headers(Header.FORCE_FORM_BODY)
fun deleteFavoriteVideo(
@Field("aid") aid: Long,
@Field("fid") fid: String
@ -351,6 +340,7 @@ interface MainAPI {
*/
@POST("/x/v2/dm/post")
@FormUrlEncoded
@Headers(Header.FORCE_QUERY)
fun sendDanmaku(
@Query("aid") aid: Long,
@Query("oid") oid: Long,

View File

@ -6,6 +6,7 @@ import com.hiczp.bilibili.api.passport.model.OAuth2Info
import com.hiczp.bilibili.api.retrofit.CommonResponse
import kotlinx.coroutines.Deferred
import retrofit2.http.*
import java.util.*
/**
* 用户鉴权相关的接口
@ -36,12 +37,12 @@ interface PassportAPI {
@POST("/api/v2/oauth2/revoke")
@FormUrlEncoded
fun revoke(
@Field("DedeUserID") dedeUserId: String,
@Field("DedeUserID__ckMd5") ckMd5: String,
@Field("SESSDATA") sessData: String,
@Field("DedeUserID") dedeUserId: String? = null,
@Field("DedeUserID__ckMd5") ckMd5: String? = null,
@Field("SESSDATA") sessData: String? = null,
@Field("access_token") accessToken: String,
@Field("bili_jct") biliJct: String,
@Field("sid") sid: String
@Field("bili_jct") biliJct: String? = null,
@Field("sid") sid: String? = null
): Deferred<CommonResponse>
/**
@ -50,7 +51,7 @@ interface PassportAPI {
@POST("/api/v2/oauth2/revoke")
@FormUrlEncoded
fun revoke(
@FieldMap cookieMap: Map<String, String>,
@FieldMap cookieMap: Map<String, String> = Collections.emptyMap(),
@Field("access_token") accessToken: String
): Deferred<CommonResponse>
@ -60,17 +61,17 @@ interface PassportAPI {
@Suppress("SpellCheckingInspection")
@GET("/api/v2/oauth2/info")
fun info(
@Query("DedeUserID") dedeUserId: String,
@Query("DedeUserID__ckMd5") ckMd5: String,
@Query("SESSDATA") sessData: String,
@Query("DedeUserID") dedeUserId: String? = null,
@Query("DedeUserID__ckMd5") ckMd5: String? = null,
@Query("SESSDATA") sessData: String? = null,
@Query("access_token") accessToken: String,
@Query("bili_jct") biliJct: String,
@Query("sid") sid: String
@Query("bili_jct") biliJct: String? = null,
@Query("sid") sid: String? = null
): Deferred<OAuth2Info>
@GET("/api/v2/oauth2/info")
fun info(
@QueryMap cookieMap: Map<String, String>,
@QueryMap cookieMap: Map<String, String> = Collections.emptyMap(),
@Query("access_token") accessToken: String
): Deferred<OAuth2Info>
}

View File

@ -21,9 +21,12 @@ object Header {
const val ACCEPT_LANGUAGE = "Accept-Language"
const val ACCEPT_ENCODING = "Accept-Encoding"
//强制将公共参数加到 FormBody 上
const val FORCE_FORM_BODY_NAME = "Force-Form-Body"
const val FORCE_FORM_BODY = "$FORCE_FORM_BODY_NAME: true"
//强制公共参数添加位置
const val FORCE_PARAM = "Retrofit-Force-Param"
const val FORCE_PARAM_QUERY = "query"
const val FORCE_PARAM_FORMBODY = "formBody"
const val FORCE_QUERY = "$FORCE_PARAM: $FORCE_PARAM_QUERY"
const val FORCE_FORMBODY = "$FORCE_PARAM: $FORCE_PARAM_FORMBODY"
}
object Param {

View File

@ -42,7 +42,9 @@ fun FormBody.Builder.addAllEncoded(formBody: FormBody): FormBody.Builder {
return this
}
internal inline fun Array<out Pair<String, () -> String?>>.forEachNonNull(action: (String, String) -> Unit) {
typealias ParamExpression = Pair<String, () -> String?>
internal inline fun Array<out ParamExpression>.forEachNonNull(action: (String, String) -> Unit) {
forEach { (name, valueExpression) ->
val value = valueExpression()
if (value != null) {

View File

@ -1,5 +1,6 @@
package com.hiczp.bilibili.api.retrofit.interceptor
import com.hiczp.bilibili.api.retrofit.ParamExpression
import com.hiczp.bilibili.api.retrofit.forEachNonNull
import okhttp3.Interceptor
import okhttp3.Response
@ -9,7 +10,7 @@ import okhttp3.Response
*
* @param additionHeaders HeaderName to HeaderValueExpression
*/
class CommonHeaderInterceptor(private vararg val additionHeaders: Pair<String, () -> String?>) : Interceptor {
class CommonHeaderInterceptor(private vararg val additionHeaders: ParamExpression) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request().newBuilder().apply {
additionHeaders.forEachNonNull { name, value ->

View File

@ -1,9 +1,6 @@
package com.hiczp.bilibili.api.retrofit.interceptor
import com.hiczp.bilibili.api.retrofit.Header
import com.hiczp.bilibili.api.retrofit.ParamType
import com.hiczp.bilibili.api.retrofit.addAllEncoded
import com.hiczp.bilibili.api.retrofit.forEachNonNull
import com.hiczp.bilibili.api.retrofit.*
import mu.KotlinLogging
import okhttp3.FormBody
import okhttp3.Interceptor
@ -13,29 +10,28 @@ private val logger = KotlinLogging.logger {}
/**
* 为请求添加公共参数
* 如果请求为 GET 方式则添加到 Query, 如果是其他其他方式则尝试添加到 BODY.
*
* @param paramType 参数类型, Query FormUrlEncoded
* @param additionParams ParamName to ParamValueExpression
*/
class CommonParamInterceptor(
private var paramType: ParamType,
private vararg val additionParams: Pair<String, () -> String?>
) : Interceptor {
class CommonParamInterceptor(private vararg val additionParams: ParamExpression) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
var headers = request.headers()
var httpUrl = request.url()
var body = request.body()
//是否强制加到 FormBody
if (headers[Header.FORCE_FORM_BODY_NAME] != null) {
paramType = ParamType.FORM_URL_ENCODED
headers = headers.newBuilder().removeAll(Header.FORCE_FORM_BODY_NAME).build()
//是否强制加到 Query(暂不存在强制加到 FormBody 的情况)
var forceQuery = false
val forceParam = headers[Header.FORCE_PARAM]
if (forceParam != null) {
if (forceParam == Header.FORCE_PARAM_QUERY) forceQuery = true
headers = headers.newBuilder().removeAll(Header.FORCE_PARAM).build()
}
when {
//如果欲添加参数的位置为 Query 则直接添加, paramType 为 FORM_URL_ENCODED 则继续下面的判断
paramType == ParamType.QUERY -> {
//如果是 GET 则添加到 Query
request.method() == Method.GET || forceQuery -> {
httpUrl = request.url().newBuilder().apply {
additionParams.forEachNonNull { name, value ->
addQueryParameter(name, value)
@ -43,7 +39,7 @@ class CommonParamInterceptor(
}.build()
}
//BODY 不存在或者是空的
//如果 Body 不存在或者为空则创建一个 FormBody
body == null || body.contentLength() == 0L -> {
body = FormBody.Builder().apply {
additionParams.forEachNonNull { name, value ->
@ -52,7 +48,7 @@ class CommonParamInterceptor(
}.build()
}
//只要 BODY 为 FormBody, 那么里面一定有内容
//如果 Body 为 FormBody 则里面可能已经存在内容
body is FormBody -> {
body = FormBody.Builder().addAllEncoded(body).apply {
additionParams.forEachNonNull { name, value ->
@ -61,6 +57,7 @@ class CommonParamInterceptor(
}.build()
}
//如果方式不为 GET 且 Body 不为空或者为 FormBody 则无法添加公共参数
else -> {
logger.error {
"Cannot add params to request: ${request.method()} ${request.url()} ${body.javaClass.simpleName}"

View File

@ -7,7 +7,7 @@ import retrofit2.http.GET
import retrofit2.http.Query
/**
* 小视频
* 小视频(好像 动态 也是在这个站)
*/
@Suppress("DeferredIsResult")
interface VcAPI {

View File

@ -14,14 +14,7 @@ class UserInfoTest {
@Test
fun oauthInfo() {
runBlocking {
with(bilibiliClient) {
passportAPI.info(
loginResponse!!.data.cookieInfo.cookies.associate {
it.name to it.value
},
token!!
).await()
}
bilibiliClient.passportAPI.info(accessToken = bilibiliClient.token!!).await()
}
}
}