@@ -96,17 +96,43 @@ public void handleRequest(HttpServletRequest request, HttpServletResponse respon
96
96
throws ServletException , IOException {
97
97
98
98
checkAndPrepare (request , response , true );
99
+
100
+ // check whether a matching resource exists
99
101
Resource resource = getResource (request );
100
102
if (resource == null ) {
103
+ logger .debug ("No matching resource found - returning 404" );
101
104
response .sendError (HttpServletResponse .SC_NOT_FOUND );
102
105
return ;
103
106
}
104
- setHeaders (resource , response );
105
- if (new ServletWebRequest (request , response ).checkNotModified (resource .lastModified ()) ||
106
- METHOD_HEAD .equals (request .getMethod ())) {
107
+
108
+ // check the resource's media type
109
+ MediaType mediaType = getMediaType (resource );
110
+ if (mediaType != null ) {
111
+ if (logger .isDebugEnabled ()) {
112
+ logger .debug ("Determined media type [" + mediaType + "] for " + resource );
113
+ }
114
+ }
115
+ else {
116
+ if (logger .isDebugEnabled ()) {
117
+ logger .debug ("No media type found for " + resource + " - returning 404" );
118
+ }
119
+ response .sendError (HttpServletResponse .SC_NOT_FOUND );
107
120
return ;
108
121
}
109
- writeContent (resource , response );
122
+
123
+ // header phase
124
+ setHeaders (response , resource , mediaType );
125
+ if (new ServletWebRequest (request , response ).checkNotModified (resource .lastModified ())) {
126
+ logger .debug ("Resource not modified - returning 304" );
127
+ return ;
128
+ }
129
+
130
+ // content phase
131
+ if (METHOD_HEAD .equals (request .getMethod ())) {
132
+ logger .trace ("HEAD request - skipping content" );
133
+ return ;
134
+ }
135
+ writeContent (response , resource );
110
136
}
111
137
112
138
protected Resource getResource (HttpServletRequest request ) {
@@ -115,42 +141,72 @@ protected Resource getResource(HttpServletRequest request) {
115
141
throw new IllegalStateException ("Required request attribute '" +
116
142
HandlerMapping .PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE + "' is not set" );
117
143
}
144
+
118
145
if (!StringUtils .hasText (path ) || path .contains ("WEB-INF" ) || path .contains ("META-INF" )) {
146
+ if (logger .isDebugEnabled ()) {
147
+ logger .debug ("Ignoring invalid resource path [" + path + "]" );
148
+ }
119
149
return null ;
120
150
}
121
- for (Resource resourcePath : this .locations ) {
151
+
152
+ for (Resource location : this .locations ) {
122
153
try {
123
- Resource resource = resourcePath .createRelative (path );
154
+ if (logger .isDebugEnabled ()) {
155
+ logger .debug ("Trying relative path [" + path + "] against base location: " + location );
156
+ }
157
+ Resource resource = location .createRelative (path );
124
158
if (resource .exists () && resource .isReadable ()) {
159
+ if (logger .isDebugEnabled ()) {
160
+ logger .debug ("Found matching resource: " + resource );
161
+ }
125
162
return resource ;
126
163
}
164
+ else if (logger .isTraceEnabled ()) {
165
+ logger .trace ("Relative resource doesn't exist or isn't readable: " + resource );
166
+ }
127
167
}
128
168
catch (IOException ex ) {
129
- // resource not found
130
- return null ;
169
+ logger .debug ("Failed to create relative resource - trying next resource location" , ex );
131
170
}
132
171
}
133
172
return null ;
134
173
}
135
174
136
- protected void setHeaders (Resource resource , HttpServletResponse response ) throws IOException {
137
- MediaType mediaType = getMediaType (resource );
138
- if (mediaType != null ) {
139
- response .setContentType (mediaType .toString ());
140
- }
175
+ /**
176
+ * Determine an appropriate media type for the given resource.
177
+ * @param resource the resource to check
178
+ * @return the corresponding media type, or <code>null</code> if none found
179
+ */
180
+ protected MediaType getMediaType (Resource resource ) {
181
+ String mimeType = getServletContext ().getMimeType (resource .getFilename ());
182
+ return (StringUtils .hasText (mimeType ) ? MediaType .parseMediaType (mimeType ) : null );
183
+ }
184
+
185
+ /**
186
+ * Set headers on the given servlet response.
187
+ * Called for GET requests as well as HEAD requests.
188
+ * @param response current servlet response
189
+ * @param resource the identified resource (never <code>null</code>)
190
+ * @param mediaType the resource's media type (never <code>null</code>)
191
+ * @throws IOException in case of errors while setting the headers
192
+ */
193
+ protected void setHeaders (HttpServletResponse response , Resource resource , MediaType mediaType ) throws IOException {
141
194
long length = resource .contentLength ();
142
195
if (length > Integer .MAX_VALUE ) {
143
196
throw new IOException ("Resource content too long (beyond Integer.MAX_VALUE): " + resource );
144
197
}
145
198
response .setContentLength ((int ) length );
199
+ response .setContentType (mediaType .toString ());
146
200
}
147
201
148
- protected MediaType getMediaType (Resource resource ) {
149
- String mimeType = getServletContext ().getMimeType (resource .getFilename ());
150
- return (StringUtils .hasText (mimeType ) ? MediaType .parseMediaType (mimeType ) : null );
151
- }
152
-
153
- protected void writeContent (Resource resource , HttpServletResponse response ) throws IOException {
202
+ /**
203
+ * Write the actual content out to the given servlet response,
204
+ * streaming the resource's content.
205
+ * @param response current servlet response
206
+ * @param resource the identified resource (never <code>null</code>)
207
+ * @throws IOException in case of errors while writing the content
208
+ */
209
+ protected void writeContent (HttpServletResponse response , Resource resource ) throws IOException {
154
210
FileCopyUtils .copy (resource .getInputStream (), response .getOutputStream ());
155
211
}
156
212
0 commit comments