Skip to content

Commit a3add8b

Browse files
authored
Merge pull request #1205 from TBlueF/fix/pre-compressed-npe
[UNDERTOW-1950] Fix NullPointerException in PreCompressedResourceSupplier
2 parents 3c6f60d + 9cb4516 commit a3add8b

4 files changed

Lines changed: 118 additions & 12 deletions

File tree

core/src/main/java/io/undertow/server/handlers/resource/PreCompressedResourceSupplier.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,19 @@ public PreCompressedResourceSupplier(ResourceManager resourceManager) {
5454

5555
@Override
5656
public Resource getResource(HttpServerExchange exchange, String path) throws IOException {
57-
Resource originalResource = resourceManager.getResource(path);
5857
if(exchange.getRequestHeaders().contains(Headers.RANGE)) {
5958
//we don't use serve pre compressed resources for range requests
60-
return originalResource;
59+
return resourceManager.getResource(path);
6160
}
62-
Resource resource = getEncodedResource(exchange, path, originalResource);
61+
Resource resource = getEncodedResource(exchange, path);
6362
if(resource == null) {
64-
return originalResource;
63+
return resourceManager.getResource(path);
6564
}
6665
return resource;
6766
}
6867

6968

70-
private Resource getEncodedResource(final HttpServerExchange exchange, String path, Resource originalResource) throws IOException {
69+
private Resource getEncodedResource(final HttpServerExchange exchange, String path) throws IOException {
7170
final List<String> res = exchange.getRequestHeaders().get(Headers.ACCEPT_ENCODING);
7271
if (res == null || res.isEmpty()) {
7372
return null;
@@ -118,7 +117,13 @@ public List<Resource> list() {
118117

119118
@Override
120119
public String getContentType(MimeMappings mimeMappings) {
121-
return originalResource.getContentType(mimeMappings);
120+
String fileName = resource.getName();
121+
String originalFileName = fileName.substring(0, fileName.length() - extension.length());
122+
int index = originalFileName.lastIndexOf('.');
123+
if (index != -1 && index != originalFileName.length() - 1) {
124+
return mimeMappings.getMimeType(originalFileName.substring(index + 1));
125+
}
126+
return null;
122127
}
123128

124129
@Override

core/src/test/java/io/undertow/server/handlers/file/PreCompressedResourceTestCase.java

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,72 @@ public void testContentEncodedResource() throws IOException, URISyntaxException
102102
generatePreCompressedResource("gz");
103103

104104
//assert compressed response that was pre compressed
105-
assertResponse(compClient.execute(get), true, plainResponse, "gz");
105+
assertResponse(compClient.execute(get), true, plainResponse, "gz", "text/html");
106106

107107
} finally {
108108
client.getConnectionManager().shutdown();
109109
}
110110
}
111111

112+
@Test
113+
public void testContentEncodedJsonResource() throws IOException, URISyntaxException {
114+
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/path/data1.json");
115+
TestHttpClient client = new TestHttpClient();
116+
Path rootPath = Paths.get(getClass().getResource("data1.json").toURI()).getParent();
117+
118+
try (CloseableHttpClient compClient = HttpClientBuilder.create().build()){
119+
DefaultServer.setRootHandler(new CanonicalPathHandler()
120+
.setNext(new PathHandler()
121+
.addPrefixPath("/path", new ResourceHandler(new PreCompressedResourceSupplier(new PathResourceManager(rootPath, 10485760)).addEncoding("gzip", ".gz"))
122+
.setDirectoryListingEnabled(true))));
123+
124+
//assert response without compression
125+
final String plainResponse = assertResponse(client.execute(get), false, null, "web", "application/json");
126+
127+
//assert compressed response, that doesn't exists, so returns plain
128+
assertResponse(compClient.execute(get), false, plainResponse, "web", "application/json");
129+
130+
//generate compressed resource with extension .gz
131+
Path json = rootPath.resolve("data1.json");
132+
generateGZipFile(json, rootPath.resolve("data1.json.gz"));
133+
134+
//assert compressed response that was pre compressed
135+
assertResponse(compClient.execute(get), true, plainResponse, "gz", "application/json");
136+
137+
} finally {
138+
client.getConnectionManager().shutdown();
139+
}
140+
}
141+
142+
@Test
143+
public void testContentEncodedJsonResourceWithoutUncompressed() throws IOException, URISyntaxException {
144+
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/path/data3.json");
145+
TestHttpClient client = new TestHttpClient();
146+
Path rootPath = Paths.get(getClass().getResource("data2.json").toURI()).getParent();
147+
148+
try (CloseableHttpClient compClient = HttpClientBuilder.create().build()){
149+
DefaultServer.setRootHandler(new CanonicalPathHandler()
150+
.setNext(new PathHandler()
151+
.addPrefixPath("/path", new ResourceHandler(new PreCompressedResourceSupplier(new PathResourceManager(rootPath, 10485760)).addEncoding("gzip", ".gz"))
152+
.setDirectoryListingEnabled(true))));
153+
154+
//generate compressed resource with extension .gz and delete the uncompressed
155+
Path json = rootPath.resolve("data2.json");
156+
Path jsonFileToBeZippedAndDeleted = rootPath.resolve("data3.json");
157+
Files.copy(json, jsonFileToBeZippedAndDeleted);
158+
// data3.json.gz has no corresponding data3.json in the filesystem (UNDERTOW-1950)
159+
generateGZipFile(jsonFileToBeZippedAndDeleted, rootPath.resolve("data3.json.gz"));
160+
Files.delete(jsonFileToBeZippedAndDeleted);
161+
162+
//assert compressed response even with missing uncompressed
163+
assertResponse(compClient.execute(get), true, null, "gz", "application/json");
164+
165+
} finally {
166+
client.getConnectionManager().shutdown();
167+
}
168+
}
169+
170+
112171
@Test
113172
public void testCorrectResourceSelected() throws IOException, URISyntaxException {
114173
HttpGet get = new HttpGet(DefaultServer.getDefaultServerURL() + "/path/page.html");
@@ -136,7 +195,7 @@ public void testCorrectResourceSelected() throws IOException, URISyntaxException
136195
generatePreCompressedResource("gzip.nonsense");
137196

138197
//assert compressed response that was pre compressed
139-
assertResponse(compClient.execute(get), true, plainResponse, "gzip");
198+
assertResponse(compClient.execute(get), true, plainResponse, "gzip", "text/html");
140199

141200
} finally {
142201
client.getConnectionManager().shutdown();
@@ -166,21 +225,21 @@ private void replaceStringInFile(Path file, String original, String replacement)
166225
}
167226

168227
private String assertResponse(HttpResponse response, boolean encoding) throws IOException {
169-
return assertResponse(response, encoding, null, null);
228+
return assertResponse(response, encoding, null, null, "text/html");
170229
}
171230

172231
private String assertResponse(HttpResponse response, boolean encoding, String compareWith) throws IOException {
173-
return assertResponse(response, encoding, compareWith, "web");
232+
return assertResponse(response, encoding, compareWith, "web", "text/html");
174233
}
175234

176235
/**
177236
* Series of assertions checking response code, headers and response content
178237
*/
179-
private String assertResponse(HttpResponse response, boolean encoding, String compareWith, String extension) throws IOException {
238+
private String assertResponse(HttpResponse response, boolean encoding, String compareWith, String extension, String contentType) throws IOException {
180239
Assert.assertEquals(StatusCodes.OK, response.getStatusLine().getStatusCode());
181240
String body = HttpClientUtils.readResponse(response);
182241
Header[] headers = response.getHeaders(Headers.CONTENT_TYPE_STRING);
183-
Assert.assertEquals("text/html", headers[0].getValue());
242+
Assert.assertEquals(contentType, headers[0].getValue());
184243

185244
if (encoding) {
186245
assert response.getEntity() instanceof DecompressingEntity; //no other nice way to be sure we get back gzipped content
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"undertow": {
3+
"title": "compressed resource",
4+
"subtype": {
5+
"method": "test json compressed resource",
6+
"listInfo": {
7+
"test": {
8+
"json": "js",
9+
"compressed": "c",
10+
"resource": "this file",
11+
"type": "data",
12+
"def": {
13+
"thisFile": "Test purposes",
14+
"seeAlso": ["data2", "json"]
15+
},
16+
"See": "compression"
17+
}
18+
}
19+
}
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"undertow": {
3+
"title": "compressed resource",
4+
"subtype": {
5+
"method": "test json compressed resource",
6+
"listInfo": {
7+
"test": {
8+
"json": "js",
9+
"compressed": "c",
10+
"resource": "this file",
11+
"type": "data",
12+
"def": {
13+
"thisFile": "Test purposes",
14+
"seeAlso": ["data1", "json"]
15+
},
16+
"See": "compression"
17+
}
18+
}
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)