@GetMapping(
        path = "/api/{namespace}/{extension}",
        produces = MediaType.APPLICATION_JSON_VALUE
    )
    @CrossOrigin
    @Operation(summary = "Provides metadata of the latest version of an extension")
    @ApiResponses({
        @ApiResponse(
            responseCode = "200",
            description = "The extension metadata are returned in JSON format"
        ),
        @ApiResponse(
            responseCode = "404",
            description = "The specified extension could not be found",
            content = @Content()
        ),
        @ApiResponse(
            responseCode = "429",
            description = "A client has sent too many requests in a given amount of time",
            content = @Content(),
            headers = {
                @Header(
                    name = "X-Rate-Limit-Retry-After-Seconds",
                    description = "Number of seconds to wait after receiving a 429 response",
                    schema = @Schema(type = "integer", format = "int32")
                ),
                @Header(
                    name = "X-Rate-Limit-Remaining",
                    description = "Remaining number of requests left",
                    schema = @Schema(type = "integer", format = "int32")
                )
            }
        )
    })
    public ResponseEntity<ExtensionJson> getExtension(
            @PathVariable @Parameter(description = "Extension namespace", example = "redhat")
            String namespace,
            @PathVariable @Parameter(description = "Extension name", example = "java")
            String extension
    ) {
        for (var registry : getRegistries()) {
            try {
                return ResponseEntity.ok()
                        .cacheControl(CacheControl.noCache().cachePublic())
                        .body(registry.getExtension(namespace, extension, null));
            } catch (NotFoundException exc) {
                // Try the next registry
            }
        }
        var json = ExtensionJson.error("Extension not found: " + NamingUtil.toExtensionId(namespace, extension));
        return new ResponseEntity<>(json, HttpStatus.NOT_FOUND);
    }
@Test
    public void testPreReleaseExtensionVersionNonDefaultTarget() throws Exception {
        var extVersion = mockExtension("web");
        extVersion.setPreRelease(true);
        extVersion.setDisplayName("Foo Bar (web)");
        Mockito.when(repositories.findExtensionVersion("foo", "bar", null, VersionAlias.PRE_RELEASE)).thenReturn(extVersion);
        Mockito.when(repositories.findLatestVersionForAllUrls(extVersion.getExtension(), null, false, true)).thenReturn(extVersion);
        Mockito.when(repositories.findLatestVersionForAllUrls(extVersion.getExtension(), null, true, true)).thenReturn(extVersion);
        mockMvc.perform(get("/api/{namespace}/{extension}/{version}", "foo", "bar", "pre-release"))
                .andExpect(status().isOk())
                .andExpect(content().json(extensionJson(e -> {
                    e.namespace = "foo";
                    e.name = "bar";
                    e.version = "1.0.0";
                    e.verified = false;
                    e.timestamp = "2000-01-01T10:00Z";
                    e.displayName = "Foo Bar (web)";
                    e.versionAlias = List.of("pre-release", "latest");
                    e.preRelease = true;
                })));
    }