예제 #1
0
  @Override
  public void sendRedirect(String location) throws IOException {
    if (isIncluding()) return;

    if (location == null) throw new IllegalArgumentException();

    if (!URIUtil.hasScheme(location)) {
      StringBuilder buf = _channel.getRequest().getRootURL();
      if (location.startsWith("/")) buf.append(location);
      else {
        String path = _channel.getRequest().getRequestURI();
        String parent = (path.endsWith("/")) ? path : URIUtil.parentPath(path);
        location = URIUtil.addPaths(parent, location);
        if (location == null) throw new IllegalStateException("path cannot be above root");
        if (!location.startsWith("/")) buf.append('/');
        buf.append(location);
      }

      location = buf.toString();
      HttpURI uri = new HttpURI(location);
      String path = uri.getDecodedPath();
      String canonical = URIUtil.canonicalPath(path);
      if (canonical == null) throw new IllegalArgumentException();
      if (!canonical.equals(path)) {
        buf = _channel.getRequest().getRootURL();
        buf.append(URIUtil.encodePath(canonical));
        String param = uri.getParam();
        if (param != null) {
          buf.append(';');
          buf.append(param);
        }
        String query = uri.getQuery();
        if (query != null) {
          buf.append('?');
          buf.append(query);
        }
        String fragment = uri.getFragment();
        if (fragment != null) {
          buf.append('#');
          buf.append(fragment);
        }
        location = buf.toString();
      }
    }

    resetBuffer();
    setHeader(HttpHeader.LOCATION, location);
    setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
    complete();
  }
예제 #2
0
  /* ------------------------------------------------------------ */
  protected void handleRequest() throws IOException {
    boolean error = false;

    String threadName = null;
    try {
      if (LOG.isDebugEnabled()) {
        threadName = Thread.currentThread().getName();
        Thread.currentThread().setName(threadName + " - " + _uri);
      }

      // Loop here to handle async request redispatches.
      // The loop is controlled by the call to async.unhandle in the
      // finally block below.  If call is from a non-blocking connector,
      // then the unhandle will return false only if an async dispatch has
      // already happened when unhandle is called.   For a blocking connector,
      // the wait for the asynchronous dispatch or timeout actually happens
      // within the call to unhandle().

      final Server server = _server;
      boolean handling = _request._async.handling() && server != null && server.isRunning();
      while (handling) {
        _request.setHandled(false);

        String info = null;
        try {
          _uri.getPort();
          info = URIUtil.canonicalPath(_uri.getDecodedPath());
          if (info == null && !_request.getMethod().equals(HttpMethods.CONNECT))
            throw new HttpException(400);
          _request.setPathInfo(info);

          if (_out != null) _out.reopen();

          if (_request._async.isInitial()) {
            _request.setDispatcherType(DispatcherType.REQUEST);
            _connector.customize(_endp, _request);
            server.handle(this);
          } else {
            _request.setDispatcherType(DispatcherType.ASYNC);
            server.handleAsync(this);
          }
        } catch (ContinuationThrowable e) {
          LOG.ignore(e);
        } catch (EofException e) {
          LOG.debug(e);
          error = true;
          _request.setHandled(true);
        } catch (RuntimeIOException e) {
          LOG.debug(e);
          error = true;
          _request.setHandled(true);
        } catch (HttpException e) {
          LOG.debug(e);
          error = true;
          _request.setHandled(true);
          _response.sendError(e.getStatus(), e.getReason());
        } catch (Throwable e) {
          if (e instanceof ThreadDeath) throw (ThreadDeath) e;

          LOG.warn(String.valueOf(_uri), e);
          error = true;
          _request.setHandled(true);
          _generator.sendError(info == null ? 400 : 500, null, null, true);
        } finally {
          handling = !_request._async.unhandle() && server.isRunning() && _server != null;
        }
      }
    } finally {
      if (threadName != null) Thread.currentThread().setName(threadName);

      if (_request._async.isUncompleted()) {
        _request._async.doComplete();

        if (_expect100Continue) {
          LOG.debug("100 continues not sent");
          // We didn't send 100 continues, but the latest interpretation
          // of the spec (see httpbis) is that the client will either
          // send the body anyway, or close.  So we no longer need to
          // do anything special here other than make the connection not persistent
          _expect100Continue = false;
          if (!_response.isCommitted()) _generator.setPersistent(false);
        }

        if (_endp.isOpen()) {
          if (error) {
            _endp.shutdownOutput();
            _generator.setPersistent(false);
            if (!_generator.isComplete()) _response.complete();
          } else {
            if (!_response.isCommitted() && !_request.isHandled())
              _response.sendError(HttpServletResponse.SC_NOT_FOUND);
            _response.complete();
            if (_generator.isPersistent()) _connector.persist(_endp);
          }
        } else {
          _response.complete();
        }

        _request.setHandled(true);
      }
    }
  }
예제 #3
0
  @Override
  public void sendError(int code, String message) throws IOException {
    if (isIncluding()) return;

    if (isCommitted()) LOG.warn("Committed before " + code + " " + message);

    resetBuffer();
    _characterEncoding = null;
    setHeader(HttpHeader.EXPIRES, null);
    setHeader(HttpHeader.LAST_MODIFIED, null);
    setHeader(HttpHeader.CACHE_CONTROL, null);
    setHeader(HttpHeader.CONTENT_TYPE, null);
    setHeader(HttpHeader.CONTENT_LENGTH, null);

    _outputType = OutputType.NONE;
    setStatus(code);
    _reason = message;

    Request request = _channel.getRequest();
    Throwable cause = (Throwable) request.getAttribute(Dispatcher.ERROR_EXCEPTION);
    if (message == null) message = cause == null ? HttpStatus.getMessage(code) : cause.toString();

    // If we are allowed to have a body
    if (code != SC_NO_CONTENT
        && code != SC_NOT_MODIFIED
        && code != SC_PARTIAL_CONTENT
        && code >= SC_OK) {

      ErrorHandler error_handler = null;
      ContextHandler.Context context = request.getContext();
      if (context != null) error_handler = context.getContextHandler().getErrorHandler();
      if (error_handler == null) error_handler = _channel.getServer().getBean(ErrorHandler.class);
      if (error_handler != null) {
        request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, new Integer(code));
        request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
        request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
        request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, request.getServletName());
        error_handler.handle(null, _channel.getRequest(), _channel.getRequest(), this);
      } else {
        setHeader(HttpHeader.CACHE_CONTROL, "must-revalidate,no-cache,no-store");
        setContentType(MimeTypes.Type.TEXT_HTML_8859_1.toString());
        ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(2048);
        if (message != null) {
          message = StringUtil.replace(message, "&", "&");
          message = StringUtil.replace(message, "<", "&lt;");
          message = StringUtil.replace(message, ">", "&gt;");
        }
        String uri = request.getRequestURI();
        if (uri != null) {
          uri = StringUtil.replace(uri, "&", "&amp;");
          uri = StringUtil.replace(uri, "<", "&lt;");
          uri = StringUtil.replace(uri, ">", "&gt;");
        }

        writer.write(
            "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\"/>\n");
        writer.write("<title>Error ");
        writer.write(Integer.toString(code));
        writer.write(' ');
        if (message == null) writer.write(message);
        writer.write("</title>\n</head>\n<body>\n<h2>HTTP ERROR: ");
        writer.write(Integer.toString(code));
        writer.write("</h2>\n<p>Problem accessing ");
        writer.write(uri);
        writer.write(". Reason:\n<pre>    ");
        writer.write(message);
        writer.write("</pre>");
        writer.write("</p>\n<hr /><i><small>Powered by Jetty://</small></i>");
        writer.write("\n</body>\n</html>\n");

        writer.flush();
        setContentLength(writer.size());
        writer.writeTo(getOutputStream());
        writer.destroy();
      }
    } else if (code != SC_PARTIAL_CONTENT) {
      // TODO work out why this is required?
      _channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_TYPE);
      _channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_LENGTH);
      _characterEncoding = null;
      _mimeType = null;
    }

    complete();
  }