Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Retrofit / Rxjava y servicios basados ​​en sesiones

Estoy implementando servicios basados ​​en sesiones. Todas las solicitudes tienen que ser suscritas con un parámetro de sesión de cookie, que a su vez se recupera con api de reposo separado. Así que el flujo de trabajo básico sería obtener la cookie de sesión y proceder a consultar los servicios. De vez en cuando la cookie expiraría y daría lugar a otra solicitud de cookie de sesión.

Estoy tratando de hacer cliente código de sesión agnóstico, por lo que no tiene que preocuparse por mantener la sesión, sino que quiero que se oculte dentro de la capa de servicios.

¿Puede sugerir ideas para implementarlo con Retrofit/RxJava ? Creo que el SessionService tiene que ser encapsulado por todos los demás servicios, para que puedan consultarlo cuando sea necesario, pero no estoy seguro de cómo hacerlo con RestAdapter.create de RestAdapter.create

One Solution collect form web for “Retrofit / Rxjava y servicios basados ​​en sesiones”

He hecho algo similar a esto antes pero con la autorización de OAuth. Básicamente, tiene un RestAdapter inicializado con un RequestInterceptor que añade la cookie de sesión a cada solicitud. RequestInterceptor obtiene una nueva cookie de sesión cada vez que se autoriza una sesión.

La siguiente definición de interfaz REST de Retrofit se utiliza en el código de ejemplo siguiente:

 interface ApiService { @GET("/examples/v1/example") Observable<Example> getExample(); } 

El interceptor Request obtiene un vistazo en cada solicitud REST y puede agregar encabezados, parámetros de consulta o puede modificar la URL. En este ejemplo se supone que la cookie se agrega como un encabezado HTTP.

 class CookieHeaderProvider implements RequestInterceptor { private String sessionCookie = ""; public CookieHeaderProvider() { } public void setSesstionCookie(String sessionCookie) { this.sessionCookie = sessionCookie; } @Override public void intercept(RequestFacade requestFacade) { requestFacade.addHeader("Set-Cookie", sessionCookie); } } 

Este es el SessionService al que usted aludió. Su responsabilidad es hacer que la solicitud de red autorice / actualice la cookie de sesión.

 class SessionService { // Modify contructor params to pass in anything needed // to get the session cookie. SessionService(...) { } public Observable<String> observeSessionCookie(...) { // Modify to return an Observable that when subscribed to // will make the network request to get the session cookie. return Observable.just("Fake Session Cookie"); } } 

La clase RestService envuelve la interfaz Retrofit para que la lógica de reintento de solicitud pueda agregarse a cada Retrofit Observable.

 class RestService { private final apiService; private final sessionSerivce; private final cookieHeaderProvider; RestService(ApiService apiService, SessionService sessionSerivce, CookieHeaderProvider cookieHeaderProvider) { this.apiService = apiService; this.sessionSerivce = sessionSerivce; this.cookieHeaderProvider = cookieHeaderProvider; } Observable<Example> observeExamples() { // Return a Retrofit Observable modified with // session retry logic. return apiService .observeExamples() .retryWhen(new RetryWithSessionRefresh(sessionSerivce, cookieHeaderProvider)); } } 

La lógica de reintento siguiente usará SessionService para actualizar la cookie de sesión y luego volver a intentar las peticiones REST fallidas si la cookie de sesión enviada al servidor devuelve un error HTTP no autorizado (401).

 public class RetryWithSessionRefresh implements Func1<Observable<? extends Throwable>, Observable<?>> { private final SessionService sessionSerivce; private final CookieHeaderProvider cookieHeaderProvider; public RetryWithSessionRefresh(SessionService sessionSerivce, CookieHeaderProvider cookieHeaderProvider) { this.sessionSerivce = sessionSerivce; this.cookieHeaderProvider = cookieHeaderProvider; } @Override public Observable<?> call(Observable<? extends Throwable> attempts) { return attempts .flatMap(new Func1<Throwable, Observable<?>>() { public int retryCount = 0; @Override public Observable<?> call(final Throwable throwable) { // Modify retry conditions to suit your needs. The following // will retry 1 time if the error returned was an // HTTP Unauthoried (401) response. retryCount++; if (retryCount <= 1 && throwable instanceof RetrofitError) { final RetrofitError retrofitError = (RetrofitError) throwable; if (!retrofitError.isNetworkError() && retrofitError.getResponse().getStatus() == HttpStatus.SC_UNAUTHORIZED) { return sessionSerivce .observeSessionCookie() .doOnNext(new Action1<String>() { @Override public void call(String sessionCookie) { // Update session cookie so that next // retrofit request will use it. cookieHeaderProvider.setSesstionCookie(sessionCookie); } }) .doOnError(new Action1<Throwable>() { @Override public void call(Throwable throwable) { // Clear session cookie on error. cookieHeaderProvider.setSesstionCookie(""); } }); } } // No more retries. Pass the original // Retrofit error through. return Observable.error(throwable); } }); } } 

El código de inicialización del cliente se verá similar al siguiente:

 CookieHeaderProvider cookieHeaderProvider = new CookieHeaderProvider(); SessionService sessionSerivce = new SessionService(); ApiService apiService = new RestAdapter.Builder() .setEndpoint(...) .setClient(...) .setRequestInterceptor(cookieHeaderProvider) .build() .create(ApiService.class); RestService restService = new RestService(apiService, sessionSerivce, cookieHeaderProvider); 

A continuación, obtener un REST observable desde el RestService y suscribirse a él para iniciar la solicitud de red.

 Observable<Example> exampleObservable = restService .observeExamples(); Subsctiption subscription = exampleObservable .subscribe(new Observer<Example>() { void onNext(Example example) { // Do stuff with example } void onCompleted() { // All done. } void onError(Throwalbe e) { // All API errors will end up here. } }); 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.