use of com.linecorp.armeria.common.HttpData in project curiostack by curioswitch.
the class StorageClient method createFile.
/**
* Create a new file for uploading data to cloud storage.
*/
public ListenableFuture<FileWriter> createFile(String filename, Map<String, String> metadata, RequestContext ctx) {
FileRequest request = ImmutableFileRequest.builder().name(filename).metadata(metadata).build();
ByteBuf buf = ctx.alloc().buffer();
try (ByteBufOutputStream os = new ByteBufOutputStream(buf)) {
OBJECT_MAPPER.writeValue((DataOutput) os, request);
} catch (IOException e) {
buf.release();
throw new UncheckedIOException("Could not serialize resource JSON to buffer.", e);
}
HttpData data = new ByteBufHttpData(buf, true);
HttpHeaders headers = HttpHeaders.of(HttpMethod.POST, uploadUrl).contentType(MediaType.JSON_UTF_8);
HttpResponse res = httpClient.execute(headers, data);
return CompletableFuturesExtra.toListenableFuture(res.aggregate(ctx.contextAwareEventLoop()).handle((msg, t) -> {
if (t != null) {
throw new RuntimeException("Unexpected error creating new file.", t);
}
HttpHeaders responseHeaders = msg.headers();
if (!responseHeaders.status().equals(HttpStatus.OK)) {
throw new RuntimeException("Non-successful response when creating new file: " + responseHeaders + "\n" + msg.content().toStringUtf8());
}
String location = responseHeaders.get(HttpHeaderNames.LOCATION);
String pathAndQuery = location.substring("https://www.googleapis.com/upload/storage/v1".length());
return new FileWriter(pathAndQuery, ctx, httpClient);
}));
}
use of com.linecorp.armeria.common.HttpData in project zipkin by openzipkin.
the class ScribeInboundHandler method channelRead.
@Override
public void channelRead(ChannelHandlerContext ctx, Object payload) {
assert payload instanceof ByteBuf;
HttpRequest request = HttpRequest.of(THRIFT_HEADERS, HttpData.wrap((ByteBuf) payload));
ServiceRequestContextBuilder requestContextBuilder = ServiceRequestContext.builder(request).service(scribeService).alloc(ctx.alloc());
if (ctx.executor() instanceof EventLoop) {
requestContextBuilder.eventLoop((EventLoop) ctx.executor());
}
ServiceRequestContext requestContext = requestContextBuilder.build();
final HttpResponse response;
try (SafeCloseable unused = requestContext.push()) {
response = HttpResponse.of(scribeService.serve(requestContext, request));
} catch (Throwable t) {
propagateIfFatal(t);
exceptionCaught(ctx, t);
return;
}
int responseIndex = nextResponseIndex++;
response.aggregateWithPooledObjects(ctx.executor(), ctx.alloc()).handle((msg, t) -> {
if (t != null) {
exceptionCaught(ctx, t);
return null;
}
try (HttpData content = msg.content()) {
ByteBuf returned = ctx.alloc().buffer(content.length() + 4);
returned.writeInt(content.length());
returned.writeBytes(content.byteBuf());
if (responseIndex == previouslySentResponseIndex + 1) {
ctx.writeAndFlush(returned);
previouslySentResponseIndex++;
flushResponses(ctx);
} else {
pendingResponses.put(responseIndex, returned);
}
}
return null;
});
}
use of com.linecorp.armeria.common.HttpData in project curiostack by curioswitch.
the class FileWriter method doUploadChunk.
private CompletableFuture<Void> doUploadChunk(ByteBuf chunk, boolean endOfFile) {
int length = chunk.readableBytes();
long limit = filePosition + length;
StringBuilder range = new StringBuilder("bytes ");
if (length == 0) {
range.append('*');
} else {
range.append(filePosition).append('-').append(limit - 1);
}
range.append('/');
if (endOfFile) {
range.append(limit);
} else {
range.append('*');
}
RequestHeaders headers = RequestHeaders.of(HttpMethod.PUT, uploadUrl, HttpHeaderNames.CONTENT_RANGE, range.toString());
HttpData data = HttpData.wrap(chunk).withEndOfStream();
chunk.retain();
return httpClient.execute(headers, data).aggregate(eventLoop).thenComposeAsync(msg -> {
ResponseHeaders responseHeaders = msg.headers();
if (!responseHeaders.status().codeClass().equals(HttpStatusClass.SUCCESS) && responseHeaders.status().code() != 308) {
chunk.release();
throw new RuntimeException("Unsuccessful response uploading chunk: endOfFile: " + endOfFile + " Request headers: " + headers + "\n" + " Response headers: " + responseHeaders + "\n" + msg.content().toStringUtf8());
}
String responseRange = responseHeaders.get(HttpHeaderNames.RANGE);
if (responseRange == null) {
chunk.release();
return completedFuture(null);
}
long responseLimit = rangeHeaderLimit(responseHeaders.get(HttpHeaderNames.RANGE));
filePosition = responseLimit + 1;
int notUploaded = (int) (limit - 1 - responseLimit);
if (notUploaded > 0) {
chunk.readerIndex(chunk.writerIndex() - notUploaded);
if (endOfFile) {
return doUploadChunk(chunk, true);
}
if (unfinishedChunk == null) {
copyUnfinishedBuffer(chunk);
} else {
ByteBuf newUnfinished = alloc.buffer(chunk.readableBytes() + unfinishedChunk.readableBytes());
newUnfinished.writeBytes(chunk).writeBytes(unfinishedChunk);
unfinishedChunk.release();
unfinishedChunk = newUnfinished;
}
}
chunk.release();
return completedFuture(null);
}, eventLoop);
}
use of com.linecorp.armeria.common.HttpData in project zipkin by openzipkin.
the class UnzippingBytesRequestConverter method validateAndStoreSpans.
/**
* This synchronously decodes the message so that users can see data errors.
*/
@SuppressWarnings("FutureReturnValueIgnored")
// check? Say it is somehow canceled, would we take action? Would callback.onError() be redundant?
HttpResponse validateAndStoreSpans(SpanBytesDecoder decoder, ServiceRequestContext ctx, HttpRequest req) {
CompletableCallback result = new CompletableCallback();
req.aggregateWithPooledObjects(ctx.eventLoop(), ctx.alloc()).handle((msg, t) -> {
if (t != null) {
result.onError(t);
return null;
}
final HttpData requestContent;
try {
requestContent = UnzippingBytesRequestConverter.convertRequest(ctx, msg);
} catch (Throwable t1) {
propagateIfFatal(t1);
result.onError(t1);
return null;
}
try (HttpData content = requestContent) {
// logging already handled upstream in UnzippingBytesRequestConverter where request context exists
if (content.isEmpty()) {
result.onSuccess(null);
return null;
}
final ByteBuffer nioBuffer = content.byteBuf().nioBuffer();
try {
SpanBytesDecoderDetector.decoderForListMessage(nioBuffer);
} catch (IllegalArgumentException e) {
result.onError(new IllegalArgumentException("Expected a " + decoder + " encoded list\n"));
return null;
} catch (Throwable t1) {
result.onError(t1);
return null;
}
SpanBytesDecoder unexpectedDecoder = testForUnexpectedFormat(decoder, nioBuffer);
if (unexpectedDecoder != null) {
result.onError(new IllegalArgumentException("Expected a " + decoder + " encoded list, but received: " + unexpectedDecoder + "\n"));
return null;
}
// collector.accept might block so need to move off the event loop. We make sure the
// callback is context aware to continue the trace.
Executor executor = ctx.makeContextAware(ctx.blockingTaskExecutor());
try {
collector.acceptSpans(nioBuffer, decoder, result, executor);
} catch (Throwable t1) {
result.onError(t1);
return null;
}
}
return null;
});
return HttpResponse.from(result);
}
use of com.linecorp.armeria.common.HttpData in project zipkin by openzipkin.
the class UnzippingBytesRequestConverter method convertRequest.
static HttpData convertRequest(ServiceRequestContext ctx, AggregatedHttpRequest request) {
ZipkinHttpCollector.metrics.incrementMessages();
String encoding = request.headers().get(HttpHeaderNames.CONTENT_ENCODING);
HttpData content = request.content();
if (!content.isEmpty() && encoding != null && encoding.contains("gzip")) {
content = StreamDecoderFactory.gzip().newDecoder(ctx.alloc()).decode(content);
// The implementation of the armeria decoder is to return an empty body on failure
if (content.isEmpty()) {
ZipkinHttpCollector.maybeLog("Malformed gzip body", ctx, request);
content.close();
throw new IllegalArgumentException("Cannot gunzip spans");
}
}
if (content.isEmpty())
ZipkinHttpCollector.maybeLog("Empty POST body", ctx, request);
if (content.length() == 2 && "[]".equals(content.toStringAscii())) {
ZipkinHttpCollector.maybeLog("Empty JSON list POST body", ctx, request);
content.close();
content = HttpData.empty();
}
ZipkinHttpCollector.metrics.incrementBytes(content.length());
return content;
}
Aggregations