Skip to content

Commit 492e51f

Browse files
committed
Add handling of deprecated API versions
See gh-35049
1 parent 0eec1dc commit 492e51f

File tree

25 files changed

+950
-19
lines changed

25 files changed

+950
-19
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2002-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.web.accept;
18+
19+
import jakarta.servlet.http.HttpServletRequest;
20+
import jakarta.servlet.http.HttpServletResponse;
21+
22+
/**
23+
* Contract to add handling of requests with a deprecated API version. Typically,
24+
* this involves use of response headers to send hints and information about
25+
* the deprecation to clients.
26+
*
27+
* @author Rossen Stoyanchev
28+
* @since 7.0
29+
* @see StandardApiDeprecationHandler
30+
*/
31+
public interface ApiDeprecationHandler {
32+
33+
/**
34+
* Check if the requested API version is deprecated, and if so handle it
35+
* accordingly, e.g. by setting response headers to signal the deprecation,
36+
* to specify relevant dates and provide links to further details.
37+
* @param version the resolved and parsed request version
38+
* @param request the current request
39+
* @param response the current response
40+
*/
41+
void handleVersion(Comparable<?> version, HttpServletRequest request, HttpServletResponse response);
42+
43+
}

spring-web/src/main/java/org/springframework/web/accept/ApiVersionStrategy.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.web.accept;
1818

1919
import jakarta.servlet.http.HttpServletRequest;
20+
import jakarta.servlet.http.HttpServletResponse;
2021
import org.jspecify.annotations.Nullable;
2122

2223
/**
@@ -25,13 +26,15 @@
2526
*
2627
* @author Rossen Stoyanchev
2728
* @since 7.0
29+
* @see DefaultApiVersionStrategy
2830
*/
2931
public interface ApiVersionStrategy {
3032

3133
/**
3234
* Resolve the version value from a request, e.g. from a request header.
3335
* @param request the current request
3436
* @return the version, if present or {@code null}
37+
* @see ApiVersionResolver
3538
*/
3639
@Nullable
3740
String resolveVersion(HttpServletRequest request);
@@ -40,6 +43,7 @@ public interface ApiVersionStrategy {
4043
* Parse the version of a request into an Object.
4144
* @param version the value to parse
4245
* @return an Object that represents the version
46+
* @see ApiVersionParser
4347
*/
4448
Comparable<?> parseVersion(String version);
4549

@@ -58,4 +62,15 @@ void validateVersion(@Nullable Comparable<?> requestVersion, HttpServletRequest
5862
*/
5963
@Nullable Comparable<?> getDefaultVersion();
6064

65+
/**
66+
* Check if the requested API version is deprecated, and if so handle it
67+
* accordingly, e.g. by setting response headers to signal the deprecation,
68+
* to specify relevant dates and provide links to further details.
69+
* @param version the resolved and parsed request version
70+
* @param request the current request
71+
* @param response the current response
72+
* @see ApiDeprecationHandler
73+
*/
74+
void handleDeprecations(Comparable<?> version, HttpServletRequest request, HttpServletResponse response);
75+
6176
}

spring-web/src/main/java/org/springframework/web/accept/DefaultApiVersionStrategy.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@
2222
import java.util.TreeSet;
2323

2424
import jakarta.servlet.http.HttpServletRequest;
25+
import jakarta.servlet.http.HttpServletResponse;
2526
import org.jspecify.annotations.Nullable;
2627

2728
import org.springframework.util.Assert;
2829

2930
/**
3031
* Default implementation of {@link ApiVersionStrategy} that delegates to the
31-
* configured version resolvers and version parser.
32+
* configured version resolvers, version parser, and deprecation handler.
3233
*
3334
* @author Rossen Stoyanchev
3435
* @since 7.0
@@ -43,6 +44,8 @@ public class DefaultApiVersionStrategy implements ApiVersionStrategy {
4344

4445
private final @Nullable Comparable<?> defaultVersion;
4546

47+
private final @Nullable ApiDeprecationHandler deprecationHandler;
48+
4649
private final Set<Comparable<?>> supportedVersions = new TreeSet<>();
4750

4851

@@ -56,10 +59,13 @@ public class DefaultApiVersionStrategy implements ApiVersionStrategy {
5659
* validation fails with {@link MissingApiVersionException}
5760
* @param defaultVersion a default version to assign to requests that
5861
* don't specify one
62+
* @param deprecationHandler handler to send hints and information about
63+
* deprecated API versions to clients
5964
*/
6065
public DefaultApiVersionStrategy(
6166
List<ApiVersionResolver> versionResolvers, ApiVersionParser<?> versionParser,
62-
boolean versionRequired, @Nullable String defaultVersion) {
67+
boolean versionRequired, @Nullable String defaultVersion,
68+
@Nullable ApiDeprecationHandler deprecationHandler) {
6369

6470
Assert.notEmpty(versionResolvers, "At least one ApiVersionResolver is required");
6571
Assert.notNull(versionParser, "ApiVersionParser is required");
@@ -68,6 +74,7 @@ public DefaultApiVersionStrategy(
6874
this.versionParser = versionParser;
6975
this.versionRequired = (versionRequired && defaultVersion == null);
7076
this.defaultVersion = (defaultVersion != null ? versionParser.parseVersion(defaultVersion) : null);
77+
this.deprecationHandler = deprecationHandler;
7178
}
7279

7380

@@ -120,6 +127,13 @@ public void validateVersion(@Nullable Comparable<?> requestVersion, HttpServletR
120127
}
121128
}
122129

130+
@Override
131+
public void handleDeprecations(Comparable<?> version, HttpServletRequest request, HttpServletResponse response) {
132+
if (this.deprecationHandler != null) {
133+
this.deprecationHandler.handleVersion(version, request, response);
134+
}
135+
}
136+
123137
@Override
124138
public String toString() {
125139
return "DefaultApiVersionStrategy[supportedVersions=" + this.supportedVersions +

0 commit comments

Comments
 (0)