@Test
 public void shouldAddXContentTypeOptionsHeader() {
   HttpRequest httpRequest =
       new DefaultHttpRequest(
           HttpVersion.HTTP_1_1, HttpMethod.GET, "/foo?param1=bar&param2=baz&quux");
   httpRequest.addHeader("Host", "testing-host");
   Response response = new Response();
   postprocessor.process(new Request(httpRequest, null), response);
   assertTrue(response.hasHeaders());
   String result = response.getHeader(XCONTENTTYPEOPTIONS);
   assertNotNull(result);
   assertEquals(NOSNIFF, result);
 }
 /**
  * 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.
  *
  * @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();
       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");
   }
   List<String> contentTypes = request.getHeaders(HttpHeaders.Names.CONTENT_TYPE);
   List<String> transferEncoding = request.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
   if (contentTypes != null) {
     request.removeHeader(HttpHeaders.Names.CONTENT_TYPE);
     for (String contentType : contentTypes) {
       // "multipart/form-data; boundary=--89421926422648"
       if (contentType.toLowerCase().startsWith(HttpHeaders.Values.MULTIPART_FORM_DATA)) {
         // ignore
       } else if (contentType
           .toLowerCase()
           .startsWith(HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED)) {
         // ignore
       } else {
         request.addHeader(HttpHeaders.Names.CONTENT_TYPE, contentType);
       }
     }
   }
   if (isMultipart) {
     String value =
         HttpHeaders.Values.MULTIPART_FORM_DATA
             + "; "
             + HttpHeaders.Values.BOUNDARY
             + "="
             + multipartDataBoundary;
     request.addHeader(HttpHeaders.Names.CONTENT_TYPE, value);
   } else {
     // Not multipart
     request.addHeader(
         HttpHeaders.Names.CONTENT_TYPE, HttpHeaders.Values.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();
   }
   request.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(realSize));
   if (realSize > HttpPostBodyUtil.chunkSize) {
     isChunked = true;
     if (transferEncoding != null) {
       request.removeHeader(HttpHeaders.Names.TRANSFER_ENCODING);
       for (String v : transferEncoding) {
         if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
           // ignore
         } else {
           request.addHeader(HttpHeaders.Names.TRANSFER_ENCODING, v);
         }
       }
     }
     request.addHeader(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED);
     request.setContent(ChannelBuffers.EMPTY_BUFFER);
   } else {
     // get the only one body and set it to the request
     HttpChunk chunk = nextChunk();
     request.setContent(chunk.getContent());
   }
   return request;
 }
  /**
   * Sends the opening request to the server:
   *
   * <pre>
   * GET /demo HTTP/1.1
   * Upgrade: WebSocket
   * Connection: Upgrade
   * Host: example.com
   * Origin: http://example.com
   * Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5
   * Sec-WebSocket-Key2: 12998 5 Y3 1  .P00
   *
   * ^n:ds[4U
   * </pre>
   *
   * @param ctx Channel context
   * @param channel Channel into which we can write our request
   */
  @Override
  public void beginOpeningHandshake(ChannelHandlerContext ctx, Channel channel) {
    // Make keys
    int spaces1 = createRandomNumber(1, 12);
    int spaces2 = createRandomNumber(1, 12);

    int max1 = Integer.MAX_VALUE / spaces1;
    int max2 = Integer.MAX_VALUE / spaces2;

    int number1 = createRandomNumber(0, max1);
    int number2 = createRandomNumber(0, max2);

    int product1 = number1 * spaces1;
    int product2 = number2 * spaces2;

    String key1 = Integer.toString(product1);
    String key2 = Integer.toString(product2);

    key1 = insertRandomCharacters(key1);
    key2 = insertRandomCharacters(key2);

    key1 = insertSpaces(key1, spaces1);
    key2 = insertSpaces(key2, spaces2);

    byte[] key3 = createRandomBytes(8);

    ByteBuffer buffer = ByteBuffer.allocate(4);
    buffer.putInt(number1);
    byte[] number1Array = buffer.array();
    buffer = ByteBuffer.allocate(4);
    buffer.putInt(number2);
    byte[] number2Array = buffer.array();

    byte[] challenge = new byte[16];
    System.arraycopy(number1Array, 0, challenge, 0, 4);
    System.arraycopy(number2Array, 0, challenge, 4, 4);
    System.arraycopy(key3, 0, challenge, 8, 8);
    this.expectedChallengeResponseBytes = md5(challenge);

    // Get path
    URI wsURL = this.getWebSocketURL();
    String path = wsURL.getPath();
    if (wsURL.getQuery() != null && wsURL.getQuery().length() > 0) {
      path = wsURL.getPath() + "?" + wsURL.getQuery();
    }

    // Format request
    HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path);
    request.addHeader(Names.UPGRADE, Values.WEBSOCKET);
    request.addHeader(Names.CONNECTION, Values.UPGRADE);
    request.addHeader(Names.HOST, wsURL.getHost());
    request.addHeader(Names.ORIGIN, "http://" + wsURL.getHost());
    request.addHeader(Names.SEC_WEBSOCKET_KEY1, key1);
    request.addHeader(Names.SEC_WEBSOCKET_KEY2, key2);
    if (this.getSubProtocolRequest() != null && !this.getSubProtocolRequest().equals("")) {
      request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, this.getSubProtocolRequest());
    }
    request.setContent(ChannelBuffers.copiedBuffer(key3));

    channel.write(request);

    ctx.getPipeline().replace("encoder", "ws-encoder", new WebSocket00FrameEncoder());
  }