Skip to content

Commit

Permalink
Undertow file servlet listing
Browse files Browse the repository at this point in the history
  • Loading branch information
melloware committed Apr 17, 2023
1 parent 6c7268b commit 4056c1b
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.quarkus.undertow.test;

import static org.hamcrest.Matchers.is;

import java.io.IOException;
import java.util.TreeSet;
import java.util.stream.Collectors;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class ResourceManagerTestCase {

private static final String CONTEXT_PATH = "/foo";
public static final String META_INF_RESOURCES = "META-INF/resources/";

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(ContextPathServlet.class)
.addAsResource(new StringAsset("index.html"), "META-INF/resources/index.html")
.addAsResource(new StringAsset("foo/foo.html"), "META-INF/resources/foo/foo.html")
.addAsResource(new StringAsset("foo/bar/bar.html"), "META-INF/resources/foo/bar/bar.html"));

@Test
public void testServlet() {
RestAssured.when().get("/").then()
.statusCode(200)
.body(is("[foo, index.html]"));
RestAssured.when().get("/foo").then()
.statusCode(200)
.body(is("[foo/bar, foo/foo.html]"));
RestAssured.when().get("/foo/bar").then()
.statusCode(200)
.body(is("[foo/bar/bar.html]"));
}

@WebServlet(urlPatterns = "/*")
public static class ContextPathServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
var paths = req.getServletContext().getResourcePaths(req.getPathInfo() == null ? "/" : req.getPathInfo());
resp.getWriter().write(String.valueOf(new TreeSet<>(
paths.stream().map(s -> s.substring(s.lastIndexOf(META_INF_RESOURCES) + META_INF_RESOURCES.length()))
.collect(Collectors.toSet()))));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.NavigableSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import io.undertow.httpcore.OutputChannel;
Expand All @@ -23,8 +25,10 @@

public class KnownPathResourceManager implements ResourceManager {

public static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows");

private final NavigableSet<String> files;
private final Set<String> directories;
private final NavigableSet<String> directories;
private final ResourceManager underlying;

public KnownPathResourceManager(Set<String> files, Set<String> directories, ResourceManager underlying) {
Expand All @@ -51,7 +55,7 @@ public KnownPathResourceManager(Set<String> files, Set<String> directories, Reso
tmp.add(i);
}
tmp.add("");
this.directories = Collections.unmodifiableSet(tmp);
this.directories = new TreeSet<>(tmp);
}

@Override
Expand All @@ -78,7 +82,11 @@ private class DirectoryResource implements Resource {
private final String path;

private DirectoryResource(String path) {
this.path = path;
this.path = evaluatePath(path);
}

private String evaluatePath(String path) {
return IS_WINDOWS ? path.replaceAll("\\\\", "/") : path;
}

@Override
Expand Down Expand Up @@ -118,18 +126,38 @@ public boolean isDirectory() {
@Override
public List<Resource> list() {
List<Resource> ret = new ArrayList<>();
String slashPath = path + "/";
for (String i : files.headSet(path)) {
if (i.startsWith(slashPath)) {
try {
ret.add(underlying.getResource(i));
} catch (IOException e) {
throw new RuntimeException(e);
String slashPath = path.isEmpty() ? path : path + "/";
if (IS_WINDOWS) {
slashPath = slashPath.replaceAll("/", "\\\\"); // correct Windows paths
}
SortedSet<String> fileSet = files.tailSet(slashPath);
SortedSet<String> dirSet = directories.tailSet(slashPath);

for (var s : List.of(fileSet, dirSet)) {
for (String i : s) {
if (i.equals(slashPath)) {
continue;
}
if (i.startsWith(slashPath)) {
i = evaluatePath(i);
if (!i.substring(slashPath.length()).contains("/")) {
try {
Resource resource = underlying.getResource(i);
if (resource == null) {
throw new RuntimeException("Unable to get listed resource " + i + " from directory " + path
+ " for path " + slashPath + " from underlying manager " + underlying);
}
ret.add(resource);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
} else {
break;
}
} else {
break;
}
}

return ret;
}

Expand Down Expand Up @@ -184,4 +212,4 @@ public URL getUrl() {
return null;
}
}
}
}

0 comments on commit 4056c1b

Please sign in to comment.