use of org.jboss.netty.handler.codec.http.HttpRequest in project opentsdb by OpenTSDB.
the class TestTreeRpc method handleBranchBadMethod.
@Test(expected = BadRequestException.class)
public void handleBranchBadMethod() throws Exception {
final HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.TRACE, "/api/tree/branch");
final HttpQuery query = new HttpQuery(tsdb, req, NettyMocks.fakeChannel());
rpc.execute(tsdb, query);
}
use of org.jboss.netty.handler.codec.http.HttpRequest in project opentsdb by OpenTSDB.
the class TestTreeRpc method handleNotMatchedBadMethod.
@Test(expected = BadRequestException.class)
public void handleNotMatchedBadMethod() throws Exception {
final HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.TRACE, "/api/tree/notmatched");
final HttpQuery query = new HttpQuery(tsdb, req, NettyMocks.fakeChannel());
rpc.execute(tsdb, query);
}
use of org.jboss.netty.handler.codec.http.HttpRequest in project opentsdb by OpenTSDB.
the class NettyMocks method getQuery.
/**
* Returns an HttpQuery object with the given URI and the following parameters:
* Method = GET
* Content = null
* Content-Type = null
* @param tsdb The TSDB to associate with, needs to be mocked with the Config
* object set
* @param uri A URI to use
* @return an HttpQuery object
*/
public static HttpQuery getQuery(final TSDB tsdb, final String uri) {
final Channel channelMock = NettyMocks.fakeChannel();
final HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri);
return new HttpQuery(tsdb, req, channelMock);
}
use of org.jboss.netty.handler.codec.http.HttpRequest in project opentsdb by OpenTSDB.
the class NettyMocks method contentQuery.
/**
* Returns an HttpQuery object with the given settings
* @param tsdb The TSDB to associate with, needs to be mocked with the Config
* object set
* @param uri A URI to use
* @param content Content to POST (UTF-8 encoding)
* @param type Content-Type value
* @param method The HTTP method to use, GET, POST, etc.
* @return an HttpQuery object
*/
public static HttpQuery contentQuery(final TSDB tsdb, final String uri, final String content, final String type, final HttpMethod method) {
final Channel channelMock = NettyMocks.fakeChannel();
final HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, method, uri);
if (content != null) {
req.setContent(ChannelBuffers.copiedBuffer(content, Charset.forName("UTF-8")));
}
req.headers().set("Content-Type", type);
return new HttpQuery(tsdb, req, channelMock);
}
use of org.jboss.netty.handler.codec.http.HttpRequest in project druid by druid-io.
the class NettyHttpClient method go.
@Override
public <Intermediate, Final> ListenableFuture<Final> go(final Request request, final HttpResponseHandler<Intermediate, Final> handler, final Duration requestReadTimeout) {
final HttpMethod method = request.getMethod();
final URL url = request.getUrl();
final Multimap<String, String> headers = request.getHeaders();
final String requestDesc = method + " " + url;
if (log.isDebugEnabled()) {
log.debug("[%s] starting", requestDesc);
}
// Block while acquiring a channel from the pool, then complete the request asynchronously.
final Channel channel;
final String hostKey = getPoolKey(url);
final ResourceContainer<ChannelFuture> channelResourceContainer = pool.take(hostKey);
final ChannelFuture channelFuture = channelResourceContainer.get().awaitUninterruptibly();
if (!channelFuture.isSuccess()) {
// Some other poor sap will have to deal with it...
channelResourceContainer.returnResource();
return Futures.immediateFailedFuture(new ChannelException("Faulty channel in resource pool", channelFuture.getCause()));
} else {
channel = channelFuture.getChannel();
// In case we get a channel that never had its readability turned back on.
channel.setReadable(true);
}
final String urlFile = StringUtils.nullToEmptyNonDruidDataString(url.getFile());
final HttpRequest httpRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1, method, urlFile.isEmpty() ? "/" : urlFile);
if (!headers.containsKey(HttpHeaders.Names.HOST)) {
httpRequest.headers().add(HttpHeaders.Names.HOST, getHost(url));
}
// If Accept-Encoding is set in the Request, use that. Otherwise use the default from "compressionCodec".
if (!headers.containsKey(HttpHeaders.Names.ACCEPT_ENCODING)) {
httpRequest.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, compressionCodec.getEncodingString());
}
for (Map.Entry<String, Collection<String>> entry : headers.asMap().entrySet()) {
String key = entry.getKey();
for (String obj : entry.getValue()) {
httpRequest.headers().add(key, obj);
}
}
if (request.hasContent()) {
httpRequest.setContent(request.getContent());
}
final long readTimeout = getReadTimeout(requestReadTimeout);
final SettableFuture<Final> retVal = SettableFuture.create();
if (readTimeout > 0) {
channel.getPipeline().addLast(READ_TIMEOUT_HANDLER_NAME, new ReadTimeoutHandler(timer, readTimeout, TimeUnit.MILLISECONDS));
}
channel.getPipeline().addLast(LAST_HANDLER_NAME, new SimpleChannelUpstreamHandler() {
private volatile ClientResponse<Intermediate> response = null;
// Chunk number most recently assigned.
private long currentChunkNum = 0;
// Suspend and resume watermarks (respectively: last chunk number that triggered a suspend, and that was
// provided to the TrafficCop's resume method). Synchronized access since they are not always accessed
// from an I/O thread. (TrafficCops can be called from any thread.)
private final Object watermarkLock = new Object();
private long suspendWatermark = -1;
private long resumeWatermark = -1;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
if (log.isDebugEnabled()) {
log.debug("[%s] messageReceived: %s", requestDesc, e.getMessage());
}
try {
Object msg = e.getMessage();
if (msg instanceof HttpResponse) {
HttpResponse httpResponse = (HttpResponse) msg;
if (log.isDebugEnabled()) {
log.debug("[%s] Got response: %s", requestDesc, httpResponse.getStatus());
}
HttpResponseHandler.TrafficCop trafficCop = resumeChunkNum -> {
synchronized (watermarkLock) {
resumeWatermark = Math.max(resumeWatermark, resumeChunkNum);
if (suspendWatermark >= 0 && resumeWatermark >= suspendWatermark) {
suspendWatermark = -1;
channel.setReadable(true);
long backPressureDuration = System.nanoTime() - backPressureStartTimeNs;
log.debug("[%s] Resumed reads from channel (chunkNum = %,d).", requestDesc, resumeChunkNum);
return backPressureDuration;
}
}
// If we didn't resume, don't know if backpressure was happening
return 0;
};
response = handler.handleResponse(httpResponse, trafficCop);
if (response.isFinished()) {
retVal.set((Final) response.getObj());
}
assert currentChunkNum == 0;
possiblySuspendReads(response);
if (!httpResponse.isChunked()) {
finishRequest();
}
} else if (msg instanceof HttpChunk) {
HttpChunk httpChunk = (HttpChunk) msg;
if (log.isDebugEnabled()) {
log.debug("[%s] Got chunk: %sB, last=%s", requestDesc, httpChunk.getContent().readableBytes(), httpChunk.isLast());
}
if (httpChunk.isLast()) {
finishRequest();
} else {
response = handler.handleChunk(response, httpChunk, ++currentChunkNum);
if (response.isFinished() && !retVal.isDone()) {
retVal.set((Final) response.getObj());
}
possiblySuspendReads(response);
}
} else {
throw new ISE("Unknown message type[%s]", msg.getClass());
}
} catch (Exception ex) {
log.warn(ex, "[%s] Exception thrown while processing message, closing channel.", requestDesc);
if (!retVal.isDone()) {
retVal.set(null);
}
channel.close();
channelResourceContainer.returnResource();
throw ex;
}
}
private void possiblySuspendReads(ClientResponse<?> response) {
if (!response.isContinueReading()) {
synchronized (watermarkLock) {
suspendWatermark = Math.max(suspendWatermark, currentChunkNum);
if (suspendWatermark > resumeWatermark) {
channel.setReadable(false);
backPressureStartTimeNs = System.nanoTime();
log.debug("[%s] Suspended reads from channel (chunkNum = %,d).", requestDesc, currentChunkNum);
}
}
}
}
private void finishRequest() {
ClientResponse<Final> finalResponse = handler.done(response);
if (!finalResponse.isFinished() || !finalResponse.isContinueReading()) {
throw new ISE("[%s] Didn't get a completed ClientResponse Object from [%s] (finished = %s, continueReading = %s)", requestDesc, handler.getClass(), finalResponse.isFinished(), finalResponse.isContinueReading());
}
if (!retVal.isDone()) {
retVal.set(finalResponse.getObj());
}
removeHandlers();
channel.setReadable(true);
channelResourceContainer.returnResource();
}
@Override
public void exceptionCaught(ChannelHandlerContext context, ExceptionEvent event) {
if (log.isDebugEnabled()) {
final Throwable cause = event.getCause();
if (cause == null) {
log.debug("[%s] Caught exception", requestDesc);
} else {
log.debug(cause, "[%s] Caught exception", requestDesc);
}
}
retVal.setException(event.getCause());
// response is non-null if we received initial chunk and then exception occurs
if (response != null) {
handler.exceptionCaught(response, event.getCause());
}
try {
if (channel.isOpen()) {
channel.close();
}
} catch (Exception e) {
log.warn(e, "Error while closing channel");
} finally {
channelResourceContainer.returnResource();
}
}
@Override
public void channelDisconnected(ChannelHandlerContext context, ChannelStateEvent event) {
if (log.isDebugEnabled()) {
log.debug("[%s] Channel disconnected", requestDesc);
}
// response is non-null if we received initial chunk and then exception occurs
if (response != null) {
handler.exceptionCaught(response, new ChannelException("Channel disconnected"));
}
channel.close();
channelResourceContainer.returnResource();
if (!retVal.isDone()) {
log.warn("[%s] Channel disconnected before response complete", requestDesc);
retVal.setException(new ChannelException("Channel disconnected"));
}
}
private void removeHandlers() {
if (readTimeout > 0) {
channel.getPipeline().remove(READ_TIMEOUT_HANDLER_NAME);
}
channel.getPipeline().remove(LAST_HANDLER_NAME);
}
});
channel.write(httpRequest).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess()) {
channel.close();
channelResourceContainer.returnResource();
if (!retVal.isDone()) {
retVal.setException(new ChannelException(StringUtils.format("[%s] Failed to write request to channel", requestDesc), future.getCause()));
}
}
}
});
return retVal;
}
Aggregations