Customize connection in UrlResource getInputStream

Prior to this commit, the `AbstractFileResolvingResource` would
provide a default implementation for `customizeConnection` which only
sets the HTTP request method as "HEAD".
While this is consistent with its usage within that class (in
`exists()`, `contentLength()` or `lastModified()`), this is not opened
for general usage by sub-classes.

`UrlResource` is an example of that, where its `getInputStream()` method
does not call this customization method.

This not only prevents implementations from calling
`customizeConnection` in various cases, but it also misleads developers
as they might think that customizations will be applied automatically.

This commit ensures that `customizeConnection` is called in all relevant
places and that the configuration of the HTTP method is instead done in
each method as it is use case specific.

Fixes gh-28909
This commit is contained in:
Brian Clozel
2022-08-03 22:50:34 +02:00
parent 4eb8a5c082
commit 0caa2ac696
4 changed files with 339 additions and 223 deletions

View File

@@ -57,6 +57,7 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
HttpURLConnection httpCon =
(con instanceof HttpURLConnection ? (HttpURLConnection) con : null);
if (httpCon != null) {
httpCon.setRequestMethod("HEAD");
int code = httpCon.getResponseCode();
if (code == HttpURLConnection.HTTP_OK) {
return true;
@@ -108,6 +109,7 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
customizeConnection(con);
if (con instanceof HttpURLConnection) {
HttpURLConnection httpCon = (HttpURLConnection) con;
httpCon.setRequestMethod("HEAD");
int code = httpCon.getResponseCode();
if (code != HttpURLConnection.HTTP_OK) {
httpCon.disconnect();
@@ -245,6 +247,10 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
// Try a URL connection content-length header
URLConnection con = url.openConnection();
customizeConnection(con);
if (con instanceof HttpURLConnection) {
HttpURLConnection httpCon = (HttpURLConnection) con;
httpCon.setRequestMethod("HEAD");
}
return con.getContentLengthLong();
}
}
@@ -270,6 +276,10 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
// Try a URL connection last-modified header
URLConnection con = url.openConnection();
customizeConnection(con);
if (con instanceof HttpURLConnection) {
HttpURLConnection httpCon = (HttpURLConnection) con;
httpCon.setRequestMethod("HEAD");
}
long lastModified = con.getLastModified();
if (fileCheck && lastModified == 0 && con.getContentLengthLong() <= 0) {
throw new FileNotFoundException(getDescription() +
@@ -279,8 +289,7 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
}
/**
* Customize the given {@link URLConnection}, obtained in the course of an
* {@link #exists()}, {@link #contentLength()} or {@link #lastModified()} call.
* Customize the given {@link URLConnection} before fetching the resource.
* <p>Calls {@link ResourceUtils#useCachesIfNecessary(URLConnection)} and
* delegates to {@link #customizeConnection(HttpURLConnection)} if possible.
* Can be overridden in subclasses.
@@ -295,14 +304,12 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
}
/**
* Customize the given {@link HttpURLConnection}, obtained in the course of an
* {@link #exists()}, {@link #contentLength()} or {@link #lastModified()} call.
* <p>Sets request method "HEAD" by default. Can be overridden in subclasses.
* Customize the given {@link HttpURLConnection} before fetching the resource.
* <p>Can be overridden in subclasses for configuring request headers and timeouts.
* @param con the HttpURLConnection to customize
* @throws IOException if thrown from HttpURLConnection methods
*/
protected void customizeConnection(HttpURLConnection con) throws IOException {
con.setRequestMethod("HEAD");
}

View File

@@ -28,7 +28,6 @@ import java.net.URLConnection;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
/**
@@ -183,7 +182,7 @@ public class UrlResource extends AbstractFileResolvingResource {
@Override
public InputStream getInputStream() throws IOException {
URLConnection con = this.url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
customizeConnection(con);
try {
return con.getInputStream();
}