下面列出了怎么用 io.netty.handler.codec.http.DefaultFullHttpResponse 的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
public void testFullResponse() throws Exception {
outputReceived = new CountDownLatch(1);
ByteBuf body = ByteBufUtil.writeUtf8(UnpooledByteBufAllocator.DEFAULT, "response");
FullHttpResponse responseIn = new DefaultFullHttpResponse(HTTP_1_1, OK, body);
channel.writeInbound(responseIn);
channel.runPendingTasks(); // blocks
Uninterruptibles.awaitUninterruptibly(outputReceived);
Response responseOut = responses.remove(0);
assertTrue(responseOut != null);
assertTrue(responseOut instanceof FullResponse);
assertEquals("HTTP/1.1", responseOut.version());
assertEquals(OK, responseOut.status());
assertTrue(responseOut.hasBody());
assertFalse(responseOut.body() == null);
assertEquals(body, responseOut.body());
}
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) {
if (!(msg instanceof HttpRequest)) return;
HttpRequest req = (HttpRequest) msg;
if (HttpUtil.is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
}
boolean keepAlive = HttpUtil.isKeepAlive(req);
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK,
Unpooled.wrappedBuffer(HELLO_WORLD));
response.headers().set(CONTENT_TYPE, "text/plain");
response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
if (!keepAlive) {
ctx.write(response).addListener(ChannelFutureListener.CLOSE);
} else {
response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE);
ctx.write(response);
}
}
@Override
public void messageReceived(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
if (HttpHeaderUtil.is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
}
boolean keepAlive = HttpHeaderUtil.isKeepAlive(req);
ByteBuf content = ctx.alloc().buffer();
content.writeBytes(HelloWorldHttp2Handler.RESPONSE_BYTES.duplicate());
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, content);
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes());
if (!keepAlive) {
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
} else {
response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE);
ctx.writeAndFlush(response);
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, SuggestRequest msg) throws Exception {
byte[] buf = null;
try {
buf = JsonUtil.getObjectMapper().writeValueAsBytes(dataStore.suggest(msg));
} catch (TimelyException e) {
LOG.error(e.getMessage(), e);
this.sendHttpError(ctx, e);
return;
}
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
Unpooled.copiedBuffer(buf));
response.headers().set(HttpHeaderNames.CONTENT_TYPE, Constants.JSON_TYPE);
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
sendResponse(ctx, response);
}
static void sendDecodingFailures(ChannelHandlerContext ctx, Throwable t, Object msg) {
Throwable cause = t.getCause() != null ? t.getCause() : t;
if (log.isDebugEnabled()) {
log.debug(format(ctx.channel(), "Decoding failed: " + msg + " : "), cause);
}
ReferenceCountUtil.release(msg);
HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_0,
cause instanceof TooLongFrameException ? HttpResponseStatus.REQUEST_ENTITY_TOO_LARGE:
HttpResponseStatus.BAD_REQUEST);
response.headers()
.setInt(HttpHeaderNames.CONTENT_LENGTH, 0)
.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
ctx.writeAndFlush(response)
.addListener(ChannelFutureListener.CLOSE);
}
@Override
public void sendResponse(FullHttpRequest req, ChannelHandlerContext ctx) throws Exception {
counter.inc();
byte[] content = null;
try(InputStream is = FallbackResponder.class.getClassLoader().getResourceAsStream(resource)) {
content = IOUtils.toByteArray(is);
}
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
HttpHeaders.setContentLength(response, content.length);
response.headers().set(HttpHeaders.Names.CONTENT_TYPE, MediaType.APPLICATION_XML_UTF_8.toString());
response.content().writeBytes(content);
ctx.write(response);
ChannelFuture future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
future.addListener(ChannelFutureListener.CLOSE);
}
private void writeResourceReport(Channel channel) {
ByteBuf content = Unpooled.buffer();
Writer writer = new OutputStreamWriter(new ByteBufOutputStream(content), CharsetUtil.UTF_8);
try {
reportAdapter.toJson(resourceReport.get(), writer);
writer.close();
} catch (IOException e) {
LOG.error("error writing resource report", e);
writeAndClose(channel, new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR,
Unpooled.copiedBuffer(e.getMessage(), StandardCharsets.UTF_8)));
return;
}
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
HttpUtil.setContentLength(response, content.readableBytes());
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
channel.writeAndFlush(response);
}
public static FullHttpResponse createResponse(HttpResponse homekitResponse) {
FullHttpResponse response =
new DefaultFullHttpResponse(
homekitResponse.getVersion() == HttpResponse.HttpVersion.EVENT_1_0
? EVENT_VERSION
: HttpVersion.HTTP_1_1,
HttpResponseStatus.valueOf(homekitResponse.getStatusCode()),
Unpooled.copiedBuffer(homekitResponse.getBody()));
for (Entry<String, String> header : homekitResponse.getHeaders().entrySet()) {
response.headers().add(header.getKey(), header.getValue());
}
response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, response.content().readableBytes());
response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
return response;
}
@Override
protected void encode(ChannelHandlerContext ctx, Response msg, List<Object> out) throws Exception {
String content = msg.getContent();
int byteBufLen = 0;
if (content != null && content.length() > 0) {
byteBufLen = content.length();
}
ByteBuf buf;
if (byteBufLen > 0) {
buf = ctx.alloc().buffer(byteBufLen);
buf.writeBytes(content.getBytes());
} else {
buf = Unpooled.EMPTY_BUFFER;
}
DefaultFullHttpResponse httpResponse
= new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, msg.getStatus(), buf);
httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, String.format("%s;charset=%s",msg.getContentType(),msg.getCharset()));
httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, httpResponse.content().toString());
if(msg.isKeepAlive()) {
httpResponse.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
}
out.add(httpResponse);
}
@Override
public void getState(Channel channel, SendServerVO serverVO) {
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
response.headers().set(HttpConstant.CONTENT_TYPE, HttpConstant.APPLICATION_JSON);
if (serverVO.getToken() == "") {
notFindUri(channel);
}
Boolean state = WebSocketCacheMap.hasToken(serverVO.getToken());
StateVo stateVo = new StateVo(serverVO.getToken(), state);
ResultVO<StateVo> resultVO = new ResultVO<>(HttpResponseStatus.OK.code(), stateVo);
Gson gson = new Gson();
ByteBuf buf = Unpooled.copiedBuffer(gson.toJson(resultVO), CharsetUtil.UTF_8);
response.content().writeBytes(buf);
channel.writeAndFlush(response);
close(channel);
}
protected int sendHttp1Response(ChannelHandlerContext ctx, HttpResponseStatus status, String resultStr,
boolean isKeepAlive) {
ByteBuf content = Unpooled.copiedBuffer(resultStr, RpcConstants.DEFAULT_CHARSET);
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, status, content);
res.headers().set(CONTENT_TYPE, "text/html; charset=" + RpcConstants.DEFAULT_CHARSET.displayName());
HttpUtil.setContentLength(res, content.readableBytes());
try {
ChannelFuture f = ctx.channel().writeAndFlush(res);
if (isKeepAlive) {
HttpUtil.setKeepAlive(res, true);
} else {
HttpUtil.setKeepAlive(res, false); //set keepalive closed
f.addListener(ChannelFutureListener.CLOSE);
}
} catch (Exception e2) {
LOGGER.warn("Failed to send HTTP response to remote, cause by:", e2);
}
return content.readableBytes();
}
/**
* 给客户端回复消息
*
* @param ctx
* @param req
* @param res
*/
private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, DefaultFullHttpResponse res) {
//返回应答给客户端
if (res.getStatus().code() != 200) {
ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8);
res.content().writeBytes(buf);
buf.release();
}
// 如果是非Keep-Alive,关闭连接
ChannelFuture f = ctx.channel().writeAndFlush(res);
if (!HttpHeaders.isKeepAlive(req) || res.getStatus().code() != 200) {
f.addListener(ChannelFutureListener.CLOSE);
}
}
/**
* Returns a full HTTP response with the specified status, content type, and custom headers.
*
* <p>Headers should be specified as a map of strings. For example, to allow CORS, add the
* following key and value: "access-control-allow-origin", "http://foo.example"
*
* <p>If content type or content length are passed in as custom headers, they will be ignored.
* Instead, content type will be as specified by the parameter mediaTypes and content length will
* be the length of the parameter contentLength.
*/
public static FullHttpResponse newResponse(
HttpResponseStatus status,
ByteBuf payload,
ContentType contentType,
Map<String, String> customHeaders) {
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, payload);
if (customHeaders != null) {
for (Map.Entry<String, String> entry : customHeaders.entrySet()) {
response.headers().set(entry.getKey(), entry.getValue());
}
}
response.headers().set(CONTENT_TYPE, contentType.value);
response.headers().setInt(CONTENT_LENGTH, payload.readableBytes());
return response;
}
/**
* Create a new object to contain the response data
*
* @param streamId The stream associated with the response
* @param http2Headers The initial set of HTTP/2 headers to create the response with
* @param alloc The {@link ByteBufAllocator} to use to generate the content of the message
* @param validateHttpHeaders <ul>
* <li>{@code true} to validate HTTP headers in the http-codec</li>
* <li>{@code false} not to validate HTTP headers in the http-codec</li>
* </ul>
* @return A new response object which represents headers/data
* @throws Http2Exception see {@link #addHttp2ToHttpHeaders(int, Http2Headers, FullHttpMessage, boolean)}
*/
public static FullHttpResponse toFullHttpResponse(int streamId, Http2Headers http2Headers, ByteBufAllocator alloc,
boolean validateHttpHeaders)
throws Http2Exception {
HttpResponseStatus status = parseStatus(http2Headers.status());
// HTTP/2 does not define a way to carry the version or reason phrase that is included in an
// HTTP/1.1 status line.
FullHttpResponse msg = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, alloc.buffer(),
validateHttpHeaders);
try {
addHttp2ToHttpHeaders(streamId, http2Headers, msg, false);
} catch (Http2Exception e) {
msg.release();
throw e;
} catch (Throwable t) {
msg.release();
throw streamError(streamId, PROTOCOL_ERROR, t, "HTTP/2 to HTTP/1.x headers conversion error");
}
return msg;
}
public static FullHttpResponse buildJson(Object obj, Include include) {
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, AsciiString.cached("application/json; charset=utf-8"));
if (obj != null) {
try {
ObjectMapper objectMapper = new ObjectMapper();
if (include != null) {
objectMapper.setSerializationInclusion(include);
}
String content = objectMapper.writeValueAsString(obj);
response.content().writeBytes(content.getBytes(Charset.forName("utf-8")));
} catch (JsonProcessingException e) {
response.setStatus(HttpResponseStatus.SERVICE_UNAVAILABLE);
}
}
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
return response;
}
@Override
protected ChannelHandler newNonSslHandler(ChannelHandlerContext context) {
return new ChannelInboundHandlerAdapter() {
private HttpResponseEncoder encoder = new HttpResponseEncoder();
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
LOG.trace("Received non-SSL request, returning redirect");
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.MOVED_PERMANENTLY, Unpooled.EMPTY_BUFFER);
response.headers().set(HttpHeaderNames.LOCATION, redirectAddress);
LOG.trace(Constants.LOG_RETURNING_RESPONSE, response);
encoder.write(ctx, response, ctx.voidPromise());
ctx.flush();
}
};
}
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest req = (HttpRequest) msg;
if (is100ContinueExpected(req)) {
ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
}
boolean keepAlive = isKeepAlive(req);
ByteBuf content = Unpooled.copiedBuffer("Hello World " + new Date(), CharsetUtil.UTF_8);
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
if (!keepAlive) {
ctx.write(response).addListener(ChannelFutureListener.CLOSE);
} else {
response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
ctx.write(response);
}
}
}
public static FullHttpResponse buildResponse(BidResponse bidResponse) {
String respJson = JSON.toJSONString(bidResponse, jsonSnakeConfig);
// byte[] buf = JSON.toJSONBytes(bidResponse, jsonSnakeConfig);
FullHttpResponse response = new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
Unpooled.wrappedBuffer(respJson.getBytes())
);
response.headers().set(
HttpHeaderNames.CONTENT_TYPE.toString(),
"application/json;charset=utf8"
);
log.info("gae_response\t{}", respJson);
return response;
}
private void checkAndInit() {
if (ok.compareAndSet(true, false)) {
delegator = new DefaultFullHttpResponse(HttpVersion.valueOf(httpVer),
HttpResponseStatus.OK);
status = new HttpStatus(delegator);
headers = new HttpHeaders(delegator.headers());
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
// TODO Auto-generated method stub
try {
ByteBuf content = msg.content();
byte[] bts = new byte[content.readableBytes()];
content.readBytes(bts);
String result = null;
if(msg.getMethod() == HttpMethod.GET) {
String url = msg.getUri().toString();
//result = "get method and paramters is "+JSON.toJSONString(UrlUtil.parse(url).params);
}else if(msg.getMethod() == HttpMethod.POST) {
result = "post method and paramters is "+ new String(bts);
}
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
response.headers().set("content-Type","text/html;charset=UTF-8");
StringBuilder sb = new StringBuilder();
sb.append("<html>")
.append("<head>")
.append("<title>netty http server</title>")
.append("</head>")
.append("<body>")
.append(result)
.append("</body>")
.append("</html>\r\n");
ByteBuf responseBuf = Unpooled.copiedBuffer(sb,CharsetUtil.UTF_8);
response.content().writeBytes(responseBuf);
responseBuf.release();
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, MetricRequest m) throws Exception {
try {
this.dataStore.store(m.getMetric());
} catch (TimelyException e) {
LOG.error(e.getMessage(), e);
this.sendHttpError(ctx, e);
return;
}
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
Unpooled.EMPTY_BUFFER);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, Constants.JSON_TYPE);
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
sendResponse(ctx, response);
}
public static FullHttpResponse theHttpContent(String str, HttpResponseStatus status) {
ByteBuf byteBuf = Unpooled.copiedBuffer(str.getBytes());
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status ,byteBuf);
response.headers().set(CONTENT_TYPE, ContentTypePool.TEXT_UTF8);
response.headers().set(CONTENT_LENGTH, byteBuf.readableBytes());
response.headers().set(CONNECTION, HEADER_CONNECTION_CLOSE);
return response;
}
@Override
public FullHttpResponse marshallResponse(final Object res,
final HttpResponseStatus status) throws JsonProcessingException {
final String content = mapper.writeValueAsString(res);
final ByteBuf buf = Unpooled.copiedBuffer(content, CharsetUtil.UTF_8);
final FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status, buf);
response.headers().set(CONTENT_TYPE, ContentType.JSON.responseEncoding());
return response;
}
public static FullHttpResponse theBase64Image1pxGif() {
ByteBuf byteBuf = Base64.decode(Unpooled.copiedBuffer(BASE64GIF_BYTES));
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK , byteBuf);
response.headers().set(CONTENT_TYPE, ContentTypePool.GIF);
response.headers().set(CONTENT_LENGTH, byteBuf.readableBytes());
response.headers().set(CONNECTION, HEADER_CONNECTION_CLOSE);
return response;
}
/**
* response输出
* @param text
* @param contentType
*/
public static FullHttpResponse render(String text, String contentType){
if(text == null){
text = "";
}
ByteBuf byteBuf = Unpooled.wrappedBuffer(text.getBytes());
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf);
response.headers().add(CONTENT_TYPE, contentType);
response.headers().add(CONTENT_LENGTH, String.valueOf(byteBuf.readableBytes()));
return response;
}
@Override
public void send(Channel channel, ExceptionResponse exceptionResponse) {
String content = exceptionResponse.getContent();
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, exceptionResponse.getStatus());
if (content != null) {
response.headers().set("X-Ca-Error-Message", content);
}
config.getResponseHandler().send(channel, response);
}
@Override
public HttpResponse clientToProxyRequest(HttpObject httpObject) {
if (!whitelistEnabled) {
return null;
}
if (httpObject instanceof HttpRequest) {
HttpRequest httpRequest = (HttpRequest) httpObject;
// do not allow HTTP CONNECTs to be short-circuited
if (ProxyUtils.isCONNECT(httpRequest)) {
return null;
}
boolean urlWhitelisted = false;
String url = getFullUrl(httpRequest);
for (Pattern pattern : whitelistUrls) {
if (pattern.matcher(url).matches()) {
urlWhitelisted = true;
break;
}
}
if (!urlWhitelisted) {
HttpResponseStatus status = HttpResponseStatus.valueOf(whitelistResponseCode);
HttpResponse resp = new DefaultFullHttpResponse(httpRequest.getProtocolVersion(), status);
HttpHeaders.setContentLength(resp, 0L);
return resp;
}
}
return null;
}
public static void sendJsonResponse(
ChannelHandlerContext ctx, String json, HttpResponseStatus status) {
FullHttpResponse resp = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, false);
resp.headers().set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
ByteBuf content = resp.content();
content.writeCharSequence(json, CharsetUtil.UTF_8);
content.writeByte('\n');
sendHttpResponse(ctx, resp, true);
}
@Override
public FullHttpResponse get(ChannelHandlerContext channelHandlerContext,
QueryDecoder queryDecoder,
PathProvider path,
HttpRequest httpRequest) throws Exception {
CloudNet.getLogger().debug("HTTP Request from " + channelHandlerContext.channel().remoteAddress());
FullHttpResponse fullHttpResponse = new DefaultFullHttpResponse(httpRequest.getProtocolVersion(), HttpResponseStatus.UNAUTHORIZED);
fullHttpResponse.headers().set("Content-Type", "application/json");
fullHttpResponse.headers().set("Access-Control-Allow-Origin", "*");
Document dataDocument = new Document("success", false).append("reason", new ArrayList<>()).append("response", new Document());
if (!httpRequest.headers().contains("-Xcloudnet-user") || (!httpRequest.headers()
.contains("-Xcloudnet-token") && !httpRequest.headers()
.contains(
"-Xcloudnet-password"))) {
dataDocument.append("reason", Arrays.asList("-Xcloudnet-user, -Xcloudnet-token or -Xmessage not found!"));
fullHttpResponse.content().writeBytes(dataDocument.convertToJsonString().getBytes(StandardCharsets.UTF_8));
return fullHttpResponse;
}
if (httpRequest.headers().contains("-Xcloudnet-token") ? !CloudNet.getInstance().authorization(httpRequest.headers()
.get("-Xcloudnet-user"),
httpRequest.headers()
.get("-Xcloudnet-token")) : !CloudNet
.getInstance()
.authorizationPassword(httpRequest.headers().get("-Xcloudnet-user"), httpRequest.headers().get("-Xcloudnet-password"))) {
dataDocument.append("reason", Arrays.asList("failed authorization!"));
fullHttpResponse.content().writeBytes(dataDocument.convertToJsonString().getBytes(StandardCharsets.UTF_8));
return fullHttpResponse;
}
dataDocument.append("success", true);
fullHttpResponse.content().writeBytes(dataDocument.convertToJsonString().getBytes(StandardCharsets.UTF_8));
return fullHttpResponse;
}
@Test
public void testDownloadFailsOnDigestMismatch() throws Exception {
// Test that the download fails when a blob/file has a different content hash than expected.
ServerChannel server = null;
try {
server =
testServer.start(
new SimpleChannelInboundHandler<FullHttpRequest>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
ByteBuf data = ctx.alloc().buffer();
ByteBufUtil.writeUtf8(data, "bar");
DefaultFullHttpResponse response =
new DefaultFullHttpResponse(
HttpVersion.HTTP_1_1, HttpResponseStatus.OK, data);
HttpUtil.setContentLength(response, data.readableBytes());
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
}
});
Credentials credentials = newCredentials();
HttpCacheClient blobStore =
createHttpBlobStore(
server, /* timeoutSeconds= */ 1, /* remoteVerifyDownloads= */ true, credentials);
Digest fooDigest = DIGEST_UTIL.compute("foo".getBytes(Charsets.UTF_8));
try (OutputStream out = new ByteArrayOutputStream()) {
IOException e =
assertThrows(
IOException.class, () -> getFromFuture(blobStore.downloadBlob(fooDigest, out)));
assertThat(e).hasMessageThat().contains(fooDigest.getHash());
assertThat(e).hasMessageThat().contains(DIGEST_UTIL.computeAsUtf8("bar").getHash());
}
} finally {
testServer.stop(server);
}
}