Exemple #1
0
  /**
   * Get the resource list as a HTML directory listing.
   *
   * @param base The base URL
   * @param parent True if the parent directory should be included
   * @return String of HTML
   */
  public String getListHTML(String base, boolean parent) throws IOException {
    base = URIUtil.canonicalPath(base);
    if (base == null || !isDirectory()) return null;

    String[] ls = list();
    if (ls == null) return null;
    Arrays.sort(ls);

    String decodedBase = URIUtil.decodePath(base);
    String title = "Directory: " + deTag(decodedBase);

    StringBuilder buf = new StringBuilder(4096);
    buf.append("<HTML><HEAD>");
    buf.append("<LINK HREF=\"")
        .append("jetty-dir.css")
        .append("\" REL=\"stylesheet\" TYPE=\"text/css\"/><TITLE>");
    buf.append(title);
    buf.append("</TITLE></HEAD><BODY>\n<H1>");
    buf.append(title);
    buf.append("</H1>\n<TABLE BORDER=0>\n");

    if (parent) {
      buf.append("<TR><TD><A HREF=\"");
      buf.append(URIUtil.addPaths(base, "../"));
      buf.append("\">Parent Directory</A></TD><TD></TD><TD></TD></TR>\n");
    }

    String encodedBase = hrefEncodeURI(base);

    DateFormat dfmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
    for (int i = 0; i < ls.length; i++) {
      Resource item = addPath(ls[i]);

      buf.append("\n<TR><TD><A HREF=\"");
      String path = URIUtil.addPaths(encodedBase, URIUtil.encodePath(ls[i]));

      buf.append(path);

      if (item.isDirectory() && !path.endsWith("/")) buf.append(URIUtil.SLASH);

      // URIUtil.encodePath(buf,path);
      buf.append("\">");
      buf.append(deTag(ls[i]));
      buf.append("&nbsp;");
      buf.append("</A></TD><TD ALIGN=right>");
      buf.append(item.length());
      buf.append(" bytes&nbsp;</TD><TD>");
      buf.append(dfmt.format(new Date(item.lastModified())));
      buf.append("</TD></TR>");
    }
    buf.append("</TABLE>\n");
    buf.append("</BODY></HTML>\n");

    return buf.toString();
  }
Exemple #2
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();
  }
  @Override
  public Set<String> getResourcePaths(String path) {
    // Try to get regular resource paths
    Set<String> paths = super.getResourcePaths(path);

    // If no paths are returned check for virtual paths /WEB-INF/classes and /WEB-INF/lib
    if (paths.isEmpty() && path != null) {
      path = URIUtil.canonicalPath(path);
      if (path.startsWith(WEB_INF_LIB_PREFIX)) {
        paths = new TreeSet<String>();
        for (String fileName : webInfJarMap.keySet()) {
          // Return all jar files from class path
          paths.add(WEB_INF_LIB_PREFIX + "/" + fileName);
        }
      } else if (path.startsWith(WEB_INF_CLASSES_PREFIX)) {
        int i = 0;

        while (paths.isEmpty() && (i < webInfClasses.size())) {
          String newPath = path.replace(WEB_INF_CLASSES_PREFIX, webInfClasses.get(i).getPath());
          paths = super.getResourcePaths(newPath);
          i++;
        }
      }
    }
    return paths;
  }
  /* Handle a request from a connection.
   * Called to handle a request on the connection when either the header has been received,
   * or after the entire request has been received (for short requests of known length), or
   * on the dispatch of an async request.
   */
  public void handleAsync(AbstractHttpConnection connection) throws IOException, ServletException {
    final AsyncContinuation async = connection.getRequest().getAsyncContinuation();
    final AsyncContinuation.AsyncEventState state = async.getAsyncEventState();

    final Request baseRequest = connection.getRequest();
    final String path = state.getPath();

    if (path != null) {
      // this is a dispatch with a path
      final String contextPath = state.getServletContext().getContextPath();
      HttpURI uri = new HttpURI(URIUtil.addPaths(contextPath, path));
      baseRequest.setUri(uri);
      baseRequest.setRequestURI(null);
      baseRequest.setPathInfo(baseRequest.getRequestURI());
      if (uri.getQuery() != null) baseRequest.mergeQueryString(uri.getQuery());
    }

    final String target = baseRequest.getPathInfo();
    final HttpServletRequest request = (HttpServletRequest) async.getRequest();
    final HttpServletResponse response = (HttpServletResponse) async.getResponse();

    if (LOG.isDebugEnabled()) {
      LOG.debug("REQUEST " + target + " on " + connection);
      handle(target, baseRequest, request, response);
      LOG.debug("RESPONSE " + target + "  " + connection.getResponse().getStatus());
    } else handle(target, baseRequest, request, response);
  }
 private void handleOpenArticle(
     Request request, HttpServletResponse httpServletResponse, String target) throws Exception {
   try {
     int k1 = target.indexOf('/', 1);
     int k2 = target.indexOf('/', k1 + 1);
     String feedId = target.substring(k1 + 1, k2);
     String strSeq = target.substring(k2 + 1);
     int seq = Integer.parseInt(strSeq);
     Article article = articleDb.get(feedId, seq);
     LoginInfo loginInfo = userHelpers.getLoginInfo(request);
     // ttt2 using the link from a non-authenticated browser causes a NPE; maybe do something
     // better, e.g. sign up
     ReadArticlesColl readArticlesColl = readArticlesCollDb.get(loginInfo.userId, feedId);
     if (readArticlesColl == null) {
       readArticlesColl = new ReadArticlesColl(loginInfo.userId, feedId);
     }
     if (!readArticlesColl.isRead(seq)) {
       readArticlesColl.markRead(seq, Config.getConfig().maxSizeForReadArticles);
       readArticlesCollDb.add(readArticlesColl);
     }
     String s =
         URIUtil.encodePath(article.url)
             .replace("%3F", "?")
             .replace("%23", "#"); // ttt2 see how to do this right
     httpServletResponse.sendRedirect(s);
   } catch (Exception e) {
     WebUtils.showResult(
         String.format("Failed to get article for path %s. %s", target, e),
         "/",
         request,
         httpServletResponse);
   }
 }
  /* ------------------------------------------------------------ */
  @Override
  public void push() {
    if (HttpMethod.POST.is(_method) || HttpMethod.PUT.is(_method))
      throw new IllegalStateException("Bad Method " + _method);

    if (_path == null || _path.length() == 0) throw new IllegalStateException("Bad Path " + _path);

    String path = _path;
    String query = _queryString;
    int q = path.indexOf('?');
    if (q >= 0) {
      query =
          (query != null && query.length() > 0)
              ? (_path.substring(q + 1) + '&' + query)
              : _path.substring(q + 1);
      path = _path.substring(0, q);
    }

    if (!path.startsWith("/")) path = URIUtil.addPaths(_request.getContextPath(), path);

    String param = null;
    if (_sessionId != null) {
      if (_request.isRequestedSessionIdFromURL()) param = "jsessionid=" + _sessionId;
      // TODO else
      //      _fields.add("Cookie","JSESSIONID="+_sessionId);
    }

    if (_conditional) {
      if (_etag != null) _fields.add(HttpHeader.IF_NONE_MATCH, _etag);
      else if (_lastModified != null) _fields.add(HttpHeader.IF_MODIFIED_SINCE, _lastModified);
    }

    HttpURI uri =
        HttpURI.createHttpURI(
            _request.getScheme(),
            _request.getServerName(),
            _request.getServerPort(),
            _path,
            param,
            query,
            null);
    MetaData.Request push = new MetaData.Request(_method, uri, _request.getHttpVersion(), _fields);

    if (LOG.isDebugEnabled())
      LOG.debug(
          "Push {} {} inm={} ims={}",
          _method,
          uri,
          _fields.get(HttpHeader.IF_NONE_MATCH),
          _fields.get(HttpHeader.IF_MODIFIED_SINCE));

    _request.getHttpChannel().getHttpTransport().push(push);
    _path = null;
    _etag = null;
    _lastModified = null;
  }
  @Override
  public Resource getResource(String uriInContext) throws MalformedURLException {
    Resource resource = null;
    // Try to get regular resource
    resource = super.getResource(uriInContext);

    // If no regular resource exists check for access to /WEB-INF/lib or /WEB-INF/classes
    if ((resource == null || !resource.exists()) && uriInContext != null && _classes != null) {
      String uri = URIUtil.canonicalPath(uriInContext);
      if (uri == null) return null;

      try {
        // Replace /WEB-INF/classes with candidates for the classpath
        if (uri.startsWith(WEB_INF_CLASSES_PREFIX)) {
          if (uri.equalsIgnoreCase(WEB_INF_CLASSES_PREFIX)
              || uri.equalsIgnoreCase(WEB_INF_CLASSES_PREFIX + "/")) {
            // exact match for a WEB-INF/classes, so preferentially return the resource matching the
            // web-inf classes
            // rather than the test classes
            if (_classes != null) return Resource.newResource(_classes);
            else if (_testClasses != null) return Resource.newResource(_testClasses);
          } else {
            // try matching
            Resource res = null;
            int i = 0;
            while (res == null && (i < _webInfClasses.size())) {
              String newPath = uri.replace(WEB_INF_CLASSES_PREFIX, _webInfClasses.get(i).getPath());
              res = Resource.newResource(newPath);
              if (!res.exists()) {
                res = null;
                i++;
              }
            }
            return res;
          }
        } else if (uri.startsWith(WEB_INF_LIB_PREFIX)) {
          // Return the real jar file for all accesses to
          // /WEB-INF/lib/*.jar
          String jarName = uri.replace(WEB_INF_LIB_PREFIX, "");
          if (jarName.startsWith("/") || jarName.startsWith("\\")) jarName = jarName.substring(1);
          if (jarName.length() == 0) return null;
          File jarFile = _webInfJarMap.get(jarName);
          if (jarFile != null) return Resource.newResource(jarFile.getPath());

          return null;
        }
      } catch (MalformedURLException e) {
        throw e;
      } catch (IOException e) {
        LOG.ignore(e);
      }
    }
    return resource;
  }
  @Override
  public Resource getResource(String uriInContext) throws MalformedURLException {
    Resource resource = null;
    // Try to get regular resource
    //        replacer.getAutoconfigTempDirectory().getAbsolutePath()
    try {
      resource = getAutoconfigResource(uriInContext);
      if (resource == null) {
        //                resource = super.getResource(uriInContext);
        resource = getResourceFromMavenOrSuper(uriInContext);
      }
    } catch (Exception e) {
      logger.warn("find autoconfig resource error! " + uriInContext, e);
    }
    // If no regular resource exists check for access to /WEB-INF/lib or /WEB-INF/classes
    if ((resource == null || !resource.exists()) && uriInContext != null && webInfClasses != null) {
      String uri = URIUtil.canonicalPath(uriInContext);

      try {
        // Replace /WEB-INF/classes with real classes directory
        if (uri.startsWith(WEB_INF_CLASSES_PREFIX)) {
          Resource res = null;
          int i = 0;
          while (res == null && (i < webInfClasses.size())) {
            String newPath = uri.replace(WEB_INF_CLASSES_PREFIX, webInfClasses.get(i).getPath());
            res = Resource.newResource(newPath);
            if (!res.exists()) {
              res = null;
              i++;
            }
          }
          return res;
        }
        // Return the real jar file for all accesses to
        // /WEB-INF/lib/*.jar
        else if (uri.startsWith(WEB_INF_LIB_PREFIX)) {
          String jarName = uri.replace(WEB_INF_LIB_PREFIX, "");
          if (jarName.startsWith("/") || jarName.startsWith("\\")) jarName = jarName.substring(1);
          if (jarName.length() == 0) return null;
          File jarFile = webInfJarMap.get(jarName);
          if (jarFile != null) return Resource.newResource(jarFile.getPath());

          return null;
        }
      } catch (MalformedURLException e) {
        throw e;
      } catch (IOException e) {
        Log.ignore(e);
      }
    }
    return resource;
  }
  public String normalizePath(Path path) {
    for (PathAttribute attr : attributes) {
      if (attr.path == null) continue;

      try {
        if (path.startsWith(attr.path)
            || path.equals(attr.path)
            || Files.isSameFile(path, attr.path)) {
          return URIUtil.addPaths("${" + attr.key + "}", attr.path.relativize(path).toString());
        }
      } catch (IOException ignore) {
        LOG.ignore(ignore);
      }
    }

    return path.toString();
  }
  /** @param url The url with a war scheme */
  @Override
  public URLConnection openConnection(URL url) throws IOException {
    // remove the war scheme.
    URL actual = new URL(url.toString().substring("war:".length()));

    // let's do some basic tests: see if this is a folder or not.
    // if it is a folder. we will try to support it.
    if (actual.getProtocol().equals("file")) {
      File file = new File(URIUtil.encodePath(actual.getPath()));
      if (file.exists()) {
        if (file.isDirectory()) {
          // TODO (not mandatory for rfc66 though)
        }
      }
    }

    // if (actual.toString().startsWith("file:/") && ! actual.to)
    URLConnection ori = (URLConnection) actual.openConnection();
    ori.setDefaultUseCaches(Resource.getDefaultUseCaches());
    JarURLConnection jarOri = null;
    try {
      if (ori instanceof JarURLConnection) {
        jarOri = (JarURLConnection) ori;
      } else {
        jarOri = (JarURLConnection) new URL("jar:" + actual.toString() + "!/").openConnection();
        jarOri.setDefaultUseCaches(Resource.getDefaultUseCaches());
      }
      Manifest mf =
          WarBundleManifestGenerator.createBundleManifest(
              jarOri.getManifest(), url, jarOri.getJarFile());
      try {
        jarOri.getJarFile().close();
        jarOri = null;
      } catch (Throwable t) {
      }
      return new WarURLConnection(actual, mf);
    } finally {
      if (jarOri != null)
        try {
          jarOri.getJarFile().close();
        } catch (Throwable t) {
        }
    }
  }
Exemple #11
0
  @Override
  public boolean startRequest(
      HttpMethod httpMethod, String method, ByteBuffer uri, HttpVersion version) {
    _expect = false;
    _expect100Continue = false;
    _expect102Processing = false;

    if (_request.getTimeStamp() == 0) _request.setTimeStamp(System.currentTimeMillis());
    _request.setMethod(httpMethod, method);

    if (httpMethod == HttpMethod.CONNECT)
      _uri.parseConnect(uri.array(), uri.arrayOffset() + uri.position(), uri.remaining());
    else _uri.parse(uri.array(), uri.arrayOffset() + uri.position(), uri.remaining());
    _request.setUri(_uri);

    String path;
    try {
      path = _uri.getDecodedPath();
    } catch (Exception e) {
      LOG.warn("Failed UTF-8 decode for request path, trying ISO-8859-1");
      LOG.ignore(e);
      path = _uri.getDecodedPath(StandardCharsets.ISO_8859_1);
    }

    String info = URIUtil.canonicalPath(path);

    if (info == null) {
      if (path == null && _uri.getScheme() != null && _uri.getHost() != null) {
        info = "/";
        _request.setRequestURI("");
      } else {
        badMessage(400, null);
        return true;
      }
    }
    _request.setPathInfo(info);
    _version = version == null ? HttpVersion.HTTP_0_9 : version;
    _request.setHttpVersion(_version);

    return false;
  }
  public void stop(String test, int count, int of) throws IOException {
    System.err.println("Stop " + test + " " + count + " of " + of);
    String stop =
        "GET "
            + URIUtil.encodePath("/benchmark/stop/ " + test + " " + count + " of " + of)
            + " HTTP/1.1\r\n"
            + "Host: benchmarkControl:8080\r\n"
            + "Connection: close\r\n"
            + "\r\n";

    SocketChannel control = SocketChannel.open(new InetSocketAddress("localhost", 8080));
    control.write(BufferUtil.toBuffer(stop));
    while (control.isOpen()) {
      BufferUtil.clear(responseBuf);
      int pos = BufferUtil.flipToFill(responseBuf);
      if (control.read(responseBuf) == -1) control.close();
      BufferUtil.flipToFlush(responseBuf, pos);
    }

    for (int i = 0; i < client.length; i++)
      if (client[i] != null && client[i].isOpen()) client[i].close();
    client = null;
  }
  /**
   * Create a canonical name for a webapp temp directory. The form of the name is: <code>
   * "Jetty_"+host+"_"+port+"__"+resourceBase+"_"+context+"_"+virtualhost+base36_hashcode_of_whole_string
   * </code> host and port uniquely identify the server context and virtual host uniquely identify
   * the webapp
   *
   * @return the canonical name for the webapp temp directory
   */
  public static String getCanonicalNameForWebAppTmpDir(WebAppContext context) {
    StringBuffer canonicalName = new StringBuffer();
    canonicalName.append("jetty-");

    // get the host and the port from the first connector
    Server server = context.getServer();
    if (server != null) {
      Connector[] connectors = context.getServer().getConnectors();

      if (connectors.length > 0) {
        // Get the host
        String host = (connectors == null || connectors[0] == null ? "" : connectors[0].getHost());
        if (host == null) host = "0.0.0.0";
        canonicalName.append(host);

        // Get the port
        canonicalName.append("-");
        // try getting the real port being listened on
        int port = (connectors == null || connectors[0] == null ? 0 : connectors[0].getLocalPort());
        // if not available (eg no connectors or connector not started),
        // try getting one that was configured.
        if (port < 0) port = connectors[0].getPort();
        canonicalName.append(port);
        canonicalName.append("-");
      }
    }

    // Resource  base
    try {
      Resource resource = context.getBaseResource();
      if (resource == null) {
        if (context.getWar() == null || context.getWar().length() == 0)
          resource = context.newResource(context.getResourceBase());

        // Set dir or WAR
        resource = context.newResource(context.getWar());
      }

      String tmp = URIUtil.decodePath(resource.getURL().getPath());
      if (tmp.endsWith("/")) tmp = tmp.substring(0, tmp.length() - 1);
      if (tmp.endsWith("!")) tmp = tmp.substring(0, tmp.length() - 1);
      // get just the last part which is the filename
      int i = tmp.lastIndexOf("/");
      canonicalName.append(tmp.substring(i + 1, tmp.length()));
      canonicalName.append("-");
    } catch (Exception e) {
      LOG.warn("Can't generate resourceBase as part of webapp tmp dir name", e);
    }

    // Context name
    String contextPath = context.getContextPath();
    contextPath = contextPath.replace('/', '_');
    contextPath = contextPath.replace('\\', '_');
    canonicalName.append(contextPath);

    // Virtual host (if there is one)
    canonicalName.append("-");
    String[] vhosts = context.getVirtualHosts();
    if (vhosts == null || vhosts.length <= 0) canonicalName.append("any");
    else canonicalName.append(vhosts[0]);

    // sanitize
    for (int i = 0; i < canonicalName.length(); i++) {
      char c = canonicalName.charAt(i);
      if (!Character.isJavaIdentifierPart(c) && "-.".indexOf(c) < 0)
        canonicalName.setCharAt(i, '.');
    }

    canonicalName.append("-");
    return canonicalName.toString();
  }
  /* ------------------------------------------------------------ */
  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);
      }
    }
  }
Exemple #15
0
  @Override
  public String encodeURL(String url) {
    final Request request = _channel.getRequest();
    SessionManager sessionManager = request.getSessionManager();
    if (sessionManager == null) return url;

    HttpURI uri = null;
    if (sessionManager.isCheckingRemoteSessionIdEncoding() && URIUtil.hasScheme(url)) {
      uri = new HttpURI(url);
      String path = uri.getPath();
      path = (path == null ? "" : path);
      int port = uri.getPort();
      if (port < 0) port = HttpScheme.HTTPS.asString().equalsIgnoreCase(uri.getScheme()) ? 443 : 80;
      if (!request.getServerName().equalsIgnoreCase(uri.getHost())
          || request.getServerPort() != port
          || !path.startsWith(
              request
                  .getContextPath())) // TODO the root context path is "", with which every non null
                                      // string starts
      return url;
    }

    String sessionURLPrefix = sessionManager.getSessionIdPathParameterNamePrefix();
    if (sessionURLPrefix == null) return url;

    if (url == null) return null;

    // should not encode if cookies in evidence
    if (request.isRequestedSessionIdFromCookie()) {
      int prefix = url.indexOf(sessionURLPrefix);
      if (prefix != -1) {
        int suffix = url.indexOf("?", prefix);
        if (suffix < 0) suffix = url.indexOf("#", prefix);

        if (suffix <= prefix) return url.substring(0, prefix);
        return url.substring(0, prefix) + url.substring(suffix);
      }
      return url;
    }

    // get session;
    HttpSession session = request.getSession(false);

    // no session
    if (session == null) return url;

    // invalid session
    if (!sessionManager.isValid(session)) return url;

    String id = sessionManager.getNodeId(session);

    if (uri == null) uri = new HttpURI(url);

    // Already encoded
    int prefix = url.indexOf(sessionURLPrefix);
    if (prefix != -1) {
      int suffix = url.indexOf("?", prefix);
      if (suffix < 0) suffix = url.indexOf("#", prefix);

      if (suffix <= prefix) return url.substring(0, prefix + sessionURLPrefix.length()) + id;
      return url.substring(0, prefix + sessionURLPrefix.length()) + id + url.substring(suffix);
    }

    // edit the session
    int suffix = url.indexOf('?');
    if (suffix < 0) suffix = url.indexOf('#');
    if (suffix < 0) {
      return url
          + ((HttpScheme.HTTPS.is(uri.getScheme()) || HttpScheme.HTTP.is(uri.getScheme()))
                  && uri.getPath() == null
              ? "/"
              : "")
          + // if no path, insert the root path
          sessionURLPrefix
          + id;
    }

    return url.substring(0, suffix)
        + ((HttpScheme.HTTPS.is(uri.getScheme()) || HttpScheme.HTTP.is(uri.getScheme()))
                && uri.getPath() == null
            ? "/"
            : "")
        + // if no path so insert the root path
        sessionURLPrefix
        + id
        + url.substring(suffix);
  }