Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.eclipse.jetty.client.HttpRequest Maven / Gradle / Ivy
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.client.api.ContentProvider;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.client.util.PathContentProvider;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.util.Fields;
public class HttpRequest implements Request
{
private static final AtomicLong ids = new AtomicLong();
private final HttpFields headers = new HttpFields();
private final Fields params = new Fields(true);
private final Map attributes = new HashMap<>();
private final List requestListeners = new ArrayList<>();
private final List responseListeners = new ArrayList<>();
private final HttpClient client;
private final long conversation;
private final String host;
private final int port;
private URI uri;
private String scheme;
private String path;
private String query;
private String method;
private HttpVersion version;
private long idleTimeout;
private long timeout;
private ContentProvider content;
private boolean followRedirects;
private volatile Throwable aborted;
public HttpRequest(HttpClient client, URI uri)
{
this(client, ids.incrementAndGet(), uri);
}
protected HttpRequest(HttpClient client, long conversation, URI uri)
{
this.client = client;
this.conversation = conversation;
scheme = uri.getScheme();
host = client.normalizeHost(uri.getHost());
port = client.normalizePort(scheme, uri.getPort());
path = uri.getRawPath();
query = uri.getRawQuery();
extractParams(query);
this.uri = buildURI(true);
followRedirects(client.isFollowRedirects());
}
@Override
public long getConversationID()
{
return conversation;
}
@Override
public String getScheme()
{
return scheme;
}
@Override
public Request scheme(String scheme)
{
this.scheme = scheme;
this.uri = buildURI(true);
return this;
}
@Override
public String getHost()
{
return host;
}
@Override
public int getPort()
{
return port;
}
@Override
public HttpMethod getMethod()
{
return HttpMethod.fromString(method);
}
@Override
public String method()
{
return method;
}
@Override
public Request method(HttpMethod method)
{
this.method = method.asString();
return this;
}
@Override
public Request method(String method)
{
this.method = Objects.requireNonNull(method).toUpperCase(Locale.ENGLISH);
return this;
}
@Override
public String getPath()
{
return path;
}
@Override
public Request path(String path)
{
URI uri = URI.create(path);
String rawPath = uri.getRawPath();
if (uri.isOpaque())
rawPath = path;
if (rawPath == null)
rawPath = "";
this.path = rawPath;
String query = uri.getRawQuery();
if (query != null)
{
this.query = query;
params.clear();
extractParams(query);
}
this.uri = buildURI(true);
if (uri.isAbsolute())
this.path = buildURI(false).toString();
return this;
}
@Override
public String getQuery()
{
return query;
}
@Override
public URI getURI()
{
return uri;
}
@Override
public HttpVersion getVersion()
{
return version;
}
@Override
public Request version(HttpVersion version)
{
this.version = version;
return this;
}
@Override
public Request param(String name, String value)
{
params.add(name, value);
this.query = buildQuery();
this.uri = buildURI(true);
return this;
}
@Override
public Fields getParams()
{
return new Fields(params, true);
}
@Override
public String getAgent()
{
return headers.get(HttpHeader.USER_AGENT);
}
@Override
public Request agent(String agent)
{
headers.put(HttpHeader.USER_AGENT, agent);
return this;
}
@Override
public Request header(String name, String value)
{
if (value == null)
headers.remove(name);
else
headers.add(name, value);
return this;
}
@Override
public Request header(HttpHeader header, String value)
{
if (value == null)
headers.remove(header);
else
headers.add(header, value);
return this;
}
@Override
public Request attribute(String name, Object value)
{
attributes.put(name, value);
return this;
}
@Override
public Map getAttributes()
{
return attributes;
}
@Override
public HttpFields getHeaders()
{
return headers;
}
@Override
public List getRequestListeners(Class type)
{
// This method is invoked often in a request/response conversation,
// so we avoid allocation if there is no need to filter.
if (type == null)
return (List)requestListeners;
ArrayList result = new ArrayList<>();
for (RequestListener listener : requestListeners)
if (type.isInstance(listener))
result.add((T)listener);
return result;
}
@Override
public Request listener(Request.Listener listener)
{
this.requestListeners.add(listener);
return this;
}
@Override
public Request onRequestQueued(final QueuedListener listener)
{
this.requestListeners.add(new QueuedListener()
{
@Override
public void onQueued(Request request)
{
listener.onQueued(request);
}
});
return this;
}
@Override
public Request onRequestBegin(final BeginListener listener)
{
this.requestListeners.add(new BeginListener()
{
@Override
public void onBegin(Request request)
{
listener.onBegin(request);
}
});
return this;
}
@Override
public Request onRequestHeaders(final HeadersListener listener)
{
this.requestListeners.add(new HeadersListener()
{
@Override
public void onHeaders(Request request)
{
listener.onHeaders(request);
}
});
return this;
}
@Override
public Request onRequestCommit(final CommitListener listener)
{
this.requestListeners.add(new CommitListener()
{
@Override
public void onCommit(Request request)
{
listener.onCommit(request);
}
});
return this;
}
@Override
public Request onRequestContent(final ContentListener listener)
{
this.requestListeners.add(new ContentListener()
{
@Override
public void onContent(Request request, ByteBuffer content)
{
listener.onContent(request, content);
}
});
return this;
}
@Override
public Request onRequestSuccess(final SuccessListener listener)
{
this.requestListeners.add(new SuccessListener()
{
@Override
public void onSuccess(Request request)
{
listener.onSuccess(request);
}
});
return this;
}
@Override
public Request onRequestFailure(final FailureListener listener)
{
this.requestListeners.add(new FailureListener()
{
@Override
public void onFailure(Request request, Throwable failure)
{
listener.onFailure(request, failure);
}
});
return this;
}
@Override
public Request onResponseBegin(final Response.BeginListener listener)
{
this.responseListeners.add(new Response.BeginListener()
{
@Override
public void onBegin(Response response)
{
listener.onBegin(response);
}
});
return this;
}
@Override
public Request onResponseHeader(final Response.HeaderListener listener)
{
this.responseListeners.add(new Response.HeaderListener()
{
@Override
public boolean onHeader(Response response, HttpField field)
{
return listener.onHeader(response, field);
}
});
return this;
}
@Override
public Request onResponseHeaders(final Response.HeadersListener listener)
{
this.responseListeners.add(new Response.HeadersListener()
{
@Override
public void onHeaders(Response response)
{
listener.onHeaders(response);
}
});
return this;
}
@Override
public Request onResponseContent(final Response.ContentListener listener)
{
this.responseListeners.add(new Response.ContentListener()
{
@Override
public void onContent(Response response, ByteBuffer content)
{
listener.onContent(response, content);
}
});
return this;
}
@Override
public Request onResponseSuccess(final Response.SuccessListener listener)
{
this.responseListeners.add(new Response.SuccessListener()
{
@Override
public void onSuccess(Response response)
{
listener.onSuccess(response);
}
});
return this;
}
@Override
public Request onResponseFailure(final Response.FailureListener listener)
{
this.responseListeners.add(new Response.FailureListener()
{
@Override
public void onFailure(Response response, Throwable failure)
{
listener.onFailure(response, failure);
}
});
return this;
}
@Override
public ContentProvider getContent()
{
return content;
}
@Override
public Request content(ContentProvider content)
{
return content(content, null);
}
@Override
public Request content(ContentProvider content, String contentType)
{
if (contentType != null)
header(HttpHeader.CONTENT_TYPE, contentType);
this.content = content;
return this;
}
@Override
public Request file(Path file) throws IOException
{
return file(file, "application/octet-stream");
}
@Override
public Request file(Path file, String contentType) throws IOException
{
if (contentType != null)
header(HttpHeader.CONTENT_TYPE, contentType);
return content(new PathContentProvider(file));
}
@Override
public boolean isFollowRedirects()
{
return followRedirects;
}
@Override
public Request followRedirects(boolean follow)
{
this.followRedirects = follow;
return this;
}
@Override
public long getIdleTimeout()
{
return idleTimeout;
}
@Override
public Request idleTimeout(long timeout, TimeUnit unit)
{
this.idleTimeout = unit.toMillis(timeout);
return this;
}
@Override
public long getTimeout()
{
return timeout;
}
@Override
public Request timeout(long timeout, TimeUnit unit)
{
this.timeout = unit.toMillis(timeout);
return this;
}
@Override
public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException
{
FutureResponseListener listener = new FutureResponseListener(this);
send(this, listener);
long timeout = getTimeout();
if (timeout <= 0)
return listener.get();
try
{
return listener.get(timeout, TimeUnit.MILLISECONDS);
}
catch (InterruptedException | TimeoutException x)
{
// Differently from the Future, the semantic of this method is that if
// the send() is interrupted or times out, we abort the request.
abort(x);
throw x;
}
}
@Override
public void send(Response.CompleteListener listener)
{
if (getTimeout() > 0)
{
TimeoutCompleteListener timeoutListener = new TimeoutCompleteListener(this);
timeoutListener.schedule(client.getScheduler());
responseListeners.add(timeoutListener);
}
send(this, listener);
}
private void send(Request request, Response.CompleteListener listener)
{
if (listener != null)
responseListeners.add(listener);
client.send(request, responseListeners);
}
@Override
public boolean abort(Throwable cause)
{
aborted = Objects.requireNonNull(cause);
// The conversation may be null if it is already completed
HttpConversation conversation = client.getConversation(getConversationID(), false);
return conversation != null && conversation.abort(cause);
}
@Override
public Throwable getAbortCause()
{
return aborted;
}
private String buildQuery()
{
StringBuilder result = new StringBuilder();
for (Iterator iterator = params.iterator(); iterator.hasNext();)
{
Fields.Field field = iterator.next();
String[] values = field.values();
for (int i = 0; i < values.length; ++i)
{
if (i > 0)
result.append("&");
result.append(field.name()).append("=");
result.append(urlEncode(values[i]));
}
if (iterator.hasNext())
result.append("&");
}
return result.toString();
}
private String urlEncode(String value)
{
String encoding = "UTF-8";
try
{
return URLEncoder.encode(value, encoding);
}
catch (UnsupportedEncodingException e)
{
throw new UnsupportedCharsetException(encoding);
}
}
private void extractParams(String query)
{
if (query != null)
{
for (String nameValue : query.split("&"))
{
String[] parts = nameValue.split("=");
if (parts.length > 0)
{
String name = parts[0];
if (name.trim().length() == 0)
continue;
param(name, parts.length < 2 ? "" : urlDecode(parts[1]));
}
}
}
}
private String urlDecode(String value)
{
String charset = "UTF-8";
try
{
return URLDecoder.decode(value, charset);
}
catch (UnsupportedEncodingException x)
{
throw new UnsupportedCharsetException(charset);
}
}
private URI buildURI(boolean withQuery)
{
String path = getPath();
String query = getQuery();
if (query != null && withQuery)
path += "?" + query;
URI result = URI.create(path);
if (!result.isAbsolute() && !result.isOpaque())
result = URI.create(client.address(getScheme(), getHost(), getPort()) + path);
return result;
}
@Override
public String toString()
{
return String.format("%s[%s %s %s]@%x", HttpRequest.class.getSimpleName(), method(), getPath(), getVersion(), hashCode());
}
}