@Override
 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   logger.debug("================进入客户端InBoundHandler channelRead============");
   // 如果是response
   if (msg instanceof HttpResponse) {
     HttpResponse response = (HttpResponse) msg;
     logger.debug(
         "客户端收到的响应CONTENT_TYPE:" + response.headers().get(HttpHeaders.Names.CONTENT_TYPE));
     if (HttpHeaders.isContentLengthSet(response)) {
       reader = new ByteBufToBytes((int) HttpHeaders.getContentLength(response));
     }
   }
   if (msg instanceof HttpContent) {
     HttpContent httpContent = (HttpContent) msg;
     ByteBuf content = httpContent.content();
     reader.reading(content);
     content.release();
     if (reader.isEnd()) {
       String resultStr = new String(reader.readFull());
       logger.debug("收到的服务端的消息是:" + resultStr);
       ctx.close();
     }
   }
   logger.debug("================出客户端InBoundHandler channelRead============");
 }
 @Test
 public void clientRequestMultipleEmptyDataFrames() throws Exception {
   final String text = "";
   final ByteBuf content = Unpooled.copiedBuffer(text.getBytes());
   final FullHttpRequest request =
       new DefaultFullHttpRequest(
           HttpVersion.HTTP_1_1, HttpMethod.GET, "/some/path/resource2", content, true);
   try {
     HttpHeaders httpHeaders = request.headers();
     httpHeaders.set(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
     httpHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, text.length());
     final Http2Headers http2Headers =
         new DefaultHttp2Headers().method(as("GET")).path(as("/some/path/resource2"));
     runInChannel(
         clientChannel,
         new Http2Runnable() {
           @Override
           public void run() {
             frameWriter.writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
             frameWriter.writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient());
             frameWriter.writeData(ctxClient(), 3, content.retain(), 0, false, newPromiseClient());
             frameWriter.writeData(ctxClient(), 3, content.retain(), 0, true, newPromiseClient());
             ctxClient().flush();
           }
         });
     awaitRequests();
     ArgumentCaptor<FullHttpMessage> requestCaptor =
         ArgumentCaptor.forClass(FullHttpMessage.class);
     verify(serverListener).messageReceived(requestCaptor.capture());
     capturedRequests = requestCaptor.getAllValues();
     assertEquals(request, capturedRequests.get(0));
   } finally {
     request.release();
   }
 }
  @Test
  public void testLastResponseWithTrailingHeader() {
    EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder());
    ch.writeInbound(
        Unpooled.copiedBuffer(
            "HTTP/1.1 200 OK\r\n"
                + "Transfer-Encoding: chunked\r\n"
                + "\r\n"
                + "0\r\n"
                + "Set-Cookie: t1=t1v1\r\n"
                + "Set-Cookie: t2=t2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT\r\n"
                + "\r\n",
            CharsetUtil.US_ASCII));

    HttpResponse res = ch.readInbound();
    assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1));
    assertThat(res.getStatus(), is(HttpResponseStatus.OK));

    LastHttpContent lastContent = ch.readInbound();
    assertThat(lastContent.content().isReadable(), is(false));
    HttpHeaders headers = lastContent.trailingHeaders();
    assertEquals(1, headers.names().size());
    List<String> values = headers.getAll("Set-Cookie");
    assertEquals(2, values.size());
    assertTrue(values.contains("t1=t1v1"));
    assertTrue(values.contains("t2=t2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT"));
    lastContent.release();

    assertThat(ch.finish(), is(false));
    assertThat(ch.readInbound(), is(nullValue()));
  }
示例#4
0
  @Override
  public void send(final FileChannel channel) throws Exception {
    long len = channel.size();

    DefaultHttpResponse rsp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);
    if (!headers.contains(HttpHeaderNames.CONTENT_LENGTH)) {
      headers.remove(HttpHeaderNames.TRANSFER_ENCODING);
      headers.set(HttpHeaderNames.CONTENT_LENGTH, len);
    }

    if (keepAlive) {
      headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
    }

    // dump headers
    rsp.headers().set(headers);
    ChannelHandlerContext ctx = this.ctx;
    ctx.attr(NettyRequest.NEED_FLUSH).set(false);
    ctx.channel()
        .eventLoop()
        .execute(
            () -> {
              // send headers
              ctx.write(rsp);
              ctx.write(new DefaultFileRegion(channel, 0, len));
              keepAlive(ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT));
            });

    committed = true;
  }
  private boolean exitAfterHandler(
      Channel channel,
      NettyResponseFuture<?> future,
      HttpResponse response,
      AsyncHandler<?> handler,
      NettyResponseStatus status,
      HttpRequest httpRequest,
      HttpResponseHeaders responseHeaders)
      throws IOException, Exception {

    boolean exit =
        exitAfterHandlingStatus(channel, future, response, handler, status, httpRequest)
            || //
            exitAfterHandlingHeaders(
                channel, future, response, handler, responseHeaders, httpRequest)
            || //
            exitAfterHandlingReactiveStreams(channel, future, response, handler, httpRequest);

    if (exit)
      finishUpdate(
          future,
          channel,
          HttpHeaders.isTransferEncodingChunked(httpRequest)
              || HttpHeaders.isTransferEncodingChunked(response));

    return exit;
  }
示例#6
0
  private void send(final ByteBuf buffer) throws Exception {
    DefaultFullHttpResponse rsp = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buffer);

    if (!headers.contains(HttpHeaderNames.CONTENT_LENGTH)) {
      headers
          .remove(HttpHeaderNames.TRANSFER_ENCODING)
          .set(HttpHeaderNames.CONTENT_LENGTH, buffer.readableBytes());
    }

    if (keepAlive) {
      headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
    }

    // dump headers
    rsp.headers().set(headers);

    Attribute<Boolean> async = ctx.attr(NettyRequest.ASYNC);
    boolean isAsync = async != null && async.get() == Boolean.TRUE;
    if (isAsync) {
      // we need flush, from async
      keepAlive(ctx.writeAndFlush(rsp));
    } else {
      keepAlive(ctx.write(rsp));
    }

    committed = true;
  }
  @Test(groups = "online")
  public void asyncOptionsTest() throws Exception {
    final AtomicReference<HttpHeaders> responseHeaders = new AtomicReference<>();

    try (AsyncHttpClient c = asyncHttpClient()) {
      final String[] expected = {"GET", "HEAD", "OPTIONS", "POST", "TRACE"};
      Future<String> f =
          c.prepareOptions("http://www.apache.org/")
              .execute(
                  new AsyncHandlerAdapter() {

                    @Override
                    public State onHeadersReceived(HttpResponseHeaders content) throws Exception {
                      responseHeaders.set(content.getHeaders());
                      return State.ABORT;
                    }

                    @Override
                    public String onCompleted() throws Exception {
                      return "OK";
                    }
                  });

      f.get(20, TimeUnit.SECONDS);
      HttpHeaders h = responseHeaders.get();
      assertNotNull(h);
      String[] values = h.get(HttpHeaders.Names.ALLOW).split(",|, ");
      assertNotNull(values);
      assertEquals(values.length, expected.length);
      Arrays.sort(values);
      assertEquals(values, expected);
    }
  }
 /**
  * Sets the value of response headers after making sure that the response metadata is not already
  * sent.
  *
  * @param headerName The name of the header.
  * @param headerValue The intended value of the header.
  * @throws IllegalArgumentException if any of {@code headerName} or {@code headerValue} is null.
  * @throws IllegalStateException if response metadata has already been written to the channel.
  */
 private void setResponseHeader(String headerName, Object headerValue) {
   if (headerName != null && headerValue != null) {
     long startTime = System.currentTimeMillis();
     if (headerValue instanceof Date) {
       HttpHeaders.setDateHeader(responseMetadata, headerName, (Date) headerValue);
     } else {
       HttpHeaders.setHeader(responseMetadata, headerName, headerValue);
     }
     if (responseMetadataWritten.get()) {
       nettyMetrics.deadResponseAccessError.inc();
       throw new IllegalStateException(
           "Response metadata changed after it has already been written to the channel");
     } else {
       logger.trace(
           "Header {} set to {} for channel {}",
           headerName,
           responseMetadata.headers().get(headerName),
           ctx.channel());
       nettyMetrics.headerSetTimeInMs.update(System.currentTimeMillis() - startTime);
     }
   } else {
     throw new IllegalArgumentException(
         "Header name [" + headerName + "] or header value [" + headerValue + "] null");
   }
 }
  private void ntlmChallenge(
      String authenticateHeader, //
      Request request, //
      HttpHeaders headers, //
      Realm realm, //
      NettyResponseFuture<?> future) {

    if (authenticateHeader.equals("NTLM")) {
      // server replied bare NTLM => we didn't preemptively sent Type1Msg
      String challengeHeader = NtlmEngine.INSTANCE.generateType1Msg();
      // FIXME we might want to filter current NTLM and add (leave other
      // Authorization headers untouched)
      headers.set(HttpHeaders.Names.AUTHORIZATION, "NTLM " + challengeHeader);
      future.getInAuth().set(false);

    } else {
      String serverChallenge = authenticateHeader.substring("NTLM ".length()).trim();
      String challengeHeader =
          NtlmEngine.INSTANCE.generateType3Msg(
              realm.getPrincipal(),
              realm.getPassword(),
              realm.getNtlmDomain(),
              realm.getNtlmHost(),
              serverChallenge);
      // FIXME we might want to filter current NTLM and add (leave other
      // Authorization headers untouched)
      headers.set(HttpHeaders.Names.AUTHORIZATION, "NTLM " + challengeHeader);
    }
  }
示例#10
0
  private static FullHttpRequest createHttpRequest(int spdyVersion, SpdyHeaderBlock requestFrame)
      throws Exception {
    // Create the first line of the request from the name/value pairs
    HttpMethod method = SpdyHeaders.getMethod(spdyVersion, requestFrame);
    String url = SpdyHeaders.getUrl(spdyVersion, requestFrame);
    HttpVersion httpVersion = SpdyHeaders.getVersion(spdyVersion, requestFrame);
    SpdyHeaders.removeMethod(spdyVersion, requestFrame);
    SpdyHeaders.removeUrl(spdyVersion, requestFrame);
    SpdyHeaders.removeVersion(spdyVersion, requestFrame);

    FullHttpRequest req = new DefaultFullHttpRequest(httpVersion, method, url);

    // Remove the scheme header
    SpdyHeaders.removeScheme(spdyVersion, requestFrame);

    if (spdyVersion >= 3) {
      // Replace the SPDY host header with the HTTP host header
      String host = SpdyHeaders.getHost(requestFrame);
      SpdyHeaders.removeHost(requestFrame);
      HttpHeaders.setHost(req, host);
    }

    for (Map.Entry<String, String> e : requestFrame.headers().entries()) {
      req.headers().add(e.getKey(), e.getValue());
    }

    // The Connection and Keep-Alive headers are no longer valid
    HttpHeaders.setKeepAlive(req, true);

    // Transfer-Encoding header is not valid
    req.headers().remove(HttpHeaders.Names.TRANSFER_ENCODING);

    return req;
  }
示例#11
0
 /**
  * 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 (responseMetadataWritten.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. Note that sending HttpContent chunks data anyway - we are just
     // explicitly specifying
     // this in the header.
     if (!HttpHeaders.isContentLengthSet(responseMetadata)) {
       // This makes sure that we don't stomp on any existing transfer-encoding.
       HttpHeaders.setTransferEncodingChunked(responseMetadata);
     }
     logger.trace(
         "Sending response with status {} on channel {}",
         responseMetadata.getStatus(),
         ctx.channel());
     ChannelPromise writePromise = ctx.newPromise().addListener(listener);
     ctx.writeAndFlush(responseMetadata, writePromise);
     writtenThisTime = true;
     long writeProcessingTime = System.currentTimeMillis() - writeProcessingStartTime;
     nettyMetrics.responseMetadataProcessingTimeInMs.update(writeProcessingTime);
   }
   return writtenThisTime;
 }
示例#12
0
  private void handleChunk(
      HttpContent chunk, //
      final Channel channel, //
      final NettyResponseFuture<?> future, //
      AsyncHandler<?> handler)
      throws IOException, Exception {

    boolean interrupt = false;
    boolean last = chunk instanceof LastHttpContent;

    // Netty 4: the last chunk is not empty
    if (last) {
      LastHttpContent lastChunk = (LastHttpContent) chunk;
      HttpHeaders trailingHeaders = lastChunk.trailingHeaders();
      if (!trailingHeaders.isEmpty()) {
        interrupt =
            handler.onHeadersReceived(new HttpResponseHeaders(trailingHeaders, true))
                != State.CONTINUE;
      }
    }

    ByteBuf buf = chunk.content();
    if (!interrupt
        && !(handler instanceof StreamedAsyncHandler)
        && (buf.readableBytes() > 0 || last)) {
      HttpResponseBodyPart part =
          config.getResponseBodyPartFactory().newResponseBodyPart(buf, last);
      interrupt = updateBodyAndInterrupt(future, handler, part);
    }

    if (interrupt || last) finishUpdate(future, channel, !last);
  }
  private static void testLastResponseWithTrailingHeaderFragmented(
      byte[] content, int fragmentSize) {
    EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder());
    int headerLength = 47;
    // split up the header
    for (int a = 0; a < headerLength; ) {
      int amount = fragmentSize;
      if (a + amount > headerLength) {
        amount = headerLength - a;
      }

      // if header is done it should produce a HttpRequest
      boolean headerDone = a + amount == headerLength;
      assertEquals(headerDone, ch.writeInbound(Unpooled.wrappedBuffer(content, a, amount)));
      a += amount;
    }

    ch.writeInbound(Unpooled.wrappedBuffer(content, headerLength, content.length - headerLength));
    HttpResponse res = ch.readInbound();
    assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1));
    assertThat(res.getStatus(), is(HttpResponseStatus.OK));

    LastHttpContent lastContent = ch.readInbound();
    assertThat(lastContent.content().isReadable(), is(false));
    HttpHeaders headers = lastContent.trailingHeaders();
    assertEquals(1, headers.names().size());
    List<String> values = headers.getAll("Set-Cookie");
    assertEquals(2, values.size());
    assertTrue(values.contains("t1=t1v1"));
    assertTrue(values.contains("t2=t2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT"));
    lastContent.release();

    assertThat(ch.finish(), is(false));
    assertThat(ch.readInbound(), is(nullValue()));
  }
示例#14
0
  private void encodeChunkedContent(
      ChannelHandlerContext ctx, Object msg, int contentLength, List<Object> out) {
    if (contentLength > 0) {
      byte[] length = Integer.toHexString(contentLength).getBytes(CharsetUtil.US_ASCII);
      ByteBuf buf = ctx.alloc().buffer(length.length + 2);
      buf.writeBytes(length);
      buf.writeBytes(CRLF);
      out.add(buf);
      out.add(encodeAndRetain(msg));
      out.add(CRLF_BUF.duplicate());
    }

    if (msg instanceof LastHttpContent) {
      HttpHeaders headers = ((LastHttpContent) msg).trailingHeaders();
      if (headers.isEmpty()) {
        out.add(ZERO_CRLF_CRLF_BUF.duplicate());
      } else {
        ByteBuf buf = ctx.alloc().buffer();
        buf.writeBytes(ZERO_CRLF);
        HttpHeaders.encode(headers, buf);
        buf.writeBytes(CRLF);
        out.add(buf);
      }

      state = ST_INIT;
    } else {
      if (contentLength == 0) {
        // Need to produce some output otherwise an
        // IllegalstateException will be thrown
        out.add(EMPTY_BUFFER);
      }
    }
  }
示例#15
0
 /**
  * Verifies User metadata headers from output, to that sent in during input
  *
  * @param expectedHeaders the expected headers in the response.
  * @param response the {@link HttpResponse} which contains the headers of the response.
  * @param usermetadata if non-null, this is expected to come as the body.
  * @param content the content accompanying the response.
  */
 private void verifyUserMetadata(
     HttpHeaders expectedHeaders,
     HttpResponse response,
     byte[] usermetadata,
     Queue<HttpObject> content) {
   if (usermetadata == null) {
     assertEquals("Content-Length is not 0", 0, HttpHeaders.getContentLength(response));
     for (Map.Entry<String, String> header : expectedHeaders) {
       String key = header.getKey();
       if (key.startsWith(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX)) {
         assertEquals(
             "Value for " + key + " does not match in user metadata",
             header.getValue(),
             HttpHeaders.getHeader(response, key));
       }
     }
     for (Map.Entry<String, String> header : response.headers()) {
       String key = header.getKey();
       if (key.startsWith(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX)) {
         assertTrue(
             "Key " + key + " does not exist in expected headers", expectedHeaders.contains(key));
       }
     }
     discardContent(content, 1);
   } else {
     assertEquals(
         "Content-Length is not as expected",
         usermetadata.length,
         HttpHeaders.getContentLength(response));
     byte[] receivedMetadata = getContent(content, HttpHeaders.getContentLength(response)).array();
     assertArrayEquals("User metadata does not match original", usermetadata, receivedMetadata);
   }
 }
示例#16
0
  public void run() throws Exception {
    EventLoopGroup group = new NioEventLoopGroup();
    try {
      Bootstrap b = new Bootstrap();
      String protocol = uri.getScheme();
      if (!"ws".equals(protocol)) {
        throw new IllegalArgumentException("Unsupported protocol: " + protocol);
      }

      HttpHeaders customHeaders = new DefaultHttpHeaders();
      customHeaders.add("MyHeader", "MyValue");

      // Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
      // If you change it to V00, ping is not supported and remember to change
      // HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
      final WebSocketClientHandler handler =
          new WebSocketClientHandler(
              WebSocketClientHandshakerFactory.newHandshaker(
                  uri, WebSocketVersion.V13, null, false, customHeaders));

      b.group(group)
          .channel(NioSocketChannel.class)
          .handler(
              new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                  ChannelPipeline pipeline = ch.pipeline();
                  pipeline.addLast("http-codec", new HttpClientCodec());
                  pipeline.addLast("aggregator", new HttpObjectAggregator(8192));
                  pipeline.addLast("ws-handler", handler);
                }
              });

      System.out.println("WebSocket Client connecting");
      Channel ch = b.connect(uri.getHost(), uri.getPort()).sync().channel();
      handler.handshakeFuture().sync();

      // Send 10 messages and wait for responses
      System.out.println("WebSocket Client sending message");
      for (int i = 0; i < 10; i++) {
        ch.writeAndFlush(new TextWebSocketFrame("Message #" + i));
      }

      // Ping
      System.out.println("WebSocket Client sending ping");
      ch.writeAndFlush(
          new PingWebSocketFrame(Unpooled.copiedBuffer(new byte[] {1, 2, 3, 4, 5, 6})));

      // Close
      System.out.println("WebSocket Client sending close");
      ch.writeAndFlush(new CloseWebSocketFrame());

      // WebSocketClientHandler will close the connection when the server
      // responds to the CloseWebSocketFrame.
      ch.closeFuture().sync();
    } finally {
      group.shutdownGracefully();
    }
  }
示例#17
0
 protected void setCookie(FullHttpResponse response) {
   //		Set<Cookie> cookies = CookieDecoder.decode(MessageFormat.format(COOKIE, sessionId));
   Set<Cookie> cookies = CookieDecoder.decode(sessionId);
   HttpHeaders headers = response.headers();
   for (Cookie cookie : cookies) {
     headers.add(HttpHeaders.Names.SET_COOKIE, ServerCookieEncoder.encode(cookie));
   }
 }
示例#18
0
 /**
  * Gets the blob with blob ID {@code blobId} and verifies that the headers and content match with
  * what is expected.
  *
  * @param blobId the blob ID of the blob to GET.
  * @param range the {@link ByteRange} for the request.
  * @param expectedHeaders the expected headers in the response.
  * @param expectedContent the expected content of the blob.
  * @throws ExecutionException
  * @throws InterruptedException
  */
 private void getBlobAndVerify(
     String blobId, ByteRange range, HttpHeaders expectedHeaders, ByteBuffer expectedContent)
     throws ExecutionException, InterruptedException, RestServiceException {
   HttpHeaders headers = null;
   if (range != null) {
     headers =
         new DefaultHttpHeaders()
             .add(RestUtils.Headers.RANGE, RestTestUtils.getRangeHeaderString(range));
   }
   FullHttpRequest httpRequest = buildRequest(HttpMethod.GET, blobId, headers, null);
   Queue<HttpObject> responseParts = nettyClient.sendRequest(httpRequest, null, null).get();
   HttpResponse response = (HttpResponse) responseParts.poll();
   assertEquals(
       "Unexpected response status",
       range == null ? HttpResponseStatus.OK : HttpResponseStatus.PARTIAL_CONTENT,
       response.getStatus());
   checkCommonGetHeadHeaders(response.headers());
   assertEquals(
       "Content-Type does not match",
       expectedHeaders.get(RestUtils.Headers.AMBRY_CONTENT_TYPE),
       response.headers().get(HttpHeaders.Names.CONTENT_TYPE));
   assertEquals(
       RestUtils.Headers.BLOB_SIZE + " does not match",
       expectedHeaders.get(RestUtils.Headers.BLOB_SIZE),
       response.headers().get(RestUtils.Headers.BLOB_SIZE));
   assertEquals(
       "Accept-Ranges not set correctly",
       "bytes",
       response.headers().get(RestUtils.Headers.ACCEPT_RANGES));
   byte[] expectedContentArray = expectedContent.array();
   if (range != null) {
     long blobSize = Long.parseLong(expectedHeaders.get(RestUtils.Headers.BLOB_SIZE));
     assertEquals(
         "Content-Range header not set correctly",
         RestUtils.buildContentRangeAndLength(range, blobSize).getFirst(),
         response.headers().get(RestUtils.Headers.CONTENT_RANGE));
     ByteRange resolvedRange = range.toResolvedByteRange(blobSize);
     expectedContentArray =
         Arrays.copyOfRange(
             expectedContentArray,
             (int) resolvedRange.getStartOffset(),
             (int) resolvedRange.getEndOffset() + 1);
   } else {
     assertNull(
         "Content-Range header should not be set",
         response.headers().get(RestUtils.Headers.CONTENT_RANGE));
   }
   if (expectedContentArray.length < FRONTEND_CONFIG.frontendChunkedGetResponseThresholdInBytes) {
     assertEquals(
         "Content-length not as expected",
         expectedContentArray.length,
         HttpHeaders.getContentLength(response));
   }
   byte[] responseContentArray = getContent(responseParts, expectedContentArray.length).array();
   assertArrayEquals(
       "GET content does not match original content", expectedContentArray, responseContentArray);
   assertTrue("Channel should be active", HttpHeaders.isKeepAlive(response));
 }
示例#19
0
  public static void newHttpClientBootstrap(String url, ChannelHandler handler) throws Exception {
    URI uri = new URI(url);
    String scheme = uri.getScheme() == null ? "http" : uri.getScheme();
    String host = uri.getHost() == null ? "127.0.0.1" : uri.getHost();
    int port = uri.getPort();
    if (port == -1) {
      if ("http".equalsIgnoreCase(scheme)) {
        port = 80;
      } else if ("https".equalsIgnoreCase(scheme)) {
        port = 443;
      }
    }

    if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
      System.err.println("Only HTTP(S) is supported.");
      return;
    }

    // Configure SSL context if necessary.
    final boolean ssl = "https".equalsIgnoreCase(scheme);
    final SslContext sslCtx;
    if (ssl) {
      sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
    } else {
      sslCtx = null;
    }

    // Configure the client.
    EventLoopGroup group = new NioEventLoopGroup();
    try {
      Bootstrap b = new Bootstrap();
      b.group(group)
          .channel(NioSocketChannel.class)
          .handler(new HttpDownloadertInitializer(sslCtx, handler));
      // Make the connection attempt.
      Channel ch = b.connect(host, port).sync().channel();
      // Prepare the HTTP request.
      HttpRequest request =
          new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
      HttpHeaders headers = request.headers();
      headers.set(HttpHeaders.Names.HOST, host);
      headers.set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
      headers.set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
      // Set some example cookies.
      headers.set(
          HttpHeaders.Names.COOKIE,
          ClientCookieEncoder.encode(new DefaultCookie("my-cookie", "foo")));
      ch.writeAndFlush(request);
      // Wait for the server to close the connection.
      ch.closeFuture().sync();
      Thread.sleep(1000);
    } finally {
      // Shut down executor threads to exit.
      group.shutdownGracefully();
    }
  }
示例#20
0
  private void write(XHROptionsMessage msg, ChannelHandlerContext ctx, ChannelPromise promise) {
    HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.OK);

    HttpHeaders.addHeader(res, "Set-Cookie", "io=" + msg.getSessionId());
    HttpHeaders.addHeader(res, CONNECTION, KEEP_ALIVE);
    HttpHeaders.addHeader(res, ACCESS_CONTROL_ALLOW_HEADERS, CONTENT_TYPE);
    addOriginHeaders(ctx.channel(), res);

    ByteBuf out = encoder.allocateBuffer(ctx.alloc());
    sendMessage(msg, ctx.channel(), out, res, promise);
  }
示例#21
0
  @Override
  protected void channelRead0(ChannelHandlerContext ctx, FullHttpMessage msg)
      throws Exception { // 1
    // Request header 처리
    if (msg instanceof HttpRequest) { // 2
      this.request = (HttpRequest) msg; // 3

      if (HttpHeaders.is100ContinueExpected(request)) {
        send100Continue(ctx);
      }

      HttpHeaders headers = request.headers(); // 4
      if (!headers.isEmpty()) {
        for (Map.Entry<String, String> h : headers) {
          String key = h.getKey();
          if (usingHeader.contains(key)) { // 5
            reqData.put(key, h.getValue()); // 6
          }
        }
      }

      reqData.put("REQUEST_URI", request.getUri()); // 7
      reqData.put("REQUEST_METHOD", request.getMethod().name()); // 8
    }

    if (msg instanceof HttpContent) { // 9
      HttpContent httpContent = (HttpContent) msg; // 10

      ByteBuf content = httpContent.content(); // 11

      if (msg instanceof LastHttpContent) { // 12
        System.out.println("LastHttpContent message received!!" + request.getUri());

        LastHttpContent trailer = (LastHttpContent) msg;

        readPostData(); // 13

        ApiRequest service = ServiceDispatcher.dispatch(reqData); // 14

        try {
          service.executeService(); // 15

          apiResult = service.getApiResult(); // 16
        } finally {
          reqData.clear();
        }

        if (!writeResponse(trailer, ctx)) { // 17
          ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
        reset();
      }
    }
  }
示例#22
0
 /**
  * Verifies that a request returns the right response code once the blob has been deleted.
  *
  * @param httpRequest the {@link FullHttpRequest} to send to the server.
  * @param expectedStatusCode the expected {@link HttpResponseStatus}.
  * @throws ExecutionException
  * @throws InterruptedException
  */
 private void verifyDeleted(FullHttpRequest httpRequest, HttpResponseStatus expectedStatusCode)
     throws ExecutionException, InterruptedException {
   Queue<HttpObject> responseParts = nettyClient.sendRequest(httpRequest, null, null).get();
   HttpResponse response = (HttpResponse) responseParts.poll();
   assertEquals("Unexpected response status", expectedStatusCode, response.getStatus());
   assertTrue(
       "No Date header",
       HttpHeaders.getDateHeader(response, HttpHeaders.Names.DATE, null) != null);
   discardContent(responseParts, 1);
   assertTrue("Channel should be active", HttpHeaders.isKeepAlive(response));
 }
示例#23
0
 @Override
 protected void channelRead0(ChannelHandlerContext ctx, final Object msg) throws Exception {
   if (msg instanceof HttpMessage) {
     logger.debug("Adding no cache headers");
     HttpHeaders headers = ((HttpMessage) msg).headers();
     headers.set("Cache-Control", "no-cache, no-store, must-revalidate");
     headers.set("Pragma", "no-cache");
     headers.set("Expires", "0");
   }
   inboundChannel.writeAndFlush(msg);
 }
示例#24
0
  @Override
  public void send(final InputStream stream) throws Exception {
    byte[] chunk = new byte[bufferSize];
    int count = ByteStreams.read(stream, chunk, 0, bufferSize);
    if (count <= 0) {
      return;
    }
    ByteBuf buffer = Unpooled.wrappedBuffer(chunk, 0, count);
    if (count < bufferSize) {
      send(buffer);
    } else {
      DefaultHttpResponse rsp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);

      if (!headers.contains(HttpHeaderNames.CONTENT_LENGTH)) {
        headers.set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
      } else {
        if (keepAlive) {
          headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
        }
      }

      // dump headers
      rsp.headers().set(headers);
      ChannelHandlerContext ctx = this.ctx;
      ctx.attr(NettyRequest.NEED_FLUSH).set(false);

      // add chunker
      ChannelPipeline pipeline = ctx.pipeline();
      if (pipeline.get("chunker") == null) {
        pipeline.addAfter("encoder", "chunker", new ChunkedWriteHandler());
      }

      // group all write
      ctx.channel()
          .eventLoop()
          .execute(
              () -> {
                // send headers
                ctx.write(rsp);
                // send head chunk
                ctx.write(buffer);
                // send tail
                ctx.write(new ChunkedStream(stream, bufferSize));
                keepAlive(ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT));
              });
    }

    committed = true;
  }
  protected void processHeadRequest(
      ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) {

    if (_logger.isTraceEnabled()) {
      Channel channel = channelHandlerContext.channel();

      _logger.trace(
          "Client {}: processing head request {}", channel.remoteAddress(), fullHttpRequest.uri());
    }

    SyncFile syncFile = _getSyncFile(fullHttpRequest);

    if (syncFile == null) {
      _sendError(channelHandlerContext, NOT_FOUND);

      return;
    }

    String lanTokenKey = syncFile.getLanTokenKey();

    if ((lanTokenKey == null) || lanTokenKey.isEmpty()) {
      _sendError(channelHandlerContext, NOT_FOUND);

      return;
    }

    String encryptedToken = null;

    try {
      encryptedToken = LanTokenUtil.createEncryptedToken(lanTokenKey);
    } catch (Exception e) {
      _sendError(channelHandlerContext, NOT_FOUND);

      return;
    }

    HttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, OK);

    HttpHeaders httpHeaders = httpResponse.headers();

    httpHeaders.set("connectionsCount", _syncTrafficShapingHandler.getConnectionsCount());

    httpHeaders.set("downloadRate", _trafficCounter.lastWrittenBytes());
    httpHeaders.set("encryptedToken", encryptedToken);
    httpHeaders.set("maxConnections", PropsValues.SYNC_LAN_SERVER_MAX_CONNECTIONS);

    channelHandlerContext.writeAndFlush(httpResponse);
  }
示例#26
0
  public void sendError() {
    if (request == null
        || status == null
        || shortDescription == null
        || detailedDescription == null
        || version == null
        || status == null) throw new IllegalStateException();

    StringBuffer sb = new StringBuffer();
    sb.append("Error ").append(status.code()).append(": ").append(shortDescription);
    sb.append("\n\n");
    sb.append(detailedDescription);
    sb.append("\n\n");
    sb.append("Request:\n").append(request.getUri());
    sb.append("\n\n");
    sb.append("Request Submitted:\n").append(FdsnwsDate.toString(new Date()));
    sb.append("\n\n");
    sb.append("Service version:\n").append(version);
    String html = sb.toString();

    FullHttpResponse response =
        new DefaultFullHttpResponse(
            request.getProtocolVersion(),
            status,
            Unpooled.copiedBuffer(html, Charset.forName("UTF-8")));
    response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, html.length());
    response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8");

    if (HttpHeaders.isKeepAlive(request)) {
      response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
    }
    ctx.writeAndFlush(response);
  }
  private static void sendHttpResponse(
      ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {
    // Generate an error page if response getStatus code is not OK (200).
    if (res.getStatus().code() != 200) {
      ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8);
      res.content().writeBytes(buf);
      buf.release();
      HttpHeaders.setContentLength(res, res.content().readableBytes());
    }

    // Send the response and close the connection if necessary.
    ChannelFuture f = ctx.channel().writeAndFlush(res);
    if (!HttpHeaders.isKeepAlive(req) || res.getStatus().code() != 200) {
      f.addListener(ChannelFutureListener.CLOSE);
    }
  }
示例#28
0
 void encode(ByteBuf buf) {
   if (bytes == null) {
     HttpHeaders.encodeAscii0(name, buf);
   } else {
     buf.writeBytes(bytes);
   }
 }
  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder(getUrl());

    sb.append("\t");
    sb.append(method);
    sb.append("\theaders:");
    if (!headers.isEmpty()) {
      for (Map.Entry<String, String> header : headers) {
        sb.append("\t");
        sb.append(header.getKey());
        sb.append(":");
        sb.append(header.getValue());
      }
    }
    if (isNonEmpty(formParams)) {
      sb.append("\tformParams:");
      for (Param param : formParams) {
        sb.append("\t");
        sb.append(param.getName());
        sb.append(":");
        sb.append(param.getValue());
      }
    }

    return sb.toString();
  }
示例#30
0
 /**
  * Sets the value of the {@code "Connection"} header depending on the protocol version of the
  * specified message. This getMethod sets or removes the {@code "Connection"} header depending on
  * what the default keep alive mode of the message's protocol version is, as specified by {@link
  * HttpVersion#isKeepAliveDefault()}.
  *
  * <ul>
  *   <li>If the connection is kept alive by default:
  *       <ul>
  *         <li>set to {@code "close"} if {@code keepAlive} is {@code false}.
  *         <li>remove otherwise.
  *       </ul>
  *   <li>If the connection is closed by default:
  *       <ul>
  *         <li>set to {@code "keep-alive"} if {@code keepAlive} is {@code true}.
  *         <li>remove otherwise.
  *       </ul>
  * </ul>
  */
 public static void setKeepAlive(HttpMessage message, boolean keepAlive) {
   HttpHeaders h = message.headers();
   if (message.getProtocolVersion().isKeepAliveDefault()) {
     if (keepAlive) {
       h.remove(Names.CONNECTION);
     } else {
       h.set(Names.CONNECTION, Values.CLOSE);
     }
   } else {
     if (keepAlive) {
       h.set(Names.CONNECTION, Values.KEEP_ALIVE);
     } else {
       h.remove(Names.CONNECTION);
     }
   }
 }