/** * 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(" "); buf.append("</A></TD><TD ALIGN=right>"); buf.append(item.length()); buf.append(" bytes </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(); }
@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) { } } }
@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); } } }
@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); }