2828import org .elasticsearch .core .internal .io .Streams ;
2929import org .elasticsearch .http .HttpServerTransport ;
3030import org .elasticsearch .indices .breaker .CircuitBreakerService ;
31+ import org .elasticsearch .rest .RestHandler .Route ;
3132import org .elasticsearch .usage .UsageService ;
3233
3334import java .io .ByteArrayOutputStream ;
@@ -92,91 +93,117 @@ public RestController(Set<RestHeaderDefinition> headersToCopy, UnaryOperator<Res
9293 this .handlerWrapper = handlerWrapper ;
9394 this .client = client ;
9495 this .circuitBreakerService = circuitBreakerService ;
95- registerHandlerNoWrap (RestRequest .Method .GET , "/favicon.ico" , (request , channel , clnt ) ->
96+ registerHandlerNoWrap (RestRequest .Method .GET , "/favicon.ico" , RestApiVersion .current (),
97+ (request , channel , clnt ) ->
9698 channel .sendResponse (new BytesRestResponse (RestStatus .OK , "image/x-icon" , FAVICON_RESPONSE )));
9799 }
98100
99101 /**
100102 * Registers a REST handler to be executed when the provided {@code method} and {@code path} match the request.
101103 *
102104 * @param method GET, POST, etc.
103- * @param path Path to handle (e.g., "/{index}/{type}/_bulk")
105+ * @param path Path to handle (e.g. "/{index}/{type}/_bulk")
106+ * @param version API version to handle (e.g. RestApiVersion.V_8)
104107 * @param handler The handler to actually execute
105108 * @param deprecationMessage The message to log and send as a header in the response
106109 */
107- protected void registerAsDeprecatedHandler (RestRequest .Method method , String path , RestHandler handler , String deprecationMessage ) {
110+ protected void registerAsDeprecatedHandler (RestRequest .Method method , String path , RestApiVersion version ,
111+ RestHandler handler , String deprecationMessage ) {
108112 assert (handler instanceof DeprecationRestHandler ) == false ;
109-
110- registerHandler (method , path , new DeprecationRestHandler (handler , deprecationMessage , deprecationLogger ));
113+ if (version == RestApiVersion .current ()) {
114+ // e.g. it was marked as deprecated in 8.x, and we're currently running 8.x
115+ registerHandler (method , path , version , new DeprecationRestHandler (handler , deprecationMessage , deprecationLogger , false ));
116+ } else if (version == RestApiVersion .minimumSupported ()) {
117+ // e.g. it was marked as deprecated in 7.x, and we're currently running 8.x
118+ registerHandler (method , path , version , new DeprecationRestHandler (handler , deprecationMessage , deprecationLogger , true ));
119+ } else {
120+ // e.g. it was marked as deprecated in 7.x, and we're currently running *9.x*
121+ logger .debug ("Deprecated route [" + method + " " + path + "] for handler [" + handler .getClass () + "] " +
122+ "with version [" + version + "], which is less than the minimum supported version [" +
123+ RestApiVersion .minimumSupported () + "]" );
124+ }
111125 }
112126
113127 /**
114128 * Registers a REST handler to be executed when the provided {@code method} and {@code path} match the request, or when provided
115- * with {@code deprecatedMethod } and {@code deprecatedPath }. Expected usage:
129+ * with {@code replacedMethod } and {@code replacedPath }. Expected usage:
116130 * <pre><code>
117131 * // remove deprecation in next major release
118- * controller.registerWithDeprecatedHandler (POST, "/_forcemerge", this ,
119- * POST, "/_optimize", deprecationLogger );
120- * controller.registerWithDeprecatedHandler (POST, "/{index}/_forcemerge", this ,
121- * POST, "/{index}/_optimize", deprecationLogger );
132+ * controller.registerAsDeprecatedHandler (POST, "/_forcemerge", RestApiVersion.V_8, someHandler ,
133+ * POST, "/_optimize", RestApiVersion.V_7 );
134+ * controller.registerAsDeprecatedHandler (POST, "/{index}/_forcemerge", RestApiVersion.V_8, someHandler ,
135+ * POST, "/{index}/_optimize", RestApiVersion.V_7 );
122136 * </code></pre>
123137 * <p>
124138 * The registered REST handler ({@code method} with {@code path}) is a normal REST handler that is not deprecated and it is
125- * replacing the deprecated REST handler ({@code deprecatedMethod } with {@code deprecatedPath }) that is using the <em>same</em>
139+ * replacing the deprecated REST handler ({@code replacedMethod } with {@code replacedPath }) that is using the <em>same</em>
126140 * {@code handler}.
127141 * <p>
128142 * Deprecated REST handlers without a direct replacement should be deprecated directly using {@link #registerAsDeprecatedHandler}
129143 * and a specific message.
130144 *
131145 * @param method GET, POST, etc.
132- * @param path Path to handle (e.g., "/_forcemerge")
146+ * @param path Path to handle (e.g. "/_forcemerge")
147+ * @param version API version to handle (e.g. RestApiVersion.V_8)
133148 * @param handler The handler to actually execute
134- * @param deprecatedMethod GET, POST, etc.
135- * @param deprecatedPath <em>Deprecated</em> path to handle (e.g., "/_optimize")
149+ * @param replacedMethod GET, POST, etc.
150+ * @param replacedPath <em>Replaced</em> path to handle (e.g. "/_optimize")
151+ * @param replacedVersion <em>Replaced</em> API version to handle (e.g. RestApiVersion.V_7)
136152 */
137- protected void registerWithDeprecatedHandler (RestRequest .Method method , String path , RestHandler handler ,
138- RestRequest .Method deprecatedMethod , String deprecatedPath ) {
139- // e.g., [POST /_optimize] is deprecated! Use [POST /_forcemerge] instead.
140- final String deprecationMessage =
141- "[" + deprecatedMethod .name () + " " + deprecatedPath + "] is deprecated! Use [" + method .name () + " " + path + "] instead." ;
142-
143- registerHandler (method , path , handler );
144- registerAsDeprecatedHandler (deprecatedMethod , deprecatedPath , handler , deprecationMessage );
153+ protected void registerAsReplacedHandler (RestRequest .Method method , String path , RestApiVersion version , RestHandler handler ,
154+ RestRequest .Method replacedMethod , String replacedPath , RestApiVersion replacedVersion ) {
155+ // e.g. [POST /_optimize] is deprecated! Use [POST /_forcemerge] instead.
156+ final String replacedMessage =
157+ "[" + replacedMethod .name () + " " + replacedPath + "] is deprecated! Use [" + method .name () + " " + path + "] instead." ;
158+
159+ registerHandler (method , path , version , handler );
160+ registerAsDeprecatedHandler (replacedMethod , replacedPath , replacedVersion , handler , replacedMessage );
145161 }
146162
147163 /**
148164 * Registers a REST handler to be executed when one of the provided methods and path match the request.
149165 *
150- * @param path Path to handle (e.g., "/{index}/{type}/_bulk")
151- * @param handler The handler to actually execute
152166 * @param method GET, POST, etc.
167+ * @param path Path to handle (e.g. "/{index}/{type}/_bulk")
168+ * @param version API version to handle (e.g. RestApiVersion.V_8)
169+ * @param handler The handler to actually execute
153170 */
154- protected void registerHandler (RestRequest .Method method , String path , RestHandler handler ) {
171+ protected void registerHandler (RestRequest .Method method , String path , RestApiVersion version , RestHandler handler ) {
155172 if (handler instanceof BaseRestHandler ) {
156173 usageService .addRestHandler ((BaseRestHandler ) handler );
157174 }
158- registerHandlerNoWrap (method , path , handlerWrapper .apply (handler ));
175+ registerHandlerNoWrap (method , path , version , handlerWrapper .apply (handler ));
159176 }
160177
161- private void registerHandlerNoWrap (RestRequest .Method method , String path , RestHandler maybeWrappedHandler ) {
162- final RestApiVersion version = maybeWrappedHandler .compatibleWithVersion ();
178+ private void registerHandlerNoWrap (RestRequest .Method method , String path , RestApiVersion version , RestHandler handler ) {
163179 assert RestApiVersion .minimumSupported () == version || RestApiVersion .current () == version
164180 : "REST API compatibility is only supported for version " + RestApiVersion .minimumSupported ().major ;
165181
166- handlers .insertOrUpdate (path , new MethodHandlers (path , maybeWrappedHandler , method ),
167- (mHandlers , newMHandler ) -> mHandlers .addMethods (maybeWrappedHandler , method ));
182+ handlers .insertOrUpdate (path ,
183+ new MethodHandlers (path ).addMethod (method , version , handler ),
184+ (handlers , ignoredHandler ) -> handlers .addMethod (method , version , handler ));
185+ }
186+
187+ public void registerHandler (final Route route , final RestHandler handler ) {
188+ if (route .isReplacement ()) {
189+ Route replaced = route .getReplacedRoute ();
190+ registerAsReplacedHandler (route .getMethod (), route .getPath (), route .getRestApiVersion (), handler ,
191+ replaced .getMethod (), replaced .getPath (), replaced .getRestApiVersion ());
192+ } else if (route .isDeprecated ()) {
193+ registerAsDeprecatedHandler (route .getMethod (), route .getPath (), route .getRestApiVersion (), handler ,
194+ route .getDeprecationMessage ());
195+ } else {
196+ // it's just a normal route
197+ registerHandler (route .getMethod (), route .getPath (), route .getRestApiVersion (), handler );
198+ }
168199 }
169200
170201 /**
171202 * Registers a REST handler with the controller. The REST handler declares the {@code method}
172203 * and {@code path} combinations.
173204 */
174- public void registerHandler (final RestHandler restHandler ) {
175- restHandler .routes ().forEach (route -> registerHandler (route .getMethod (), route .getPath (), restHandler ));
176- restHandler .deprecatedRoutes ().forEach (route ->
177- registerAsDeprecatedHandler (route .getMethod (), route .getPath (), restHandler , route .getDeprecationMessage ()));
178- restHandler .replacedRoutes ().forEach (route -> registerWithDeprecatedHandler (route .getMethod (), route .getPath (),
179- restHandler , route .getDeprecatedMethod (), route .getDeprecatedPath ()));
205+ public void registerHandler (final RestHandler handler ) {
206+ handler .routes ().forEach (route -> registerHandler (route , handler ));
180207 }
181208
182209 @ Override
@@ -320,7 +347,7 @@ private void tryAllHandlers(final RestRequest request, final RestChannel channel
320347 // we consume the error_trace parameter first to ensure that it is always consumed
321348 if (request .paramAsBoolean ("error_trace" , false ) && channel .detailedErrorsEnabled () == false ) {
322349 channel .sendResponse (
323- BytesRestResponse .createSimpleErrorResponse (channel , BAD_REQUEST , "error traces in responses are disabled." ));
350+ BytesRestResponse .createSimpleErrorResponse (channel , BAD_REQUEST , "error traces in responses are disabled." ));
324351 return ;
325352 }
326353
@@ -343,9 +370,9 @@ private void tryAllHandlers(final RestRequest request, final RestChannel channel
343370 handler = handlers .getHandler (requestMethod , restApiVersion );
344371 }
345372 if (handler == null ) {
346- if (handleNoHandlerFound (rawPath , requestMethod , uri , channel )) {
347- return ;
348- }
373+ if (handleNoHandlerFound (rawPath , requestMethod , uri , channel )) {
374+ return ;
375+ }
349376 } else {
350377 dispatchRequest (request , channel , handler , restApiVersion );
351378 return ;
@@ -496,7 +523,7 @@ public XContentBuilder newBuilder(@Nullable XContentType xContentType, boolean u
496523
497524 @ Override
498525 public XContentBuilder newBuilder (XContentType xContentType , XContentType responseContentType , boolean useFiltering )
499- throws IOException {
526+ throws IOException {
500527 return delegate .newBuilder (xContentType , responseContentType , useFiltering )
501528 .withCompatibleVersion (restApiVersion );
502529 }
0 commit comments