La documentation de Retrofit 2 dit:
Les en-têtes devant être ajoutés à chaque demande peuvent être spécifiés à l'aide d'un intercepteur OkHttp.
Cela peut être fait facilement en utilisant la version précédente, voici le QA associé.
Mais avec retrofit 2, je ne pouvais pas trouver quelque chose comme la méthode setRequestInterceptor
ou setInterceptor
qui puisse être appliquée à l’objet Retrofit.Builder
.
De plus, il semble qu'il n'y ait pas de RequestInterceptor
dans OkHttp more. Le document de Retrofit nous renvoie à Interceptor que je ne comprenais pas trop comment l'utiliser à cette fin.
Comment puis-je faire ceci?
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("parameter", "value").build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create()).baseUrl(url).client(httpClient.build()).build();
version lambda:
builder.addInterceptor(chain -> {
Request request = chain.request().newBuilder().addHeader("key", "value").build();
return chain.proceed(request);
});
Version longue laide:
builder.addInterceptor(new Interceptor() {
@Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("key", "value").build();
return chain.proceed(request);
}
});
version complète:
class Factory {
public static APIService create(Context context) {
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
builder.readTimeout(10, TimeUnit.SECONDS);
builder.connectTimeout(5, TimeUnit.SECONDS);
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
builder.addInterceptor(interceptor);
}
builder.addInterceptor(chain -> {
Request request = chain.request().newBuilder().addHeader("key", "value").build();
return chain.proceed(request);
});
builder.addInterceptor(new UnauthorisedInterceptor(context));
OkHttpClient client = builder.build();
Retrofit retrofit =
new Retrofit.Builder().baseUrl(APIService.ENDPOINT).client(client).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
return retrofit.create(APIService.class);
}
}
fichier gradle (vous devez ajouter l'intercepteur de journalisation si vous prévoyez de l'utiliser):
//----- Retrofit
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile "com.squareup.retrofit2:converter-gson:2.1.0"
compile "com.squareup.retrofit2:adapter-rxjava:2.1.0"
compile 'com.squareup.okhttp3:logging-interceptor:3.4.0'
Pour consigner votre demande et votre réponse, vous avez besoin d'un intercepteur et pour définir l'en-tête, vous avez besoin d'un intercepteur. Voici la solution pour ajouter l'intercepteur simultanément en utilisant retrofit 2.1
public OkHttpClient getHeader(final String authorizationValue ) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addNetworkInterceptor(
new Interceptor() {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = null;
if (authorizationValue != null) {
Log.d("--Authorization-- ", authorizationValue);
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Authorization", authorizationValue);
request = requestBuilder.build();
}
return chain.proceed(request);
}
})
.build();
return okClient;
}
Maintenant, dans votre objet de modernisation, ajoutez cet en-tête dans le client
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.client(getHeader(authorizationValue))
.addConverterFactory(GsonConverterFactory.create())
.build();
J'ai trouvé un autre moyen de Retrofit 1.9 et 2.0, pour Json Content Type.
@Headers({"Accept: application/json"})
@POST("user/classes")
Call<playlist> addToPlaylist(@Body PlaylistParm parm);
Vous pouvez ajouter de nombreux autres en-têtes, i.e
@Headers({
"Accept: application/json",
"User-Agent: Your-App-Name",
"Cache-Control: max-age=640000"
})
Dans mon cas, addInterceptor()
ne fonctionnait pas pour ajouter des en-têtes HTTP à ma demande, je devais utiliser addNetworkInterceptor()
. Le code est le suivant:
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addNetworkInterceptor(new AddHeaderInterceptor());
Et le code d'intercepteur:
public class AddHeaderInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Authorization", "MyauthHeaderContent");
return chain.proceed(builder.build());
}
}
Ceci et d’autres exemples sur this Gist
Si vous utilisez la méthode addInterceptor pour ajouter HttpLoggingInterceptor, il n'enregistrera pas les éléments ajoutés par d'autres intercepteurs appliqués ultérieurement à HttpLoggingInterceptor.
Par exemple: Si vous avez deux intercepteurs "HttpLoggingInterceptor" et "AuthInterceptor" et que HttpLoggingInterceptor est appliqué en premier, vous ne pouvez pas afficher les paramètres http ou en-têtes définis par AuthInterceptor.
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addNetworkInterceptor(logging)
.addInterceptor(new AuthInterceptor());
Je l'ai résolu, en utilisant la méthode addNetworkInterceptor.
Utiliser ce client de modernisation
class RetrofitClient2(context: Context) : OkHttpClient() {
private var mContext:Context = context
private var retrofit: Retrofit? = null
val client: Retrofit?
get() {
val logging = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
val client = OkHttpClient.Builder()
.connectTimeout(Constants.TIME_OUT, TimeUnit.SECONDS)
.readTimeout(Constants.TIME_OUT, TimeUnit.SECONDS)
.writeTimeout(Constants.TIME_OUT, TimeUnit.SECONDS)
client.addInterceptor(logging)
client.interceptors().add(AddCookiesInterceptor(mContext))
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create()
if (retrofit == null) {
retrofit = Retrofit.Builder()
.baseUrl(Constants.URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client.build())
.build()
}
return retrofit
}
}
Je passe le JWT avec chaque demande. S'il vous plaît ne faites pas attention aux noms de variables, c'est un peu déroutant.
class AddCookiesInterceptor(context: Context) : Interceptor {
val mContext: Context = context
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val builder = chain.request().newBuilder()
val preferences = CookieStore().getCookies(mContext)
if (preferences != null) {
for (cookie in preferences!!) {
builder.addHeader("Authorization", cookie)
}
}
return chain.proceed(builder.build())
}
}