Skip to content

Implemented cookie jar and its use in http redirection #1495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.asynchttpclient.channel.ChannelPool;
import org.asynchttpclient.channel.KeepAliveStrategy;
import org.asynchttpclient.cookie.CookieStore;
import org.asynchttpclient.filter.IOExceptionFilter;
import org.asynchttpclient.filter.RequestFilter;
import org.asynchttpclient.filter.ResponseFilter;
Expand Down Expand Up @@ -182,6 +183,13 @@ public interface AsyncHttpClientConfig {
*/
List<IOExceptionFilter> getIoExceptionFilters();

/**
* Return cookie store that is used to store and retrieve cookies
*
* @return {@link CookieStore} object
*/
CookieStore getCookieStore();

/**
* Return the number of time the library will retry when an {@link java.io.IOException} is throw by the remote server
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@

import static org.asynchttpclient.util.Assertions.assertNotNull;

import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;

import io.netty.handler.codec.http.cookie.Cookie;
import org.asynchttpclient.channel.ChannelPool;
import org.asynchttpclient.filter.FilterContext;
import org.asynchttpclient.filter.FilterException;
Expand Down Expand Up @@ -180,6 +182,22 @@ public BoundRequestBuilder prepareRequest(RequestBuilder requestBuilder) {

@Override
public <T> ListenableFuture<T> executeRequest(Request request, AsyncHandler<T> handler) {
if (config.getCookieStore() != null) {
try {
List<Cookie> cookies = config.getCookieStore().get(request.getUri());
if (!cookies.isEmpty()) {
RequestBuilder requestBuilder = new RequestBuilder(request);
for (Cookie cookie : cookies)
requestBuilder.addOrReplaceCookie(cookie);

request = requestBuilder.build();
}
} catch (Exception e) {
handler.onThrowable(e);
return new ListenableFuture.CompletedFailure<>("Failed to set cookies of request", e);
}
}

if (noRequestFilters) {
return execute(request, handler);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.asynchttpclient.channel.ChannelPool;
import org.asynchttpclient.channel.DefaultKeepAliveStrategy;
import org.asynchttpclient.channel.KeepAliveStrategy;
import org.asynchttpclient.cookie.CookieStore;
import org.asynchttpclient.cookie.ThreadSafeCookieStore;
import org.asynchttpclient.filter.IOExceptionFilter;
import org.asynchttpclient.filter.RequestFilter;
import org.asynchttpclient.filter.ResponseFilter;
Expand Down Expand Up @@ -110,6 +112,9 @@ public class DefaultAsyncHttpClientConfig implements AsyncHttpClientConfig {
private final List<ResponseFilter> responseFilters;
private final List<IOExceptionFilter> ioExceptionFilters;

// cookie store
private final CookieStore cookieStore;

// internals
private final String threadPoolName;
private final int httpClientCodecMaxInitialLineLength;
Expand Down Expand Up @@ -186,6 +191,9 @@ private DefaultAsyncHttpClientConfig(//
List<ResponseFilter> responseFilters,//
List<IOExceptionFilter> ioExceptionFilters,//

// cookie store
CookieStore cookieStore,

// tuning
boolean tcpNoDelay,//
boolean soReuseAddress,//
Expand Down Expand Up @@ -263,6 +271,9 @@ private DefaultAsyncHttpClientConfig(//
this.responseFilters = responseFilters;
this.ioExceptionFilters = ioExceptionFilters;

// cookie store
this.cookieStore = cookieStore;

// tuning
this.tcpNoDelay = tcpNoDelay;
this.soReuseAddress = soReuseAddress;
Expand Down Expand Up @@ -502,6 +513,12 @@ public List<IOExceptionFilter> getIoExceptionFilters() {
return ioExceptionFilters;
}

// cookie store
@Override
public CookieStore getCookieStore() {
return cookieStore;
}

// tuning
@Override
public boolean isTcpNoDelay() {
Expand Down Expand Up @@ -676,6 +693,9 @@ public static class Builder {
private final List<ResponseFilter> responseFilters = new LinkedList<>();
private final List<IOExceptionFilter> ioExceptionFilters = new LinkedList<>();

// cookie store
private CookieStore cookieStore = new ThreadSafeCookieStore();

// tuning
private boolean tcpNoDelay = defaultTcpNoDelay();
private boolean soReuseAddress = defaultSoReuseAddress();
Expand Down Expand Up @@ -1017,6 +1037,12 @@ public Builder removeIOExceptionFilter(IOExceptionFilter ioExceptionFilter) {
return this;
}

// cookie store
public Builder setCookieStore(CookieStore cookieStore) {
this.cookieStore = cookieStore;
return this;
}

// tuning
public Builder setTcpNoDelay(boolean tcpNoDelay) {
this.tcpNoDelay = tcpNoDelay;
Expand Down Expand Up @@ -1191,6 +1217,7 @@ public DefaultAsyncHttpClientConfig build() {
requestFilters.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(requestFilters), //
responseFilters.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(responseFilters),//
ioExceptionFilters.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(ioExceptionFilters),//
cookieStore,
tcpNoDelay, //
soReuseAddress, //
soLinger, //
Expand Down
85 changes: 85 additions & 0 deletions client/src/main/java/org/asynchttpclient/cookie/CookieStore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2017 AsyncHttpClient Project. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0,
* and you may not use this file except in compliance with the Apache License Version 2.0.
* You may obtain a copy of the Apache License Version 2.0 at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the Apache License Version 2.0 is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/

package org.asynchttpclient.cookie;

import io.netty.handler.codec.http.cookie.Cookie;
import org.asynchttpclient.uri.Uri;

import java.net.CookieManager;
import java.util.List;
import java.util.function.Predicate;

/**
* This interface represents an abstract store for {@link Cookie} objects.
* <p>
* <p>{@link CookieManager} will call {@code CookieStore.add} to save cookies
* for every incoming HTTP response, and call {@code CookieStore.get} to
* retrieve cookie for every outgoing HTTP request. A CookieStore
* is responsible for removing HttpCookie instances which have expired.
*
* @since 2.1
*/
public interface CookieStore {
/**
* Adds one {@link Cookie} to the store. This is called for every incoming HTTP response.
* If the given cookie has already expired it will not be added, but existing values will still be removed.
* <p>
* <p>A cookie to store may or may not be associated with an URI. If it
* is not associated with an URI, the cookie's domain and path attribute
* will indicate where it comes from. If it is associated with an URI and
* its domain and path attribute are not specified, given URI will indicate
* where this cookie comes from.
* <p>
* <p>If a cookie corresponding to the given URI already exists,
* then it is replaced with the new one.
*
* @param uri the {@link Uri uri} this cookie associated with. if {@code null}, this cookie will not be associated with an URI
* @param cookie the {@link Cookie cookie} to be added
*/
void add(Uri uri, Cookie cookie);

/**
* Retrieve cookies associated with given URI, or whose domain matches the given URI. Only cookies that
* have not expired are returned. This is called for every outgoing HTTP request.
*
* @param uri the {@link Uri uri} associated with the cookies to be returned
* @return an immutable list of Cookie, return empty list if no cookies match the given URI
*/
List<Cookie> get(Uri uri);

/**
* Get all not-expired cookies in cookie store.
*
* @return an immutable list of http cookies;
* return empty list if there's no http cookie in store
*/
List<Cookie> getAll();

/**
* Remove a cookie from store.
*
* @param predicate that indicates what cookies to remove
* @return {@code true} if this store contained the specified cookie
* @throws NullPointerException if {@code cookie} is {@code null}
*/
boolean remove(Predicate<Cookie> predicate);

/**
* Remove all cookies in this cookie store.
*
* @return true if any cookies were purged.
*/
boolean clear();
}
Loading