web-dev-qa-db-ja.com

レトロフィットでカスタムCookieを設定する

改造リクエストにカスタムCookieを設定する方法はありますか?

RequestInterceptorまたはその他の手段を使用しますか?

17
David

を通って retrofit.RequestInterceptor

@Override
public void intercept(RequestFacade request) {    
     request.addHeader("Cookie", "cookiename=cookievalue");
}

カスタムRequestInterceptorは次のように設定できます。

String cookieKey = ...
String cookieValue = ...

RestAdapter adapter = new RestAdapter.Builder()
    .setRequestInterceptor(new RequestInterceptor() {
      @Override
      public void intercept(RequestFacade request) {
        // assuming `cookieKey` and `cookieValue` are not null 
        request.addHeader("Cookie", cookieKey + "=" + cookieValue);
      }
    })
    .setServer("http://...")
    .build();

YourService service = adapter.create(YourService.class);

また、サーバーによって設定されたCookieを読み取るには、次のようなカスタムCookieマネージャーをアタッチします。

OkHttpClient client = new OkHttpClient();
CustomCookieManager manager = new CustomCookieManager();
client.setCookieHandler(manager);

RestAdapter adapter = new RestAdapter.Builder()
    .setClient(new OkClient(client))
    ...
    .build();

ここで、CustomCookieManagerは次のようになります。

public class CustomCookieManager extends CookieManager {

  // The cookie key we're interested in.    
  private final String SESSION_KEY = "session-key";

  /**
   * Creates a new instance of this cookie manager accepting all cookies.
   */
  public CustomCookieManager() {
    super.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
  }

  @Override
  public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException {

    super.put(uri, responseHeaders);

    if (responseHeaders == null || responseHeaders.get(Constants.SET_COOKIE_KEY) == null) {
      // No cookies in this response, simply return from this method.
      return;
    }

    // Yes, we've found cookies, inspect them for the key we're looking for.
    for (String possibleSessionCookieValues : responseHeaders.get(Constants.SET_COOKIE_KEY)) {

      if (possibleSessionCookieValues != null) {

        for (String possibleSessionCookie : possibleSessionCookieValues.split(";")) {

          if (possibleSessionCookie.startsWith(SESSION_KEY) && possibleSessionCookie.contains("=")) {

            // We can safely get the index 1 of the array: we know it contains
            // a '=' meaning it has at least 2 values after splitting.
            String session = possibleSessionCookie.split("=")[1];

            // store `session` somewhere

            return;
          }
        }
      }
    }
  }
}
32
David

これがretrofit2のために行われる方法です

Gradle:

compile 'com.squareup.retrofit2:retrofit:2.1.0'

コード:

static final class CookieInterceptor implements Interceptor {
            private volatile String cookie;

            public void setSessionCookie(String cookie) {
                this.cookie = cookie;
            }

            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (this.cookie != null) {
                    request = request.newBuilder()
                            .header("Cookie", this.cookie)
                            .build();
                }
                return chain.proceed(request);
            }
}


class Creator {

    public static MyApi newApi() {
        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
                .create();

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new CookieInterceptor())
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(MyApi.URL)
                .callFactory(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        return retrofit.create(MyApi.class);
    }
}
2
arsent

Cookieを設定する別の方法は次のとおりです。

@Headers("Cookie: cookiename=cookievalue")
@GET("widget/list")
Call<List<Widget>> widgetList();

そして、これが動的な方法です。

@GET("user")
Call<User> getUser(@Header("Cookie") String cookie)
1
Uriel Frankel

RetroFitを使い始めたばかりですが、Cookieを処理する方法は、ライブラリの他の部分と同等ではないようです。私は次のようなことをすることになりました:

// Set up system-wide CookieHandler to capture all cookies sent from server.
final CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);

// Set up interceptor to include cookie value in the header.
RequestInterceptor interceptor = new RequestInterceptor() {
  @Override
  public void intercept(RequestFacade request) {
    for (HttpCookie cookie : cookieManager.getCookieStore().getCookies()) {
      // Set up expiration in format desired by cookies
      // (arbitrarily one hour from now).
      Date expiration = new Date(System.currentTimeMillis() + 60 * 60 * 1000);
      String expires = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz")
          .format(expiration);

      String cookieValue = cookie.getName() + "=" + cookie.getValue() + "; " +
          "path=" + cookie.getPath() + "; " +
          "domain=" + cookie.getDomain() + ";" +
          "expires=" + expires;

      request.addHeader("Cookie", cookieValue);
    }
  }
};

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.github.com")
    .setRequestInterceptor(interceptor) // Set the interceptor
    .build();

GitHubService service = restAdapter.create(GitHubService.class);
0
Tremelune