/**
   * Set the headers in the response object, excluding the Gzip header
   *
   * @param pageInfo
   * @param response
   */
  protected void setHeaders(final PageInfo pageInfo, final HttpServletResponse response) {

    Collection<Header<? extends Serializable>> headers = pageInfo.getHeaders();

    // Track which headers have been set so all headers of the same name
    // after the first are added
    TreeSet<String> setHeaders = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);

    for (Header<? extends Serializable> header : headers) {
      String name = header.getName();

      switch (header.getType()) {
        case STRING:
          if (setHeaders.contains(name)) {
            response.addHeader(name, (String) header.getValue());
          } else {
            setHeaders.add(name);
            response.setHeader(name, (String) header.getValue());
          }
          break;
        case DATE:
          if (setHeaders.contains(name)) {
            response.addDateHeader(name, (Long) header.getValue());
          } else {
            setHeaders.add(name);
            response.setDateHeader(name, (Long) header.getValue());
          }
          break;
        case INT:
          if (setHeaders.contains(name)) {
            response.addIntHeader(name, (Integer) header.getValue());
          } else {
            setHeaders.add(name);
            response.setIntHeader(name, (Integer) header.getValue());
          }
          break;
        default:
          throw new IllegalArgumentException("No mapping for Header: " + header);
      }
    }
  }
 @Override
 public void setIntHeader(String s, int i) {
   response.setIntHeader(s, i);
 }
Beispiel #3
0
  /** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */
  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    response.setContentType("xml");
    String fileName = "/file/data1.txt";
    String realPath = request.getRealPath(fileName);
    File file = new File(realPath);
    // TODO 如何判断文件是否被更新过
    //
    System.out.println("System.currentTimeMillis()" + System.currentTimeMillis());
    System.out.println("file.lastModified()" + file.lastModified());
    // boolean fileFlag=(new Date().getTime()-file.lastModified())>1000;
    boolean fileFlag = (System.currentTimeMillis() - file.lastModified()) > 1000 * 60 * 60 * 24L;

    System.out.println(fileFlag);
    if (fileFlag) {
      boolean flag = true;
      if (flag) {
        response.setIntHeader("Refresh", 5);
        flag = false;
      }
    }

    // 1.根据请求的数据格式dataType:xml或者json
    System.out.println(request.getPathInfo());
    if (request.getPathInfo() != null) {
      String dataType = request.getPathInfo().substring(1, request.getPathInfo().length());
      System.out.println(dataType);
      if ("xml".equals(dataType)) {
        StringBuilder sb = new StringBuilder();
        if (file.exists()) {
          FileReader reader = new FileReader(file);
          BufferedReader bufferReader = new BufferedReader(reader);
          String line = null;
          sb.append("<root>");
          while ((line = bufferReader.readLine()) != null) {
            sb.append("<child>");
            String[] strs = line.split(",");
            sb.append("<timestamp>").append(strs[0]).append("</timestamp>");
            sb.append("<monitorpoint>").append(strs[1]).append("</monitorpoint>");
            sb.append("<vehicles>").append(strs[2]).append("</vehicles>");
            sb.append("</child>");
          }
          sb.append("</root>");
          request.setAttribute("message1", sb.toString());
        } else {
          request.setAttribute("message", "请求错误");
        }
        // request.getRequestDispatcher("/index/core/message.jsp").forward(request, response);
        response.getWriter().write(sb.toString());
      } else { // json数据格式
        StringBuilder sb = new StringBuilder();
        if (file.exists()) {
          FileReader reader = new FileReader(file);
          BufferedReader bufferReader = new BufferedReader(reader);
          String line = null;
          sb.append("{\"trafficflow\":[");
          while ((line = bufferReader.readLine()) != null) {
            sb.append("{");
            String[] strs = line.split(",");
            sb.append("\"timestamp\":\"").append(strs[0]).append("\"");
            sb.append(",\"monitorpoint\":\"").append(strs[1]).append("\"");
            sb.append(",\"vehicles\":\"").append(strs[2]).append("\"");
            sb.append("},");
          }
          sb.append("]}");
          request.setAttribute("message1", sb.toString());
        } else {
          request.setAttribute("message", "请求错误");
        }
        // request.getRequestDispatcher("/index/core/message.jsp").forward(request, response);
        response.getWriter().write(sb.toString());
      }
    } else { // 显示普通数据

      StringBuilder sb = new StringBuilder();
      if (file.exists()) {
        FileReader reader = new FileReader(file);
        BufferedReader bufferReader = new BufferedReader(reader);
        String line = null;
        sb.append("时间戳,监测点,车流量<br>");
        while ((line = bufferReader.readLine()) != null) {
          sb.append(line + "<br>");
        }
        request.setAttribute("message", sb.toString());
      } else {
        request.setAttribute("message", "请求错误");
      }
      request.getRequestDispatcher("/index/core/message.jsp").forward(request, response);
    }
    // 2.读取文件Data1.txt中的数据根据类型返回相应的数据格式
    // 3.将读取到的文件内容以特定的格式响应到界面上
  }
Beispiel #4
0
 public void setIntHeader(String name, int value) {
   response.setIntHeader(name, value);
 }
Beispiel #5
0
  /**
   * Executes the {@link HttpMethod} passed in and sends the proxy response back to the client via
   * the given {@link HttpServletResponse}
   *
   * @param httpMethodProxyRequest An object representing the proxy request to be made
   * @param httpServletResponse An object by which we can send the proxied response back to the
   *     client
   * @throws IOException Can be thrown by the {@link HttpClient}.executeMethod
   * @throws ServletException Can be thrown to indicate that another error has occurred
   */
  private void executeProxyRequest(
      HttpMethod httpMethodProxyRequest,
      HttpServletRequest httpServletRequest,
      HttpServletResponse httpServletResponse)
      throws IOException, ServletException {
    // Create a default HttpClient
    HttpClient httpClient = new HttpClient();
    httpMethodProxyRequest.setFollowRedirects(false);
    // Execute the request
    int intProxyResponseCode = httpClient.executeMethod(httpMethodProxyRequest);

    // Check if the proxy response is a redirect
    // The following code is adapted from org.tigris.noodle.filters.CheckForRedirect
    // Hooray for open source software
    if (intProxyResponseCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */
        && intProxyResponseCode < HttpServletResponse.SC_NOT_MODIFIED /* 304 */) {
      String stringStatusCode = Integer.toString(intProxyResponseCode);
      String stringLocation =
          httpMethodProxyRequest.getResponseHeader(STRING_LOCATION_HEADER).getValue();
      if (stringLocation == null) {
        throw new ServletException(
            "Recieved status code: "
                + stringStatusCode
                + " but no "
                + STRING_LOCATION_HEADER
                + " header was found in the response");
      }
      // Modify the redirect to go to this proxy servlet rather that the proxied host
      String stringMyHostName = httpServletRequest.getServerName();
      if (httpServletRequest.getServerPort() != 80) {
        stringMyHostName += ":" + httpServletRequest.getServerPort();
      }
      stringMyHostName += httpServletRequest.getContextPath();
      httpServletResponse.sendRedirect(
          stringLocation.replace(getProxyHostAndPort() + this.getProxyPath(), stringMyHostName));
      return;
    } else if (intProxyResponseCode == HttpServletResponse.SC_NOT_MODIFIED) {
      // 304 needs special handling.  See:
      // http://www.ics.uci.edu/pub/ietf/http/rfc1945.html#Code304
      // We get a 304 whenever passed an 'If-Modified-Since'
      // header and the data on disk has not changed; server
      // responds w/ a 304 saying I'm not going to send the
      // body because the file has not changed.
      httpServletResponse.setIntHeader(STRING_CONTENT_LENGTH_HEADER_NAME, 0);
      httpServletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
      return;
    }

    // Pass the response code back to the client
    httpServletResponse.setStatus(intProxyResponseCode);

    // Pass response headers back to the client
    Header[] headerArrayResponse = httpMethodProxyRequest.getResponseHeaders();
    for (Header header : headerArrayResponse) {
      httpServletResponse.setHeader(header.getName(), header.getValue());
    }

    // Send the content to the client
    InputStream inputStreamProxyResponse = httpMethodProxyRequest.getResponseBodyAsStream();
    BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStreamProxyResponse);
    OutputStream outputStreamClientResponse = httpServletResponse.getOutputStream();
    int intNextByte;
    while ((intNextByte = bufferedInputStream.read()) != -1) {
      outputStreamClientResponse.write(intNextByte);
    }
  }
Beispiel #6
0
  /**
   * Process asynchronous update requests from the client.
   *
   * @since 3.0.0
   */
  protected void process(Session sess, HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    final String errClient = request.getHeader("ZK-Error-Report");
    if (errClient != null)
      if (log.debugable())
        log.debug("Error found at client: " + errClient + "\n" + Servlets.getDetail(request));

    // parse desktop ID
    final WebApp wapp = sess.getWebApp();
    final WebAppCtrl wappc = (WebAppCtrl) wapp;
    final AuDecoder audec = getAuDecoder(wapp);
    final String dtid = audec.getDesktopId(request);
    if (dtid == null) {
      // Bug 1929139: incomplete request (IE only)
      if (log.debugable()) {
        final String msg = "Incomplete request\n" + Servlets.getDetail(request);
        log.debug(msg);
      }

      response.sendError(467, "Incomplete request");
      return;
    }

    Desktop desktop = getDesktop(sess, dtid);
    if (desktop == null) {
      final String cmdId = audec.getFirstCommand(request);
      if (!"rmDesktop".equals(cmdId))
        desktop = recoverDesktop(sess, request, response, wappc, dtid);

      if (desktop == null) {
        response.setIntHeader("ZK-Error", response.SC_GONE); // denote timeout
        sessionTimeout(request, response, wapp, dtid);
        return;
      }
    }
    WebManager.setDesktop(request, desktop);
    // reason: a new page might be created (such as include)

    final String sid = request.getHeader("ZK-SID");
    if (sid != null) // Some client might not have ZK-SID
    response.setHeader("ZK-SID", sid);

    // parse commands
    final Configuration config = wapp.getConfiguration();
    final List aureqs;
    boolean keepAlive = false;
    try {
      final boolean timerKeepAlive = config.isTimerKeepAlive();
      aureqs = audec.decode(request, desktop);
      for (Iterator it = aureqs.iterator(); it.hasNext(); ) {
        final String cmdId = ((AuRequest) it.next()).getCommand();
        keepAlive = !(!timerKeepAlive && Events.ON_TIMER.equals(cmdId)) && !"dummy".equals(cmdId);
        // dummy is used for PollingServerPush for piggyback
        if (keepAlive) break; // done
      }
    } catch (Throwable ex) {
      log.warningBriefly(ex);
      responseError(request, response, Exceptions.getMessage(ex));
      return;
    }

    if (aureqs.isEmpty()) {
      final String errmsg = "Illegal request: cmd required";
      log.debug(errmsg);
      responseError(request, response, errmsg);
      return;
    }

    ((SessionCtrl) sess).notifyClientRequest(keepAlive);

    //		if (log.debugable()) log.debug("AU request: "+aureqs);
    final DesktopCtrl desktopCtrl = (DesktopCtrl) desktop;
    final Execution exec = new ExecutionImpl(getServletContext(), request, response, desktop, null);
    if (sid != null) ((ExecutionCtrl) exec).setRequestId(sid);

    final AuWriter out = AuWriters.newInstance();
    out.setCompress(_compress);
    out.open(
        request,
        response,
        desktop.getDevice().isSupported(Device.RESEND)
            ? getProcessTimeout(config.getResendDelay())
            : 0);
    // Note: getResendDelay() might return nonpositive
    try {
      wappc.getUiEngine().execUpdate(exec, aureqs, out);
    } catch (RequestOutOfSequenceException ex) {
      log.warning(ex.getMessage());
      response.setHeader("ZK-SID", sid);
      response.setIntHeader("ZK-Error", AuResponse.SC_OUT_OF_SEQUENCE);
    }
    out.close(request, response);
  }
Beispiel #7
0
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    final String pi = Https.getThisPathInfo(request);
    //		if (log.finerable()) log.finer("Path info: "+pi);

    final ServletContext ctx = getServletContext();
    final boolean withpi = pi != null && pi.length() != 0;
    if (withpi && pi.startsWith(ClassWebResource.PATH_PREFIX)) {
      // use HttpSession to avoid loading SerializableSession in GAE
      // and don't retrieve session if possible
      final ClassWebResource cwr = getClassWebResource();
      final HttpSession hsess = shallSession(cwr, pi) ? request.getSession(false) : null;
      Object oldsess = null;
      if (hsess == null) {
        oldsess = SessionsCtrl.getRawCurrent();
        SessionsCtrl.setCurrent(new SessionResolverImpl(ctx, request));
        // it might be created later
      }

      WebApp wapp;
      Session sess;
      final Object old =
          hsess != null
              ? (wapp = WebManager.getWebAppIfAny(ctx)) != null
                      && (sess = SessionsCtrl.getSession(wapp, hsess)) != null
                  ? I18Ns.setup(sess, request, response, "UTF-8")
                  : I18Ns.setup(hsess, request, response, "UTF-8")
              : Charsets.setup(null, request, response, "UTF-8");
      try {
        cwr.service(request, response, pi.substring(ClassWebResource.PATH_PREFIX.length()));
      } finally {
        if (hsess != null) I18Ns.cleanup(request, old);
        else {
          Charsets.cleanup(request, old);
          SessionsCtrl.setRawCurrent(oldsess);
        }
      }
      return; // done
    }

    final Session sess = WebManager.getSession(ctx, request, false);
    if (withpi) {
      final AuExtension aue = getAuExtensionByPath(pi);
      if (aue == null) {
        response.sendError(response.SC_NOT_FOUND);
        log.debug("Unknown path info: " + pi);
        return;
      }

      Object oldsess = null;
      if (sess == null) {
        oldsess = SessionsCtrl.getRawCurrent();
        SessionsCtrl.setCurrent(new SessionResolverImpl(ctx, request));
        // it might be created later
      }

      final Object old =
          sess != null
              ? I18Ns.setup(sess, request, response, "UTF-8")
              : Charsets.setup(null, request, response, "UTF-8");
      try {
        aue.service(request, response, pi);
      } finally {
        if (sess != null) I18Ns.cleanup(request, old);
        else {
          Charsets.cleanup(request, old);
          SessionsCtrl.setRawCurrent(oldsess);
        }
      }
      return; // done
    }

    // AU
    if (sess == null) {
      response.setIntHeader("ZK-Error", response.SC_GONE); // denote timeout

      // Bug 1849088: rmDesktop might be sent after invalidate
      // Bug 1859776: need send response to client for redirect or others
      final WebApp wapp = WebManager.getWebAppIfAny(ctx);
      final String dtid = getAuDecoder(wapp).getDesktopId(request);
      if (dtid != null) sessionTimeout(request, response, wapp, dtid);
      return;
    }

    // Feature 3285074 add no-cache for security risk.
    response.setHeader("Pragma", "no-cache");
    response.setHeader("Cache-Control", "no-cache");
    response.setHeader("Cache-Control", "no-store");
    response.setHeader("Expires", "-1");

    final Object old = I18Ns.setup(sess, request, response, "UTF-8");
    try {
      process(sess, request, response);
    } finally {
      I18Ns.cleanup(request, old);
    }
  }
  public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
      throws Exception {

    TransferStatus status = null;
    PlayQueueInputStream in = null;
    Player player = playerService.getPlayer(request, response, false, true);
    User user = securityService.getUserByName(player.getUsername());

    try {

      if (!user.isStreamRole()) {
        response.sendError(
            HttpServletResponse.SC_FORBIDDEN,
            "Streaming is forbidden for user " + user.getUsername());
        return null;
      }

      // If "playlist" request parameter is set, this is a Podcast request. In that case, create a
      // separate
      // play queue (in order to support multiple parallel Podcast streams).
      Integer playlistId = ServletRequestUtils.getIntParameter(request, "playlist");
      boolean isPodcast = playlistId != null;
      if (isPodcast) {
        PlayQueue playQueue = new PlayQueue();
        playQueue.addFiles(false, playlistService.getFilesInPlaylist(playlistId));
        player.setPlayQueue(playQueue);
        Util.setContentLength(response, playQueue.length());
        LOG.info("Incoming Podcast request for playlist " + playlistId);
      }

      String contentType = StringUtil.getMimeType(request.getParameter("suffix"));
      response.setContentType(contentType);

      String preferredTargetFormat = request.getParameter("format");
      Integer maxBitRate = ServletRequestUtils.getIntParameter(request, "maxBitRate");
      if (Integer.valueOf(0).equals(maxBitRate)) {
        maxBitRate = null;
      }

      VideoTranscodingSettings videoTranscodingSettings = null;

      // Is this a request for a single file (typically from the embedded Flash player)?
      // In that case, create a separate playlist (in order to support multiple parallel streams).
      // Also, enable partial download (HTTP byte range).
      MediaFile file = getSingleFile(request);
      boolean isSingleFile = file != null;
      LongRange range = null;

      if (isSingleFile) {
        PlayQueue playQueue = new PlayQueue();
        playQueue.addFiles(true, file);
        player.setPlayQueue(playQueue);

        if (!file.isVideo()) {
          response.setIntHeader("ETag", file.getId());
          //          response.setHeader("Accept-Ranges", "bytes");
        }

        TranscodingService.Parameters parameters =
            transcodingService.getParameters(
                file, player, maxBitRate, preferredTargetFormat, null, false);
        long fileLength = getFileLength(parameters);
        boolean isConversion = parameters.isDownsample() || parameters.isTranscode();
        boolean estimateContentLength =
            ServletRequestUtils.getBooleanParameter(request, "estimateContentLength", false);
        boolean isHls = ServletRequestUtils.getBooleanParameter(request, "hls", false);

        range = getRange(request, file);
        if (range != null) {
          LOG.info("Got range: " + range);

          //                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
          //                    Util.setContentLength(response, fileLength -
          // range.getMinimumLong());
          //                    long firstBytePos = range.getMinimumLong();
          //                    long lastBytePos = fileLength - 1;
          //                    response.setHeader("Content-Range", "bytes " + firstBytePos + "-" +
          // lastBytePos + "/" + fileLength);

          ///
          if (isConversion) {
            response.setHeader("Accept-Ranges", "none");
          } else {
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            long maxLength = fileLength;
            if (maxLength > range.getMaximumLong()) maxLength = range.getMaximumLong() + 1;
            Util.setContentLength(response, Math.max(maxLength - range.getMinimumLong(), 0));
            long firstBytePos = range.getMinimumLong();
            long lastBytePos = maxLength - 1;
            response.setHeader(
                "Content-Range", "bytes " + firstBytePos + "-" + lastBytePos + "/" + fileLength);
          }
          ///
        } else if (!isHls && (!isConversion || estimateContentLength)) {
          Util.setContentLength(response, fileLength);
        }

        if (isHls) {
          response.setContentType(StringUtil.getMimeType("ts")); // HLS is always MPEG TS.
        } else {
          String transcodedSuffix =
              transcodingService.getSuffix(player, file, preferredTargetFormat);
          response.setContentType(StringUtil.getMimeType(transcodedSuffix));
        }

        if (file.isVideo() || isHls) {
          videoTranscodingSettings = createVideoTranscodingSettings(file, request);
        }
      }

      if (request.getMethod().equals("HEAD")) {
        return null;
      }

      // Terminate any other streams to this player.
      if (!isPodcast && !isSingleFile) {
        for (TransferStatus streamStatus : statusService.getStreamStatusesForPlayer(player)) {
          if (streamStatus.isActive()) {
            streamStatus.terminate();
          }
        }
      }

      status = statusService.createStreamStatus(player);

      in =
          new PlayQueueInputStream(
              player,
              status,
              maxBitRate,
              preferredTargetFormat,
              videoTranscodingSettings,
              transcodingService,
              audioScrobblerService,
              mediaFileService,
              searchService);
      OutputStream out = RangeOutputStream.wrap(response.getOutputStream(), range);

      // Enabled SHOUTcast, if requested.
      boolean isShoutCastRequested = "1".equals(request.getHeader("icy-metadata"));
      if (isShoutCastRequested && !isSingleFile) {
        response.setHeader("icy-metaint", "" + ShoutCastOutputStream.META_DATA_INTERVAL);
        response.setHeader("icy-notice1", "This stream is served using FutureSonic");
        response.setHeader("icy-notice2", "FutureSonic - Free media streamer - sonic.lt");
        response.setHeader("icy-name", "FutureSonic");
        response.setHeader("icy-genre", "Mixed");
        response.setHeader("icy-url", "http://sonic.lt/");
        out = new ShoutCastOutputStream(out, player.getPlayQueue(), settingsService);
      }

      final int BUFFER_SIZE = 2048;
      byte[] buf = new byte[BUFFER_SIZE];

      while (true) {

        // Check if stream has been terminated.
        if (status.terminated()) {
          return null;
        }

        if (player.getPlayQueue().getStatus() == PlayQueue.Status.STOPPED) {
          if (isPodcast || isSingleFile) {
            break;
          } else {
            sendDummy(buf, out);
          }
        } else {

          int n = in.read(buf);
          if (n == -1) {
            if (isPodcast || isSingleFile) {
              break;
            } else {
              sendDummy(buf, out);
            }
          } else {
            out.write(buf, 0, n);
          }
        }
      }

    } finally {
      if (status != null) {
        securityService.updateUserByteCounts(user, status.getBytesTransfered(), 0L, 0L);
        statusService.removeStreamStatus(status);
      }
      IOUtils.closeQuietly(in);
    }
    return null;
  }
 public synchronized void setIntHeader(String arg0, int arg1) {
   actualResponse.setIntHeader(arg0, arg1);
 }
Beispiel #10
0
  /**
   * Executes the {@link HttpMethod} passed in and sends the proxy response back to the client via
   * the given {@link HttpServletResponse}.
   *
   * @param httpMethodProxyRequest An object representing the proxy request to be made
   * @param httpServletResponse An object by which we can send the proxied response back to the
   *     client
   * @throws IOException Can be thrown by the {@link HttpClient}.executeMethod
   * @throws ServletException Can be thrown to indicate that another error has occurred
   */
  private void executeProxyRequest(
      HttpMethod httpMethodProxyRequest,
      HttpServletRequest httpServletRequest,
      HttpServletResponse httpServletResponse)
      throws IOException, ServletException {
    // Create a default HttpClient
    HttpClient httpClient;
    httpClient = createClientWithLogin();
    httpMethodProxyRequest.setFollowRedirects(false);

    // Execute the request
    int intProxyResponseCode = httpClient.executeMethod(httpMethodProxyRequest);
    //        String response = httpMethodProxyRequest.getResponseBodyAsString();

    // Check if the proxy response is a redirect
    // The following code is adapted from org.tigris.noodle.filters.CheckForRedirect
    // Hooray for open source software
    if (intProxyResponseCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */
        && intProxyResponseCode < HttpServletResponse.SC_NOT_MODIFIED /* 304 */) {
      String stringStatusCode = Integer.toString(intProxyResponseCode);
      String stringLocation = httpMethodProxyRequest.getResponseHeader(HEADER_LOCATION).getValue();
      if (stringLocation == null) {
        throw new ServletException(
            "Received status code: "
                + stringStatusCode
                + " but no "
                + HEADER_LOCATION
                + " header was found in the response");
      }
      // Modify the redirect to go to this proxy servlet rather that the proxied host
      String stringMyHostName = httpServletRequest.getServerName();
      if (httpServletRequest.getServerPort() != 80) {
        stringMyHostName += ":" + httpServletRequest.getServerPort();
      }
      stringMyHostName += httpServletRequest.getContextPath();
      if (followRedirects) {
        httpServletResponse.sendRedirect(
            stringLocation.replace(getProxyHostAndPort() + proxyPath, stringMyHostName));
        return;
      }
    } else if (intProxyResponseCode == HttpServletResponse.SC_NOT_MODIFIED) {
      // 304 needs special handling. See:
      // http://www.ics.uci.edu/pub/ietf/http/rfc1945.html#Code304
      // We get a 304 whenever passed an 'If-Modified-Since'
      // header and the data on disk has not changed; server
      // responds w/ a 304 saying I'm not going to send the
      // body because the file has not changed.
      httpServletResponse.setIntHeader(HEADER_CONTENT_LENGTH, 0);
      httpServletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
      return;
    }

    // Pass the response code back to the client
    httpServletResponse.setStatus(intProxyResponseCode);

    // Pass response headers back to the client
    Header[] headerArrayResponse = httpMethodProxyRequest.getResponseHeaders();
    for (Header header : headerArrayResponse) {
      if (header.getName().equals("Transfer-Encoding") && header.getValue().equals("chunked")
          || header.getName().equals("Content-Encoding") && header.getValue().equals("gzip")) {
        // proxy servlet does not support chunked encoding
      } else {
        httpServletResponse.setHeader(header.getName(), header.getValue());
      }
    }

    List<Header> responseHeaders = Arrays.asList(headerArrayResponse);

    // FIXME We should handle both String and bytes response in the same way:
    String response = null;
    byte[] bodyBytes = null;

    if (isBodyParameterGzipped(responseHeaders)) {
      LOGGER.trace("GZipped: true");
      if (!followRedirects && intProxyResponseCode == HttpServletResponse.SC_MOVED_TEMPORARILY) {
        response = httpMethodProxyRequest.getResponseHeader(HEADER_LOCATION).getValue();
        httpServletResponse.setStatus(HttpServletResponse.SC_OK);
        intProxyResponseCode = HttpServletResponse.SC_OK;
        httpServletResponse.setHeader(HEADER_LOCATION, response);
        httpServletResponse.setContentLength(response.length());
      } else {
        bodyBytes = ungzip(httpMethodProxyRequest.getResponseBody());
        httpServletResponse.setContentLength(bodyBytes.length);
      }
    }

    if (httpServletResponse.getContentType() != null
        && httpServletResponse.getContentType().contains("text")) {
      LOGGER.trace("Received status code: {} Response: {}", intProxyResponseCode, response);
    } else {
      LOGGER.trace("Received status code: {} [Response is not textual]", intProxyResponseCode);
    }

    // Send the content to the client
    if (response != null) {
      httpServletResponse.getWriter().write(response);
    } else if (bodyBytes != null) {
      httpServletResponse.getOutputStream().write(bodyBytes);
    } else {
      IOUtils.copy(
          httpMethodProxyRequest.getResponseBodyAsStream(), httpServletResponse.getOutputStream());
    }
  }