I have a service, that return Single>
#GET("users/me/favourite-items-by-shop")
fun getFavourites(#Header("Authorization") authorization: String?):
Single<List<FavouriteItemResponse>>
And I have a repository where i want to get List
override fun getItems(): Single<List<ItemResponse>> {
return service.getFavourites(token)
.map(FavouriteItemResponse::items)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
But i get i mistake
required:Function<in List<FavouriteItemResponse>!, out (???..???)>!
Found: KProperty1<FavouriteItemResponse, ShopResponse>
How i can fix it?
Try this code to define header it wrong way..
#Headers("Content-Type:application/json")
#POST(NetworkConstants.WS_SEND_MESSAGE)
Call<MessageResponse> sendMessage(#Body UserData data);
and also you need to define token in all api request then add into retrofit object define time..
private Retrofit getClient(final Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (context == null) {
request = request
.newBuilder()
.build();
} else {
request = request
.newBuilder()
.addHeader("Authorization", "Bearer " + AppSetting.getStringSharedPref(context, Constants.USER_KEY_TOKEN, ""))
.build();
}
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
but this code in java
I can fix it that
return service.getFavourites(token)
.map { it[0] }
.map { it.items }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
Related
I have Singleton dagger module for OkHttp client and I am trying to add header using Interceptor
#Provides
#Singleton
OkHttpClient provideOkhttpClient(Cache cache, final LocalData localData) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(logging);
client.addNetworkInterceptor(new Interceptor() {
#Override
public Response intercept(#NonNull Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Hp-Application", "Android");
Request request = requestBuilder.build();
Response originalResponse = chain.proceed(request);
try {
if (originalResponse.code() == 200) {
localData.setLastUpdateTime(System.currentTimeMillis());
}
} catch (Exception e) {
e.printStackTrace();
}
return originalResponse;
}
});
client.connectTimeout(60, TimeUnit.SECONDS);
client.cache(cache);
return client.build();
}
But looking to the logs I can't see expected header. Also I receive error, as specific call don't work without required header.
I also tried to add it with addInterceptor()/addNetworkInterceptor() using different class
public class HeaderInterceptor
implements Interceptor {
#Override
public Response intercept(Chain chain)
throws IOException {
Request request = chain.request();
request = request.newBuilder()
.addHeader("Hp-Application", "Android")
.build();
return chain.proceed(request);
}
}
But this way didn't work for me too.
How can I add this header to each call of application having only one implementation?
The order you add the interceptors matters. Your logging interceptor runs first, and only after that is the header-adding interceptor run.
For best logging experience, make the logging interceptor the last one you add.
Hey #Igor try this snippet this might help
public class RetrofitClient {
private static String BASE_URL = "http://192.168.0.100/rest/main.php/";
private static Retrofit retrofit = null;
public static Retrofit getRetroftInstance() {
if (retrofit == null) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addNetworkInterceptor(new SessionRequestInterceptor());
httpClient.addNetworkInterceptor(new ReceivedCookiesInterceptor());
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
return retrofit;
}}
public class ReceivedCookiesInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
HashSet<String> cookies = new HashSet<>();
for (String header : originalResponse.headers("Set-Cookie")) {
cookies.add(header);
if(header.startsWith("XSRF-TOKEN")) {
String newCookie[]=header.split(";");
System.out.println("newCookie Length: "+newCookie.length);
for(String ss:newCookie) {
if(ss.startsWith("XSRF-TOKEN")) {
System.out.println("Cookies ss: " + ss);
sharedPrefs.setToken(ss);
}
}
}
}
}
return originalResponse;
}
}
public class SessionRequestInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder request = original.newBuilder();
request.header("Cookie",ServiceSharedPrefs.getInstance().getToken()));
request.method(original.method(), original.body());
return chain.proceed(request.build());
}
}
new OkHttpClient.Builder()
.addInterceptor(
new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder().
header(AUTHENTICATION_HEADER, AUTHENTICATION_KEY).
method(original.method(), original.body());
Request request = requestBuilder.build();
//System.out.println(request.toString());
return chain.proceed(request);
}
}).addInterceptor(logging)
.build();
i just learn about how can i implementing Retrofit with Dagger2 to set dynamic change url on this reference
i try to make simple module with HostSelectionInterceptor class to use that on Dagger2, but i can't make that correctly and i get error:
my NetworkModule:
#Module(includes = ContextModule.class)
public class NetworkModule {
#Provides
#AlachiqApplicationScope
public HttpLoggingInterceptor loggingInterceptor() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
#Override
public void log(String message) {
Timber.e(message);
}
});
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
return interceptor;
}
...
#Provides
#AlachiqApplicationScope
public HostSelectionInterceptor hostSelectionInterceptor() {
return new HostSelectionInterceptor();
}
#Provides
#AlachiqApplicationScope
public OkHttpClient okHttpClient(HostSelectionInterceptor hostInterceptor, HttpLoggingInterceptor loggingInterceptor, Cache cache) {
return new OkHttpClient.Builder()
.addInterceptor(hostInterceptor)
.addInterceptor(loggingInterceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.cache(cache)
.build();
}
}
and HostSelectionInterceptor module:
#Module(includes = {NetworkModule.class})
public final class HostSelectionInterceptor implements Interceptor {
private volatile String host;
#Provides
#AlachiqApplicationScope
public String setHost(String host) {
this.host = host;
return this.host;
}
public String getHost() {
return host;
}
#Provides
#AlachiqApplicationScope
#Override
public okhttp3.Response intercept(Chain chain) {
Request request = chain.request();
String host = getHost();
if (host != null) {
HttpUrl newUrl = request.url().newBuilder()
.host(host)
.build();
request = request.newBuilder()
.url(newUrl)
.build();
}
try {
return chain.proceed(request);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
i get this error now:
java.lang.IllegalArgumentException: unexpected host: http://myUrl.com/ at okhttp3.HttpUrl$Builder.host(HttpUrl.java:754)
problem is set host by setHost method on this line of code:
HttpUrl newUrl = request.url().newBuilder()
.host(host)
.build();
Based on this github comment, the solution is to replace
HttpUrl newUrl = request.url().newBuilder()
.host(host)
.build();
with
HttpUrl newUrl = HttpUrl.parse(host);
You should use interceptor like this:
class HostSelectionInterceptor: Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
apiHost?.let { host ->
val request = chain.request()
val newUrl = request.url.newBuilder().host(host).build()
val newRequest = request.newBuilder().url(newUrl).build()
return chain.proceed(newRequest)
}
throw IOException("Unknown Server")
}
}
You just need to change at runtime the apiHost variable (var apiHost = "example.com"). Then add this interceptor to OkHttpClient builder:
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(HostSelectionInterceptor())
.build()
i using retrofit2 and want add some header using OkHttp3 addInterceptor
but not working
this is my code
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.removeHeader("Authorization")
.removeHeader("Content-type")
.removeHeader("User-Agent")
.addHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8")
.addHeader("Accept-Language", "en-US")
.addHeader("User-Agent", ApiConfig.userAgent)
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
if (apiInterface == null) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiConfig.baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(client)
.build();
apiInterface = retrofit.create(ApiInterface.class);
}
return apiInterface;
please help me.
kind regards
Try this if it helps
RestAdapter.Builder builder = new RestAdapter.Builder()
.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json;versions=1");
if (isUserLoggedIn()) {
request.addHeader("Authorization", getToken());
}
}
});
In all requests in the application, if an error occurs 401, need to perform a certain action.
I do not want to handle this action in every request manually.
Is it possible to solve this moment at the OkHttp level so that it immediately applies to all requests at once?
Retrofit and OkHttp class:
public class RestApi {
public final User user;
private PreferenceHelper preferenceHelper;
public static final String TAG = "RestApi: ";
#Inject
public RestApi(PreferenceHelper preferenceHelper) {
this.preferenceHelper = preferenceHelper;
TokenAppendingHeaderInterceptor tokenInterceptor = new TokenAppendingHeaderInterceptor();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addInterceptor(tokenInterceptor)
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder().baseUrl(Const.Url.API)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
user = retrofit.create(User.class);
}
public class TokenAppendingHeaderInterceptor implements Interceptor {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String token = preferenceHelper.getToken();
Request newRequest = request.newBuilder()
.addHeader(Const.Url.COOKIE, token)
.build();
return chain.proceed(newRequest);
}
}
public String getCookiesFromResponse(Response response) {
String cookies = "";
List<String> listCookies;
try {
listCookies = response.headers().toMultimap().get("Set-COOKIE");
cookies = CookieHelper.getStringCookies(listCookies);
} catch (NullPointerException e) {
Log.d(TAG, "getCookiesFromResponse: BITRIX can't send cookies");
} finally {
return cookies;
}
}
}
Add Headers for Authentication in request
In your code TokenAppendingHeaderInterceptor class in method Intercept add the hweaders like this
r
equest.addheader('Content-Type': 'application/json;charset=UTF-8');
request.addheaders('Authorizcation', 'Basic '+btoa(username + ':' + password));
I think it will help you
I'd like to intercept all responses received by the retrofit engine, and scan for HTTP error code, for example error 403.
I'm aware I can use the failure(RetrofitError error) callback of every request and check for 403's but I'd like to wrap the response globally.
I can see that request interception is possible, but I do not see a similar option for response.
Any suggestions?
I was able to accomplish that by adding an interceptor to the OkHttpClient that retrofit is using.
Kotlin + Retrofit 2.x
val clientBuilder = OkHttpClient.Builder()
clientBuilder.addInterceptor { chain ->
val request = chain.request()
val response = chain.proceed(request)
if (response.code() == 403) {
handleForbiddenResponse()
}
response
}
Retrofit 2.x:
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
clientBuilder.
addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
if (response.code() == 403) {
handleForbiddenResponse();
}
return response;
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(clientBuilder.build();)
.build();
Retrofit 1.x:
public class ForbiddenInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
if (response.code() == 403) {
handleForbiddenResponse();
}
return response;
}
}
OkHttpClient okHttpClient = Utils.createUnsafeOkHttpClient();
okHttpClient.interceptors().add(new ForbiddenInterceptor());
RestAdapter.Builder restAdapterBuilder = new RestAdapter.Builder()
.setEndpoint(API_BASE_URL)
.setClient(new OkClient(okHttpClient));
Another possibility is to override the execute method in Retrofit's OkClient. In my case I was looking for a specific response header, so it went something like this:
OkClient client = new OkClient(okHttpClient) {
#Override
public retrofit.client.Response execute(retrofit.client.Request request) throws IOException {
retrofit.client.Response response = super.execute(request);
// Do whatever with 'response', such as looking for the value of a particular header:
List<retrofit.client.Header> headers = response.getHeaders();
for (retrofit.client.Header header : headers) {
if (MY_HEADER.equalsIgnoreCase(header.getName())) {
this.savedValue = header.getValue();
break;
}
}
return response;
}
};
RestAdapter.Builder restAdapterBuilder = new RestAdapter.Builder()
.setEndpoint(API_BASE_URL)
.setClient(client);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
okhttp3.Response response = chain.proceed(request);
// todo deal with the issues the way you need to
if (response.code() == 500) {
startActivity(
new Intent(
ErrorHandlingActivity.this,
ServerIsBrokenActivity.class
)
);
return response;
}
return response;
}
})
.build();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://your_url")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
As you can see in the snippet above, the okhttp3.Response response = chain.proceed(request); line accesses the server response. Consequently, we can check the status code with if (response.code() == 500) and then open the ServerIsBrokenActivity.