Skip to content

Commit

Permalink
Fixes #9288 - Jetty 12 - Use oej.http.HttpCookie in jetty-client. (#9289
Browse files Browse the repository at this point in the history
)

* Replaced usages of java.net.HttpCookie with oej.http.HttpCookie.
* Moved server-side only methods from HttpCookie to HttpCookieUtils.
* Introduced and implemented oej.http.HttpCookieStore.
* Removed now obsolete oej.util.HttpCookieStore.
* Introduced HttpScheme.isSecure(String), to avoid code duplication.
* Fixed handling of cookie "localhost" domain in HttpClient.

Signed-off-by: Simone Bordet <[email protected]>
  • Loading branch information
sbordet authored Feb 7, 2023
1 parent f565122 commit d02932f
Show file tree
Hide file tree
Showing 40 changed files with 2,133 additions and 879 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.Path;
Expand Down Expand Up @@ -54,6 +52,8 @@
import org.eclipse.jetty.client.transport.HttpClientTransportDynamic;
import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP;
import org.eclipse.jetty.fcgi.client.transport.HttpClientTransportOverFCGI;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpCookieStore;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
Expand All @@ -67,7 +67,6 @@
import org.eclipse.jetty.io.ClientConnector;
import org.eclipse.jetty.io.Content;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.HttpCookieStore;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;

Expand Down Expand Up @@ -541,8 +540,8 @@ public void getCookies() throws Exception
httpClient.start();

// tag::getCookies[]
CookieStore cookieStore = httpClient.getCookieStore();
List<HttpCookie> cookies = cookieStore.get(URI.create("http://domain.com/path"));
HttpCookieStore cookieStore = httpClient.getHttpCookieStore();
List<HttpCookie> cookies = cookieStore.match(URI.create("http://domain.com/path"));
// end::getCookies[]
}

Expand All @@ -552,11 +551,12 @@ public void setCookie() throws Exception
httpClient.start();

// tag::setCookie[]
CookieStore cookieStore = httpClient.getCookieStore();
HttpCookie cookie = new HttpCookie("foo", "bar");
cookie.setDomain("domain.com");
cookie.setPath("/");
cookie.setMaxAge(TimeUnit.DAYS.toSeconds(1));
HttpCookieStore cookieStore = httpClient.getHttpCookieStore();
HttpCookie cookie = HttpCookie.build("foo", "bar")
.domain("domain.com")
.path("/")
.maxAge(TimeUnit.DAYS.toSeconds(1))
.build();
cookieStore.add(URI.create("http://domain.com"), cookie);
// end::setCookie[]
}
Expand All @@ -568,7 +568,7 @@ public void requestCookie() throws Exception

// tag::requestCookie[]
ContentResponse response = httpClient.newRequest("http://domain.com/path")
.cookie(new HttpCookie("foo", "bar"))
.cookie(HttpCookie.from("foo", "bar"))
.send();
// end::requestCookie[]
}
Expand All @@ -579,9 +579,9 @@ public void removeCookie() throws Exception
httpClient.start();

// tag::removeCookie[]
CookieStore cookieStore = httpClient.getCookieStore();
HttpCookieStore cookieStore = httpClient.getHttpCookieStore();
URI uri = URI.create("http://domain.com");
List<HttpCookie> cookies = cookieStore.get(uri);
List<HttpCookie> cookies = cookieStore.match(uri);
for (HttpCookie cookie : cookies)
{
cookieStore.remove(uri, cookie);
Expand All @@ -595,7 +595,7 @@ public void emptyCookieStore() throws Exception
httpClient.start();

// tag::emptyCookieStore[]
httpClient.setCookieStore(new HttpCookieStore.Empty());
httpClient.setHttpCookieStore(new HttpCookieStore.Empty());
// end::emptyCookieStore[]
}

Expand All @@ -605,17 +605,18 @@ public void filteringCookieStore() throws Exception
httpClient.start();

// tag::filteringCookieStore[]
class GoogleOnlyCookieStore extends HttpCookieStore
class GoogleOnlyCookieStore extends HttpCookieStore.Default
{
@Override
public void add(URI uri, HttpCookie cookie)
public boolean add(URI uri, HttpCookie cookie)
{
if (uri.getHost().endsWith("google.com"))
super.add(uri, cookie);
return super.add(uri, cookie);
return false;
}
}

httpClient.setCookieStore(new GoogleOnlyCookieStore());
httpClient.setHttpCookieStore(new GoogleOnlyCookieStore());
// end::filteringCookieStore[]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import org.eclipse.jetty.client.transport.HttpDestination;
import org.eclipse.jetty.client.transport.HttpRequest;
import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpCookieStore;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
Expand Down Expand Up @@ -81,7 +83,7 @@
* and HTTP parameters (such as whether to follow redirects).</p>
* <p>HttpClient transparently pools connections to servers, but allows direct control of connections
* for cases where this is needed.</p>
* <p>HttpClient also acts as a central configuration point for cookies, via {@link #getCookieStore()}.</p>
* <p>HttpClient also acts as a central configuration point for cookies, via {@link #getHttpCookieStore()}.</p>
* <p>Typical usage:</p>
* <pre>
* HttpClient httpClient = new HttpClient();
Expand Down Expand Up @@ -121,8 +123,8 @@ public class HttpClient extends ContainerLifeCycle
private final HttpClientTransport transport;
private final ClientConnector connector;
private AuthenticationStore authenticationStore = new HttpAuthenticationStore();
private CookieManager cookieManager;
private CookieStore cookieStore;
private HttpCookieStore cookieStore;
private HttpCookieParser cookieParser;
private SocketAddressResolver resolver;
private HttpField agentField = new HttpField(HttpHeader.USER_AGENT, USER_AGENT);
private boolean followRedirects = true;
Expand Down Expand Up @@ -222,8 +224,9 @@ protected void doStart() throws Exception

decoderFactories.put(new GZIPContentDecoder.Factory(byteBufferPool));

cookieManager = newCookieManager();
cookieStore = cookieManager.getCookieStore();
if (cookieStore == null)
cookieStore = new HttpCookieStore.Default();
cookieParser = new HttpCookieParser();

transport.setHttpClient(this);

Expand All @@ -236,11 +239,6 @@ protected void doStart() throws Exception
}
}

private CookieManager newCookieManager()
{
return new CookieManager(getCookieStore(), CookiePolicy.ACCEPT_ALL);
}

@Override
protected void doStop() throws Exception
{
Expand Down Expand Up @@ -274,33 +272,28 @@ public List<Request.Listener> getRequestListeners()
/**
* @return the cookie store associated with this instance
*/
public CookieStore getCookieStore()
public HttpCookieStore getHttpCookieStore()
{
return cookieStore;
}

/**
* @param cookieStore the cookie store associated with this instance
*/
public void setCookieStore(CookieStore cookieStore)
public void setHttpCookieStore(HttpCookieStore cookieStore)
{
if (isStarted())
throw new IllegalStateException();
this.cookieStore = Objects.requireNonNull(cookieStore);
this.cookieManager = newCookieManager();
}

public void putCookie(URI uri, HttpField field)
{
try
{
String value = field.getValue();
if (value != null)
{
Map<String, List<String>> header = new HashMap<>(1);
header.put(field.getHeader().asString(), List.of(value));
cookieManager.put(uri, header);
}
HttpCookie cookie = cookieParser.parse(uri, field);
if (cookie != null)
cookieStore.add(uri, cookie);
}
catch (IOException x)
{
Expand Down Expand Up @@ -1138,20 +1131,77 @@ public static int normalizePort(String scheme, int port)
return HttpScheme.getDefaultPort(scheme);
}

public boolean isDefaultPort(String scheme, int port)
{
return HttpScheme.getDefaultPort(scheme) == port;
}

public static boolean isSchemeSecure(String scheme)
{
return HttpScheme.HTTPS.is(scheme) || HttpScheme.WSS.is(scheme);
}

public ClientConnectionFactory newSslClientConnectionFactory(SslContextFactory.Client sslContextFactory, ClientConnectionFactory connectionFactory)
{
if (sslContextFactory == null)
sslContextFactory = getSslContextFactory();
return new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), connectionFactory);
}

private static class HttpCookieParser extends CookieManager
{
public HttpCookieParser()
{
super(new Store(), CookiePolicy.ACCEPT_ALL);
}

public HttpCookie parse(URI uri, HttpField field) throws IOException
{
// TODO: hacky implementation waiting for a real HttpCookie parser.
String value = field.getValue();
if (value == null)
return null;
Map<String, List<String>> header = new HashMap<>(1);
header.put(field.getHeader().asString(), List.of(value));
put(uri, header);
Store store = (Store)getCookieStore();
HttpCookie cookie = store.cookie;
store.cookie = null;
return cookie;
}

private static class Store implements CookieStore
{
private HttpCookie cookie;

@Override
public void add(URI uri, java.net.HttpCookie cookie)
{
String domain = cookie.getDomain();
if ("localhost.local".equals(domain))
cookie.setDomain("localhost");
this.cookie = HttpCookie.from(cookie);
}

@Override
public List<java.net.HttpCookie> get(URI uri)
{
throw new UnsupportedOperationException();
}

@Override
public List<java.net.HttpCookie> getCookies()
{
throw new UnsupportedOperationException();
}

@Override
public List<URI> getURIs()
{
throw new UnsupportedOperationException();
}

@Override
public boolean remove(URI uri, java.net.HttpCookie cookie)
{
throw new UnsupportedOperationException();
}

@Override
public boolean removeAll()
{
throw new UnsupportedOperationException();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
package org.eclipse.jetty.client;

import java.io.IOException;
import java.net.HttpCookie;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
Expand All @@ -30,6 +29,7 @@
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory;
import org.eclipse.jetty.client.AbstractConnectorHttpClientTransport;
import org.eclipse.jetty.client.Destination;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpClientTransport;
import org.eclipse.jetty.client.MultiplexConnectionPool;
import org.eclipse.jetty.client.Origin;
import org.eclipse.jetty.client.Request;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.ClientConnector;
Expand Down Expand Up @@ -130,7 +130,8 @@ private static ClientConnector findClientConnector(ClientConnectionFactory.Info[
@Override
public Origin newOrigin(Request request)
{
boolean secure = HttpClient.isSchemeSecure(request.getScheme());
String scheme = request.getScheme();
boolean secure = HttpScheme.isSecure(scheme);
String http1 = "http/1.1";
String http2 = secure ? "h2" : "h2c";
List<String> protocols = List.of();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

package org.eclipse.jetty.client.transport;

import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
Expand All @@ -30,13 +28,15 @@
import org.eclipse.jetty.client.ProxyConfiguration;
import org.eclipse.jetty.client.Request;
import org.eclipse.jetty.client.Response;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpCookieStore;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.CyclicTimeouts;
import org.eclipse.jetty.util.Attachable;
import org.eclipse.jetty.util.HttpCookieStore;
import org.eclipse.jetty.util.NanoTime;
import org.eclipse.jetty.util.thread.AutoLock;
import org.eclipse.jetty.util.thread.Scheduler;
Expand Down Expand Up @@ -156,13 +156,17 @@ protected void normalizeRequest(HttpRequest request)
}

ProxyConfiguration.Proxy proxy = destination.getProxy();
if (proxy instanceof HttpProxy && !HttpClient.isSchemeSecure(request.getScheme()))
if (proxy instanceof HttpProxy)
{
URI uri = request.getURI();
if (uri != null)
String scheme = request.getScheme();
if (!HttpScheme.isSecure(scheme))
{
path = uri.toString();
request.path(path);
URI uri = request.getURI();
if (uri != null)
{
path = uri.toString();
request.path(path);
}
}
}

Expand Down Expand Up @@ -210,12 +214,12 @@ protected void normalizeRequest(HttpRequest request)

// Cookies
StringBuilder cookies = convertCookies(request.getCookies(), null);
CookieStore cookieStore = getHttpClient().getCookieStore();
HttpCookieStore cookieStore = getHttpClient().getHttpCookieStore();
if (cookieStore != null && cookieStore.getClass() != HttpCookieStore.Empty.class)
{
URI uri = request.getURI();
if (uri != null)
cookies = convertCookies(HttpCookieStore.matchPath(uri, cookieStore.get(uri)), cookies);
cookies = convertCookies(cookieStore.match(uri), cookies);
}
if (cookies != null)
{
Expand Down
Loading

0 comments on commit d02932f

Please sign in to comment.