1+ /*
2+ * JBoss, Home of Professional Open Source.
3+ * Copyright 2023 Red Hat, Inc., and individual contributors
4+ * as indicated by the @author tags.
5+ *
6+ * Licensed under the Apache License, Version 2.0 (the "License");
7+ * you may not use this file except in compliance with the License.
8+ * You may obtain a copy of the License at
9+ *
10+ * http://www.apache.org/licenses/LICENSE-2.0
11+ *
12+ * Unless required by applicable law or agreed to in writing, software
13+ * distributed under the License is distributed on an "AS IS" BASIS,
14+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ * See the License for the specific language governing permissions and
16+ * limitations under the License.
17+ */
18+ package io .undertow .server .handlers ;
19+
20+ import java .io .File ;
21+ import java .io .IOException ;
22+ import java .nio .file .Files ;
23+ import java .nio .file .Path ;
24+ import java .nio .file .attribute .FileAttribute ;
25+
26+ import org .apache .http .HttpResponse ;
27+ import org .apache .http .client .methods .HttpGet ;
28+ import org .apache .http .util .EntityUtils ;
29+ import org .junit .Assert ;
30+ import org .junit .Test ;
31+ import org .junit .runner .RunWith ;
32+
33+ import io .undertow .Handlers ;
34+ import io .undertow .server .HttpHandler ;
35+ import io .undertow .server .HttpServerExchange ;
36+ import io .undertow .server .handlers .builder .PredicatedHandlersParser ;
37+ import io .undertow .testutils .DefaultServer ;
38+ import io .undertow .testutils .TestHttpClient ;
39+ import io .undertow .util .StatusCodes ;
40+
41+ /**
42+ * Test basic resource serving via predicate handlers
43+ *
44+ * @author baranowb
45+ *
46+ */
47+ @ RunWith (DefaultServer .class )
48+ public class DirectoryListingEnablerTestCase {
49+
50+ private static final String DIR_PREFIXED = "prefix-resource-dir" ;
51+ private static final String FILE_NAME_LEVEL_0 = "file0" ;
52+ private static final String FILE_NAME_LEVEL_1 = "file1" ;
53+ private static final String DIR_SUB = "sub_dir" ;
54+ private static final String GIBBERISH = "Gibberish, what did you expect?" ;
55+
56+ private static final String TEST_PREFIX = "prefixToTest" ;
57+ private static final String HEADER_SWITCH = "SwitchHeader" ;
58+
59+ @ Test
60+ public void testEnableOnResource () throws IOException {
61+ final PathsRetainer pathsRetainer = createTestDir (DIR_PREFIXED , false );
62+ DefaultServer .setRootHandler (Handlers .predicates (
63+
64+ PredicatedHandlersParser .parse ("contains[value=%{i," +HEADER_SWITCH +"},search='enable'] -> { directory-listing(allow-listing=true)}"
65+ + "\n contains[value=%{i," +HEADER_SWITCH +"},search='disable'] -> { directory-listing(allow-listing=false)}" ,
66+ getClass ().getClassLoader ()),
67+ new HttpHandler () {
68+ @ Override
69+ public void handleRequest (HttpServerExchange exchange ) throws Exception {
70+ }
71+ }));
72+ testURLListing (pathsRetainer , false , false , StatusCodes .OK );
73+ testURLListing (pathsRetainer , true , false , StatusCodes .FORBIDDEN );
74+ testURLListing (pathsRetainer , true , true , StatusCodes .OK );
75+ }
76+
77+ @ Test
78+ public void testEnableWithoutResource () throws IOException {
79+ final PathsRetainer pathsRetainer = createTestDir (DIR_PREFIXED , false );
80+ DefaultServer .setRootHandler (Handlers .predicates (
81+
82+ PredicatedHandlersParser .parse ("contains[value=%{i," +HEADER_SWITCH +"},search='enable'] -> { directory-listing(allow-listing=true)}"
83+ + "\n contains[value=%{i," +HEADER_SWITCH +"},search='disable'] -> { directory-listing(allow-listing=false)}" +
84+ "\n path-prefix(/)-> { resource(location='" + pathsRetainer .root .toString () + "',allow-listing=false) }" ,
85+ getClass ().getClassLoader ()),
86+ new HttpHandler () {
87+ @ Override
88+ public void handleRequest (HttpServerExchange exchange ) throws Exception {
89+ }
90+ }));
91+ testURLListing (pathsRetainer , false , false , StatusCodes .FORBIDDEN );
92+ testURLListing (pathsRetainer , true , false , StatusCodes .FORBIDDEN );
93+ testURLListing (pathsRetainer , true , true , StatusCodes .OK );
94+ }
95+
96+ private void testURLListing (final PathsRetainer pathsRetainer , boolean includeHeader , boolean enable , int statusCode ) throws IOException {
97+
98+ try (TestHttpClient client = new TestHttpClient ();){
99+ HttpGet get = new HttpGet (DefaultServer .getDefaultServerURL () +"/" );
100+ if (includeHeader ) {
101+ if (enable ) {
102+ get .addHeader (HEADER_SWITCH , "enable" );
103+ } else {
104+ get .addHeader (HEADER_SWITCH , "disable" );
105+ }
106+ }
107+ HttpResponse result = client .execute (get );
108+ Assert .assertEquals (statusCode , result .getStatusLine ().getStatusCode ());
109+ if (statusCode != StatusCodes .OK ) {
110+ return ;
111+ }
112+ String bodyToTest = EntityUtils .toString (result .getEntity ());
113+ //this is not optimal...
114+ Assert .assertTrue (bodyToTest + "\n " + pathsRetainer .sub .getFileName (), bodyToTest .contains ("href='/" +pathsRetainer .sub .getFileName ()+"/'>" +pathsRetainer .sub .getFileName ()+"</a>" ));
115+ Assert .assertTrue (bodyToTest + "\n " + pathsRetainer .rootFile .getFileName (), bodyToTest .contains ("href='/" +pathsRetainer .rootFile .getFileName ()+"'>" +pathsRetainer .rootFile .getFileName ()+"</a>" ));
116+ }
117+ }
118+ private PathsRetainer createTestDir (final String dirName , final boolean prefixDirectory ) throws IOException {
119+ final FileAttribute <?>[] attribs = new FileAttribute <?>[] {};
120+ final PathsRetainer pathsRetainer = new PathsRetainer ();
121+ Path dir = Files .createTempDirectory (dirName );
122+ if (prefixDirectory ) {
123+ //dont use temp, as it will add random stuff
124+ //parent is already temp
125+ File f = dir .toFile ();
126+ f = new File (f ,TEST_PREFIX );
127+ Assert .assertTrue (f .mkdir ());
128+ pathsRetainer .root = dir ;
129+ dir = f .toPath ();
130+ } else {
131+ pathsRetainer .root = dir ;
132+ }
133+
134+ Path file = Files .createTempFile (dir , FILE_NAME_LEVEL_0 ,".txt" , attribs );
135+ pathsRetainer .rootFile = file ;
136+ writeGibberish (file );
137+ final Path subdir = Files .createTempDirectory (dir , DIR_SUB );
138+ pathsRetainer .sub = subdir ;
139+ file = Files .createTempFile (subdir , FILE_NAME_LEVEL_1 ,".txt" , attribs );
140+ pathsRetainer .subFile = file ;
141+ writeGibberish (file );
142+ return pathsRetainer ;
143+ }
144+
145+ private void writeGibberish (final Path p ) throws IOException {
146+ Files .write (p ,GIBBERISH .getBytes ());
147+ }
148+ private static class PathsRetainer {
149+ private Path root ;
150+ private Path rootFile ;
151+ private Path sub ;
152+ private Path subFile ;
153+ }
154+ }
0 commit comments