【问题标题】:How to add X-API-Key and X-Session to header using Retrofit library?如何使用 Retrofit 库将 X-API-Key 和 X-Session 添加到标头?
【发布时间】:2019-07-19 06:20:03
【问题描述】:

我想为我的multipart request 使用Retrofit 库而不是HttpURLConnection 将图像发送到服务器。我的HttpURLConnection 请求由于某种原因无法正常工作。

但我在Retrofit 中有问题,我不知道如何将Session tokenAPI key 添加到我的请求中。

这是我对HttpURLConnection 的每个请求使用的解决方案(它适用于除多部分请求之外的所有请求):

val con = url.openConnection() as HttpURLConnection
con.apply {
    requestMethod = method
    useCaches = false
    doOutput = true
    doInput = true
    addRequestProperty(HEADER_CONNECTION, "Keep-Alive")
    addRequestProperty(HEADER_CACHE_CONTROL, "no-cache")
    addRequestProperty(HEADER_CONTENT_TYPE, "multipart/form-data")
    addRequestProperty("X-API-Key", apiType.apiKey)
    addRequestProperty("X-Session", getServerSession())
}

这是我使用改造库的要求:

val f = File(app.cacheDir, filename)
f.createNewFile()

val fos = FileOutputStream(f)
fos.write(data)
fos.flush()
fos.close()

val reqFile = RequestBody.create(MediaType.parse("image/*"), f)
val body = MultipartBody.Part.createFormData("upload", f.name, reqFile)

val httpUrl = HttpUrl.Builder()
    .scheme("https")
    .host(mainUrl)
    .addPathSegment(apiSegment)
    .addQueryParameter("X-API-Key", apiType.apiKey)
    .addQueryParameter("X-Session", getServerSession())

val service = Retrofit.Builder().baseUrl(httpUrl.build()).build().create(Service::class.java)
val req = service.postImage(body)
val response = req.execute()

我使用了addQueryParameter,因为我读到这是将这两个参数添加到标头的方法,但这只会影响我的 API 调用 URL,它会将 API 密钥和会话添加到 URL,这根本不被服务器识别。

更新:

我的邮政服务界面:

internal interface MultipartService {
        @Multipart
        @POST("{url}")
        fun postImage(@Part image: MultipartBody.Part): Call<ResponseBody>
        fun setEndpoint(@Path("url") endpoint: String): Call<ResponseBody>
    }

更新:已修复

   internal interface MultipartServicePost {
        @POST("{url}")
        @Multipart
        fun postImage(@Part image: MultipartBody.Part, @Path(value = "url", encoded = true) endpoint: String): Call<ResponseBody>
    }

【问题讨论】:

    标签: android kotlin retrofit retrofit2 httpurlconnection


    【解决方案1】:

    addQueryParameter() 顾名思义,用于在查询中添加参数。

    你想要的是Interceptor。这是一个例子:

    OkHttpClient.Builder httpClient = new OkHttpClient.Builder();  
    httpClient.addInterceptor(new Interceptor() {  
        @Override
        public Response intercept(Interceptor.Chain chain) throws IOException {
            Request original = chain.request();
    
            Request request = original.newBuilder()
                .header("X-API-Key", apiType.apiKey)
                .header("X-Session", getServerSession())
                .method(original.method(), original.body())
                .build();
    
            return chain.proceed(request);
        }
    }
    

    关于动态 url,您可以在定义界面时定义动态路径段。示例:

    public interface PostService {  
    
        @GET("/posts/{post_id}")
        Task getPost(@Path("post_id") long id);
    }
    

    【讨论】:

    • 这是有效的。我有一个关于 URL 传递的问题。有什么方法可以更改我的 API 调用的帖子 URL?因为如果我使用 HttpUrl 和 .addPathSegment() 它会在段之间添加奇怪的 %2F 字符串。 URL 由 "https://" + baseURL + /apiVersion/ + /apiFunction/ + /name/ 组成,这三个是动态的,可以更改。所以我不能将它们添加到服务接口内的@Post。
    • 好的,很酷(不要忘记投票并验证答案......)。关于您的评论,您的意思是您想要动态网址吗?当你定义你的界面时,这是可能的
    • 是的。几乎一切都是动态的。我可以更改整个 API url(我对这个多部分请求使用多个 API 服务器)所以最好的方法是我可以将一堆 url 部分附加到一个字符串中,我想将它用作 URL。类似于 HttpUrlConnection。我可以创建由多个 url 部分粘合在一起的 URL 对象。示例:val url = URL(apiType.url + apiBasePath + apiPath + apiName + apiSubName)
    • 我已经尝试过了,因为它应该在 Kotlin 中完成(没有任务)但它导致错误:HTTP method annotation is required (e.g., @GET, @POST, etc.) 并且界面中有@POST("{url}")(请参阅编辑的问题)
    • @GET()、@POST() 等是 retrofit2 的一部分。但是你不能做你发布的事情:@POST("{url}") 必须写在你的 setEndpoint() 方法上方
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 2018-04-06
    • 2020-08-12
    相关资源
    最近更新 更多