Nasz zespół zdecydował się na Retrofit 2.0 i przeprowadzam wstępne badania. Jestem nowicjuszem w tej bibliotece.
Zastanawiam się, jak interceptor
dodać niestandardowe nagłówki poprzez Retrofits 2.0 w naszej aplikacji na Androida. Istnieje wiele samouczków na temat interceptor
dodawania nagłówków w Retrofit 1.X, ale ponieważ interfejsy API bardzo się zmieniły w najnowszej wersji, nie jestem pewien, jak dostosować te metody w nowej wersji. Ponadto Retrofit nie zaktualizował jeszcze swojej nowej dokumentacji.
Na przykład w poniższych kodach, jak zaimplementować Interceptor
klasę, aby dodać dodatkowe nagłówki? Poza tym, czym właściwie jest ten nieudokumentowany Chain
obiekt ? Kiedy zostanie intercept()
wezwany?
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
// How to add extra headers?
return response;
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_API_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
/
a adresy URL Twojego interfejsu API nie (stuff/post/whatever
)Odpowiedzi:
Sprawdź to.
public class HeaderInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request() .newBuilder() .addHeader("appid", "hello") .addHeader("deviceplatform", "android") .removeHeader("User-Agent") .addHeader("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0") .build(); Response response = chain.proceed(request); return response; } }
Kotlin
class HeaderInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response = chain.run { proceed( request() .newBuilder() .addHeader("appid", "hello") .addHeader("deviceplatform", "android") .removeHeader("User-Agent") .addHeader("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0") .build() ) } }
źródło
intercept()
jest to wyzwalane za każdym razem, gdy żądanie jest wysyłane z aplikacji? Czy możemy przechwycić odpowiedź pośrednią na potrzeby przekierowania, czy po prostu uzyskać odpowiedź końcową?client.interceptors()
. To wygląda jaknew OkHttpClient.Builder().addInterceptor(<Your Interceptor>).build()
Inna alternatywa dla zaakceptowanej odpowiedzi
public class HeaderInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); request = request.newBuilder() .addHeader("headerKey0", "HeaderVal0") .addHeader("headerKey0", "HeaderVal0--NotReplaced/NorUpdated") //new header added .build(); //alternative Headers moreHeaders = request.headers().newBuilder() .add("headerKey1", "HeaderVal1") .add("headerKey2", "HeaderVal2") .set("headerKey2", "HeaderVal2--UpdatedHere") // existing header UPDATED if available, else added. .add("headerKey3", "HeaderKey3") .add("headerLine4 : headerLine4Val") //line with `:`, spaces doesn't matter. .removeAll("headerKey3") //Oops, remove this. .build(); request = request.newBuilder().headers(moreHeaders).build(); /* ##### List of headers ##### */ // headerKey0: HeaderVal0 // headerKey0: HeaderVal0--NotReplaced/NorUpdated // headerKey1: HeaderVal1 // headerKey2: HeaderVal2--UpdatedHere // headerLine4: headerLine4Val Response response = chain.proceed(request); return response; } }
źródło
request.newBuilder().headers(moreHeaders).build()
zachowasz oryginalne nagłówki?public class ServiceFactory { public static ApiClient createService(String authToken, String userName, String password) { OkHttpClient defaultHttpClient = new OkHttpClient.Builder() .addInterceptor( chain -> { Request request = chain.request().newBuilder() .headers(getJsonHeader(authToken)) .build(); return chain.proceed(request); }) .authenticator(getBasicAuthenticator(userName, password)) .build(); return getService(defaultHttpClient); } private static Headers getJsonHeader(String authToken) { Headers.Builder builder = new Headers.Builder(); builder.add("Content-Type", "application/json"); builder.add("Accept", "application/json"); if (authToken != null && !authToken.isEmpty()) { builder.add("X-MY-Auth", authToken); } return builder.build(); } private static Authenticator getBasicAuthenticator(final String userName, final String password) { return (route, response) -> { String credential = Credentials.basic(userName, password); return response.request().newBuilder().header("Authorization", credential).build(); }; } private static ApiClient getService(OkHttpClient defaultHttpClient) { return new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(defaultHttpClient) .build() .create(ApiClient.class); } }
źródło
Możesz używać nagłówków za pomocą Interceptorów z jego wbudowanymi metodami, takimi jak ta
interceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); Request.Builder builder = original.newBuilder(); builder.header("Authorization","Bearer "+ LeafPreference.getInstance(context).getString(LeafPreference.TOKEN)); Request request = builder.method(original.method(), original.body()) .build(); Log.e("request",request.urlString()); Log.e("header",request.header("Authorization")); return chain.proceed(request); } }); }
źródło
final Context context
na liście parametrów.context
tutaj mieć , ponieważ jest to logika biznesowa.