Android Developer

设定网络请求的header信息

描述

  • 支持按照域名设置对应的header信息

  • 支持移除不需要的header信息

  • 去除之前全局白名单处理

相关类说明

  • HeaderUtils 提供通用的header信息辅助类

  • RequestHeaderProvider 总的对外暴露提供请求Header信息的类

  • HeaderDataResponder 基础的Header数据提供响应者,使得提供header信息能够像插件一样。

  • GeneralHeaderDataResponder 通用的header信息响应者,用来处理改进之前的提供header信息。

如何添加指定域名的Header信息

在已有的HeaderDataResponder增加对应的host

比如某个HeaderDataResponder满足需要提供的header数据,可以直接在其中增加host即可。

如下以添加droidyue.com为例。

package com.secoo.commonsdk.http.headers.responder

import com.secoo.commonsdk.core.Constants.*
import com.secoo.commonsdk.http.headers.HeaderDataResponder
import com.secoo.commonsdk.http.headers.HeaderUtils

/**
 * 之前全局处理的header信息,支持响应多个域名
 */
object GeneralHeaderDataResponder : HeaderDataResponder() {
    override fun provideDomainsToRespond(): List<String> {
        return listOf(HOST_LAS, HOST_LR, HOST_MSHOPPING, HOST_ANDROID,
                HOST_MMY, HOST_PAY, HOST_USER, HOST_CONTENT,
                HOST_CRM,HOST_CUSTOMER).mapNotNull { HeaderUtils.getHostOfUrl(it) }
                .plus("droidyue.com")//对应的代码
    }

    override fun provideDynamicHeaders(): Map<String, String> {
        return HeaderUtils.createHeaders()
    }
}

建立对应的HeaderDataResponder类

以添加datacollect.secoo.com域名header信息为例

package com.secoo.commonsdk.http.headers.responder

import com.secoo.commonsdk.base.SecooApplication
import com.secoo.commonsdk.count.distinctId
import com.secoo.commonsdk.count.networkType
import com.secoo.commonsdk.http.headers.HeaderDataResponder
import com.secoo.commonsdk.http.headers.HeaderUtils
import com.secoo.commonsdk.ktx.*
import com.secoo.commonsdk.utils.DeviceUtils

object DataCollectHeaderDataResponder : HeaderDataResponder() {

    private const val HEADER_DISTINCT_ID = "distinct_id"
    private const val HEADER_APP_VERSION = "app_version"
    private const val HEADER_DEVICE_MANUFACTURER = "manufacturer"
    private const val HEADER_DEVICE_MODEL = "model"
    private const val HEADER_DEVICE_OS_NAME = "os"
    private const val HEADER_DEVICE_OS_VERSION = "os_version"
    private const val HEADER_DEVICE_SCREEN_HEIGHT = "screen_height"
    private const val HEADER_DEVICE_SCREEN_WIDTH = "screen_width"
    private const val HEADER_DEVICE_MOBILE_CARRIER = "carrier"
    private const val HEADER_NETWORK_TYPE = "network_type"
    private const val HEADER_DEVICE_ID = "device_id"

    //提供静态不变的header信息
    override fun createStaticHeaders(): Map<String, String> {
        return mapOf(
                HEADER_APP_VERSION to appVersionName,
                HEADER_DEVICE_MANUFACTURER to deviceManufacturer,
                HEADER_DEVICE_MODEL to deviceModel,
                HEADER_DEVICE_OS_NAME to "android",
                HEADER_DEVICE_OS_VERSION to systemVersion.toString(),
                HEADER_DEVICE_SCREEN_HEIGHT to screenHeight.toString(),
                HEADER_DEVICE_SCREEN_WIDTH to screenWidth.toString(),
                HEADER_DEVICE_MOBILE_CARRIER to mobileCarrier,
                HEADER_DEVICE_ID to (DeviceUtils.getUUID(SecooApplication.getInstance()) ?:"")
        )
    }

    //提供动态易变的header信息
    override fun provideDynamicHeaders(): Map<String, String> {
        return mutableMapOf(
                HEADER_DISTINCT_ID to distinctId,
                HEADER_NETWORK_TYPE to networkType
        ).plus(HeaderUtils.createHeaders())
    }

    //添加想要处理的host信息
    override fun provideDomainsToRespond(): List<String> {
        return listOf("datacollect.secoo.com")
    }

}

添加到响应者队列

object RequestHeaderProvider {
    /**
     * 根据host遍历,提供header数据的响应者列表
     */
    private val headerDataResponders = mutableListOf<HeaderDataResponder>()

    init {
        headerDataResponders.add(GeneralHeaderDataResponder)
        //添加上面创建的DataCollectHeaderDataResponder
        headerDataResponders.add(DataCollectHeaderDataResponder)
    }
    //.......
}

调试日志

adb logcat |grep --color=always -E "HeaderDataResponder|RequestHeaderProvider"

Header 过滤非法名称和值

  • 目前我们使用的OkHttp 对于header的name和value有做非法数据校验

  • 我们参考了OkHttp的实现,实现了一个简单的过滤非法字符的方法,即filterValidHeaders(HeaderExt.kt)

  • 上述方法filterValidHeaders在运行时如果发现有非法内容,会抛出异常,便于尽早发现问题。

  • 尽量将filterValidHeaders调用处理在合适的时机。

注意

  • header信息中包含敏感内容,一定要慎重添加。

  • pic*.secooimg.com 由于会指向cdn,严禁增加敏感的header信息