Java Code Examples for io.netty.handler.codec.http.HttpUtil#setTransferEncodingChunked()

The following examples show how to use io.netty.handler.codec.http.HttpUtil#setTransferEncodingChunked() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: HttpSender.java    From arcusplatform with Apache License 2.0 6 votes vote down vote up
public void sendChunkedHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {
	
       HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
       HttpUtil.setTransferEncodingChunked(response, true);
       response.headers().set(HttpHeaderNames.CONTENT_TYPE, res.headers().get(HttpHeaderNames.CONTENT_TYPE));

       if(HttpUtil.isKeepAlive(req)) {
          response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
       }

       ctx.write(response);
       ctx.write(new ChunkedStream(new ByteBufInputStream(res.content())));
       ChannelFuture future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
       if(!HttpUtil.isKeepAlive(req)) {
          future.addListener(ChannelFutureListener.CLOSE);
       }		
       metrics.incHTTPResponseCounter(className, res.status().code());
}
 
Example 2
Source File: HttpOperations.java    From reactor-netty with Apache License 2.0 6 votes vote down vote up
@Override
public final NettyOutbound sendFile(Path file, long position, long count) {
	Objects.requireNonNull(file);

	if (hasSentHeaders()) {
		return super.sendFile(file, position, count);
	}

	if (!HttpUtil.isTransferEncodingChunked(outboundHttpMessage()) && !HttpUtil.isContentLengthSet(
			outboundHttpMessage()) && count < Integer.MAX_VALUE) {
		outboundHttpMessage().headers()
		                     .setInt(HttpHeaderNames.CONTENT_LENGTH, (int) count);
	}
	else if (!HttpUtil.isContentLengthSet(outboundHttpMessage())) {
		outboundHttpMessage().headers()
		                     .remove(HttpHeaderNames.CONTENT_LENGTH)
		                     .remove(HttpHeaderNames.TRANSFER_ENCODING);
		HttpUtil.setTransferEncodingChunked(outboundHttpMessage(), true);
	}

	return super.sendFile(file, position, count);
}
 
Example 3
Source File: FrontendIntegrationTest.java    From ambry with Apache License 2.0 6 votes vote down vote up
/**
 * Method to easily create a request.
 * @param httpMethod the {@link HttpMethod} desired.
 * @param uri string representation of the desired URI.
 * @param headers any associated headers as a {@link HttpHeaders} object. Can be null.
 * @param content the content that accompanies the request. Can be null.
 * @return A {@link FullHttpRequest} object that defines the request required by the input.
 */
private FullHttpRequest buildRequest(HttpMethod httpMethod, String uri, HttpHeaders headers, ByteBuffer content) {
  ByteBuf contentBuf;
  if (content != null) {
    contentBuf = Unpooled.wrappedBuffer(content);
  } else {
    contentBuf = Unpooled.buffer(0);
  }
  FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, httpMethod, uri, contentBuf);
  if (headers != null) {
    httpRequest.headers().set(headers);
  }
  if (HttpMethod.POST.equals(httpMethod) && !HttpUtil.isContentLengthSet(httpRequest)) {
    HttpUtil.setTransferEncodingChunked(httpRequest, true);
  }
  return httpRequest;
}
 
Example 4
Source File: RESTHandler.java    From arcusplatform with Apache License 2.0 5 votes vote down vote up
protected FullHttpResponse response(HttpResponseStatus status, String contentType, String contents) {
	FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status,
			Unpooled.copiedBuffer(contents, CharsetUtil.UTF_8));
	if (restHandlerConfig.isSendChunked()) {
		HttpUtil.setTransferEncodingChunked(httpResponse, true);
	}
	httpResponse.headers().set(HttpHeaders.Names.CONTENT_TYPE, contentType);
	return httpResponse;
}
 
Example 5
Source File: HttpServerOperations.java    From reactor-netty with Apache License 2.0 5 votes vote down vote up
@Override
public HttpServerOperations chunkedTransfer(boolean chunked) {
	if (!hasSentHeaders() && HttpUtil.isTransferEncodingChunked(nettyResponse) != chunked) {
		responseHeaders.remove(HttpHeaderNames.TRANSFER_ENCODING);
		HttpUtil.setTransferEncodingChunked(nettyResponse, chunked);
	}
	return this;
}
 
Example 6
Source File: NettyResponseChannel.java    From ambry with Apache License 2.0 5 votes vote down vote up
/**
 * Writes response metadata to the channel if not already written previously and channel is active.
 * @param responseMetadata the {@link HttpResponse} that needs to be written.
 * @param listener the {@link GenericFutureListener} that needs to be attached to the write.
 * @return {@code true} if response metadata was written to the channel in this call. {@code false} otherwise.
 */
private boolean maybeWriteResponseMetadata(HttpResponse responseMetadata,
    GenericFutureListener<ChannelFuture> listener) {
  long writeProcessingStartTime = System.currentTimeMillis();
  boolean writtenThisTime = false;
  if (ctx.channel().isActive() && responseMetadataWriteInitiated.compareAndSet(false, true)) {
    // we do some manipulation here for chunking. According to the HTTP spec, we can have either a Content-Length
    // or Transfer-Encoding:chunked, never both. So we check for Content-Length - if it is not there, we add
    // Transfer-Encoding:chunked on 200 response. Note that sending HttpContent chunks data anyway - we are just
    // explicitly specifying this in the header.
    if (!HttpUtil.isContentLengthSet(responseMetadata) && (responseMetadata.status().equals(HttpResponseStatus.OK)
        || responseMetadata.status().equals(HttpResponseStatus.PARTIAL_CONTENT))) {
      // This makes sure that we don't stomp on any existing transfer-encoding.
      HttpUtil.setTransferEncodingChunked(responseMetadata, true);
    } else if (HttpUtil.isContentLengthSet(responseMetadata) && HttpUtil.getContentLength(responseMetadata) == 0
        && !(responseMetadata instanceof FullHttpResponse)) {
      // if the Content-Length is 0, we can send a FullHttpResponse since there is no content expected.
      FullHttpResponse fullHttpResponse =
          new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, responseMetadata.status());
      fullHttpResponse.headers().set(responseMetadata.headers());
      responseMetadata = fullHttpResponse;
    }
    logger.trace("Sending response with status {} on channel {}", responseMetadata.status(), ctx.channel());
    finalResponseMetadata = responseMetadata;
    ChannelPromise writePromise = ctx.newPromise().addListener(listener);
    ctx.writeAndFlush(responseMetadata, writePromise);
    writtenThisTime = true;
    long writeProcessingTime = System.currentTimeMillis() - writeProcessingStartTime;
    nettyMetrics.responseMetadataProcessingTimeInMs.update(writeProcessingTime);
    if (request != null) {
      request.getMetricsTracker().nioMetricsTracker.markFirstByteSent();
    }
  }
  return writtenThisTime;
}
 
Example 7
Source File: HttpPostRequestEncoder.java    From netty-4.1.22 with Apache License 2.0 4 votes vote down vote up
/**
 * Finalize the request by preparing the Header in the request and returns the request ready to be sent.<br>
 * Once finalized, no data must be added.<br>
 * If the request does not need chunk (isChunked() == false), this request is the only object to send to the remote
 * server.通过准备请求中的标头完成请求,并返回准备发送的请求。一旦确定,就不需要添加任何数据。如果请求不需要chunk (isChunked() == false),此请求是发送到远程服务器的唯一对象。
 *
 * @return the request object (chunked or not according to size of body)
 * @throws ErrorDataEncoderException
 *             if the encoding is in error or if the finalize were already done
 */
public HttpRequest finalizeRequest() throws ErrorDataEncoderException {
    // Finalize the multipartHttpDatas
    if (!headerFinalized) {
        if (isMultipart) {
            InternalAttribute internal = new InternalAttribute(charset);
            if (duringMixedMode) {
                internal.addValue("\r\n--" + multipartMixedBoundary + "--");
            }
            internal.addValue("\r\n--" + multipartDataBoundary + "--\r\n");
            multipartHttpDatas.add(internal);
            multipartMixedBoundary = null;
            currentFileUpload = null;
            duringMixedMode = false;
            globalBodySize += internal.size();
        }
        headerFinalized = true;
    } else {
        throw new ErrorDataEncoderException("Header already encoded");
    }

    HttpHeaders headers = request.headers();
    List<String> contentTypes = headers.getAll(HttpHeaderNames.CONTENT_TYPE);
    List<String> transferEncoding = headers.getAll(HttpHeaderNames.TRANSFER_ENCODING);
    if (contentTypes != null) {
        headers.remove(HttpHeaderNames.CONTENT_TYPE);
        for (String contentType : contentTypes) {
            // "multipart/form-data; boundary=--89421926422648"
            String lowercased = contentType.toLowerCase();
            if (lowercased.startsWith(HttpHeaderValues.MULTIPART_FORM_DATA.toString()) ||
                    lowercased.startsWith(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED.toString())) {
                // ignore
            } else {
                headers.add(HttpHeaderNames.CONTENT_TYPE, contentType);
            }
        }
    }
    if (isMultipart) {
        String value = HttpHeaderValues.MULTIPART_FORM_DATA + "; " + HttpHeaderValues.BOUNDARY + '='
                + multipartDataBoundary;
        headers.add(HttpHeaderNames.CONTENT_TYPE, value);
    } else {
        // Not multipart
        headers.add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED);
    }
    // Now consider size for chunk or not
    long realSize = globalBodySize;
    if (isMultipart) {
        iterator = multipartHttpDatas.listIterator();
    } else {
        realSize -= 1; // last '&' removed
        iterator = multipartHttpDatas.listIterator();
    }
    headers.set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(realSize));
    if (realSize > HttpPostBodyUtil.chunkSize || isMultipart) {
        isChunked = true;
        if (transferEncoding != null) {
            headers.remove(HttpHeaderNames.TRANSFER_ENCODING);
            for (CharSequence v : transferEncoding) {
                if (HttpHeaderValues.CHUNKED.contentEqualsIgnoreCase(v)) {
                    // ignore
                } else {
                    headers.add(HttpHeaderNames.TRANSFER_ENCODING, v);
                }
            }
        }
        HttpUtil.setTransferEncodingChunked(request, true);

        // wrap to hide the possible content
        return new WrappedHttpRequest(request);
    } else {
        // get the only one body and set it to the request
        HttpContent chunk = nextChunk();
        if (request instanceof FullHttpRequest) {
            FullHttpRequest fullRequest = (FullHttpRequest) request;
            ByteBuf chunkContent = chunk.content();
            if (fullRequest.content() != chunkContent) {
                fullRequest.content().clear().writeBytes(chunkContent);
                chunkContent.release();
            }
            return fullRequest;
        } else {
            return new WrappedFullHttpRequest(request, chunk);
        }
    }
}
 
Example 8
Source File: HttpClientOperations.java    From reactor-netty with Apache License 2.0 4 votes vote down vote up
public void chunkedTransfer(boolean chunked) {
	if (!hasSentHeaders() && HttpUtil.isTransferEncodingChunked(nettyRequest) != chunked) {
		requestHeaders.remove(HttpHeaderNames.TRANSFER_ENCODING);
		HttpUtil.setTransferEncodingChunked(nettyRequest, chunked);
	}
}
 
Example 9
Source File: HttpClientOperations.java    From reactor-netty with Apache License 2.0 4 votes vote down vote up
@SuppressWarnings("FutureReturnValueIgnored")
void _subscribe(CoreSubscriber<? super Void> s) {
	HttpDataFactory df = DEFAULT_FACTORY;

	try {
		HttpClientFormEncoder encoder = new HttpClientFormEncoder(df,
				parent.nettyRequest,
				false,
				HttpConstants.DEFAULT_CHARSET,
				HttpPostRequestEncoder.EncoderMode.RFC1738);

		formCallback.accept(parent, encoder);

		encoder = encoder.applyChanges(parent.nettyRequest);
		df = encoder.newFactory;

		if (!encoder.isMultipart()) {
			parent.requestHeaders.remove(HttpHeaderNames.TRANSFER_ENCODING);
		}

		// Returned value is deliberately ignored
		parent.addHandlerFirst(NettyPipeline.ChunkedWriter, new ChunkedWriteHandler());

		boolean chunked = HttpUtil.isTransferEncodingChunked(parent.nettyRequest);

		HttpRequest r = encoder.finalizeRequest();

		if (!chunked) {
			HttpUtil.setTransferEncodingChunked(r, false);
			HttpUtil.setContentLength(r, encoder.length());
		}

		ChannelFuture f = parent.channel()
		                        .writeAndFlush(r);

		Flux<Long> tail = encoder.progressFlux.onBackpressureLatest();

		if (encoder.cleanOnTerminate) {
			tail = tail.doOnCancel(encoder)
			           .doAfterTerminate(encoder);
		}

		if (encoder.isChunked()) {
			if (progressCallback != null) {
				progressCallback.accept(tail);
			}
			//"FutureReturnValueIgnored" this is deliberate
			parent.channel()
			      .writeAndFlush(encoder);
		}
		else {
			if (progressCallback != null) {
				progressCallback.accept(FutureMono.from(f)
				                                  .cast(Long.class)
				                                  .switchIfEmpty(Mono.just(encoder.length()))
				                                  .flux());
			}
		}
		s.onComplete();


	}
	catch (Throwable e) {
		Exceptions.throwIfJvmFatal(e);
		df.cleanRequestHttpData(parent.nettyRequest);
		s.onError(Exceptions.unwrap(e));
	}
}
 
Example 10
Source File: NettyResponseChannelTest.java    From ambry with Apache License 2.0 4 votes vote down vote up
/**
 * Does the keep-alive test by setting the {@link HttpHeaderNames#CONNECTION} to its two possible values and tests
 * that the response has the appropriate value for the {@link HttpHeaderNames#CONNECTION}.
 * @param channel the {@link EmbeddedChannel} to send the request over.
 * @param httpMethod the {@link HttpMethod} of the request.
 * @param errorCode the {@link RestServiceErrorCode} to induce at {@link MockNettyMessageProcessor}. {@code null} if
 *                  {@link TestingUri#OnResponseCompleteWithNonRestException} is desired.
 * @param expectedResponseStatus the expected {@link HttpResponseStatus} from remote.
 * @param contentSize the size of the content to attach with the request. No content attached if size is 0. If size >
 *                    1, then {@link HttpHeaderNames#TRANSFER_ENCODING} is set to {@link HttpHeaderValues#CHUNKED}.
 * @param keepAliveHint if {@code null}, no hint is added. If not {@code null}, hint is set to the given value
 * @return the {@link EmbeddedChannel} to use once this function is complete. If the channel did not close, this
 * function will return the {@code channel} instance that was passed, otherwise it returns a new channel.
 */
private EmbeddedChannel doKeepAliveTest(EmbeddedChannel channel, HttpMethod httpMethod,
    RestServiceErrorCode errorCode, HttpResponseStatus expectedResponseStatus, int contentSize,
    Boolean keepAliveHint) {
  boolean keepAlive = true;
  for (int i = 0; i < 2; i++) {
    HttpHeaders httpHeaders = new DefaultHttpHeaders();
    TestingUri uri = TestingUri.OnResponseCompleteWithNonRestException;
    if (errorCode != null) {
      uri = TestingUri.OnResponseCompleteWithRestException;
      httpHeaders.set(MockNettyMessageProcessor.REST_SERVICE_ERROR_CODE_HEADER_NAME, errorCode);
    }
    if (!keepAlive) {
      httpHeaders.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
    }
    if (keepAliveHint != null) {
      // this will get set in the NettyRequest when it is created
      httpHeaders.set(RestUtils.InternalKeys.KEEP_ALIVE_ON_ERROR_HINT, keepAliveHint);
    }
    byte[] content = null;
    if (contentSize > 0) {
      content = TestUtils.getRandomBytes(contentSize);
    }
    HttpRequest request = RestTestUtils.createFullRequest(httpMethod, uri.toString(), httpHeaders, content);
    if (contentSize > 1) {
      HttpUtil.setTransferEncodingChunked(request, true);
    } else {
      HttpUtil.setContentLength(request, contentSize);
    }
    channel.writeInbound(request);
    HttpResponse response = channel.readOutbound();
    assertEquals("Unexpected response status", expectedResponseStatus, response.status());
    if (!(response instanceof FullHttpResponse)) {
      // empty the channel
      while (channel.readOutbound() != null) {
      }
    }
    boolean shouldBeAlive = true;
    if (keepAliveHint != null) {
      shouldBeAlive = keepAliveHint;
    } else if (httpMethod.equals(HttpMethod.POST)) {
      shouldBeAlive = false;
    } else if (httpMethod.equals(HttpMethod.PUT)) {
      shouldBeAlive = contentSize == 0;
    }
    shouldBeAlive = shouldBeAlive && keepAlive && !NettyResponseChannel.CLOSE_CONNECTION_ERROR_STATUSES.contains(
        expectedResponseStatus);

    assertEquals("Channel state (open/close) not as expected", shouldBeAlive, channel.isActive());
    assertEquals("Connection header should be consistent with channel state", shouldBeAlive,
        HttpUtil.isKeepAlive(response));
    if (!shouldBeAlive) {
      channel.close();
      channel = createEmbeddedChannel();
    }
    keepAlive = !keepAlive;
  }
  return channel;
}