diff --git a/pom.xml b/pom.xml
index 426732b3abd..ccfbf54c77c 100755
--- a/pom.xml
+++ b/pom.xml
@@ -49,10 +49,10 @@
${project.basedir}
- 0.80.0
- 5.6.1
+ 0.81.0
+ 5.6.3
3.7.1
- 3.13.1
+ 3.14.0
1.17.3
3.11.9
diff --git a/zipkin-autoconfigure/ui/src/main/java/zipkin2/autoconfigure/ui/AddHttpHeadersService.java b/zipkin-autoconfigure/ui/src/main/java/zipkin2/autoconfigure/ui/AddHttpHeadersService.java
deleted file mode 100644
index 5bc7b608921..00000000000
--- a/zipkin-autoconfigure/ui/src/main/java/zipkin2/autoconfigure/ui/AddHttpHeadersService.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2015-2019 The OpenZipkin Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package zipkin2.autoconfigure.ui;
-
-import com.linecorp.armeria.common.HttpHeaders;
-import com.linecorp.armeria.common.HttpRequest;
-import com.linecorp.armeria.common.HttpResponse;
-import com.linecorp.armeria.server.Service;
-import com.linecorp.armeria.server.ServiceRequestContext;
-import com.linecorp.armeria.server.SimpleDecoratingService;
-
-/** Decorates a {@link Service} with additional HTTP headers upon success. */
-final class AddHttpHeadersService extends SimpleDecoratingService {
-
- final HttpHeaders toAdd;
-
- AddHttpHeadersService(Service delegate, HttpHeaders toAdd) {
- super(delegate);
- this.toAdd = toAdd;
- }
-
- @Override public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
- ctx.addAdditionalResponseHeaders(toAdd);
- return delegate().serve(ctx, req);
- }
-}
diff --git a/zipkin-autoconfigure/ui/src/main/java/zipkin2/autoconfigure/ui/ZipkinUiAutoConfiguration.java b/zipkin-autoconfigure/ui/src/main/java/zipkin2/autoconfigure/ui/ZipkinUiAutoConfiguration.java
index 474fa925562..3fd90022175 100644
--- a/zipkin-autoconfigure/ui/src/main/java/zipkin2/autoconfigure/ui/ZipkinUiAutoConfiguration.java
+++ b/zipkin-autoconfigure/ui/src/main/java/zipkin2/autoconfigure/ui/ZipkinUiAutoConfiguration.java
@@ -16,17 +16,19 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.linecorp.armeria.common.HttpData;
import com.linecorp.armeria.common.HttpHeaderNames;
-import com.linecorp.armeria.common.HttpHeaders;
import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.common.HttpStatus;
+import com.linecorp.armeria.common.MediaType;
import com.linecorp.armeria.server.AbstractHttpService;
import com.linecorp.armeria.server.HttpService;
import com.linecorp.armeria.server.RedirectService;
+import com.linecorp.armeria.server.ServerCacheControl;
+import com.linecorp.armeria.server.ServerCacheControlBuilder;
import com.linecorp.armeria.server.Service;
import com.linecorp.armeria.server.ServiceRequestContext;
import com.linecorp.armeria.server.file.HttpFileBuilder;
-import com.linecorp.armeria.server.file.HttpFileService;
+import com.linecorp.armeria.server.file.HttpFileServiceBuilder;
import com.linecorp.armeria.spring.ArmeriaServerConfigurator;
import io.netty.handler.codec.http.cookie.Cookie;
import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
@@ -46,8 +48,6 @@
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.Resource;
-import static com.linecorp.armeria.common.HttpHeaderNames.CACHE_CONTROL;
-import static com.linecorp.armeria.common.HttpHeaderNames.CONTENT_TYPE;
import static java.nio.charset.StandardCharsets.UTF_8;
import static zipkin2.autoconfigure.ui.ZipkinUiProperties.DEFAULT_BASEPATH;
@@ -77,15 +77,6 @@
@EnableConfigurationProperties(ZipkinUiProperties.class)
@ConditionalOnProperty(name = "zipkin.ui.enabled", matchIfMissing = true)
class ZipkinUiAutoConfiguration {
- static final HttpHeaders CACHE_YEAR =
- HttpHeaders.of(CACHE_CONTROL, "max-age=" + TimeUnit.DAYS.toSeconds(365));
- static final HttpHeaders CONFIG_HEADERS = HttpHeaders.of(HttpStatus.OK)
- .add(HttpHeaders.of(CONTENT_TYPE, "application/json"))
- .add(HttpHeaders.of(CACHE_CONTROL, "max-age=" + TimeUnit.MINUTES.toSeconds(10)));
- static final HttpHeaders INDEX_HEADERS = HttpHeaders.of(HttpStatus.OK)
- .add(HttpHeaders.of(CONTENT_TYPE, "text/html"))
- .add(HttpHeaders.of(CACHE_CONTROL, "max-age=" + TimeUnit.MINUTES.toSeconds(1)));
-
@Autowired
ZipkinUiProperties ui;
@@ -130,27 +121,33 @@ String processedIndexHtml(Resource indexHtml) {
lensIndex = HttpFileBuilder.of(HttpData.of(processedLensIndexHtml().getBytes(UTF_8)));
}
- legacyIndex.setHeaders(INDEX_HEADERS);
- lensIndex.setHeaders(INDEX_HEADERS);
+ ServerCacheControl maxAgeMinute = new ServerCacheControlBuilder().maxAgeSeconds(60).build();
+ legacyIndex.contentType(MediaType.HTML_UTF_8).cacheControl(maxAgeMinute);
+ lensIndex.contentType(MediaType.HTML_UTF_8).cacheControl(maxAgeMinute);
+ // In both our old and new UI, assets have hashes in the filenames (generated by webpack).
+ // This allows us to host both simultaneously without conflict as long as we change the index
+ // file to point to the correct files.
return new IndexSwitchingService(
legacyIndex.build().asService(), lensIndex.build().asService());
}
@Bean @Lazy ArmeriaServerConfigurator uiServerConfigurator(
- IndexSwitchingService indexSwitchingService)
- throws IOException {
+ IndexSwitchingService indexSwitchingService) throws IOException {
+ ServerCacheControl maxAgeYear =
+ new ServerCacheControlBuilder().maxAgeSeconds(TimeUnit.DAYS.toSeconds(365)).build();
Service uiFileService =
- new AddHttpHeadersService(HttpFileService.forClassPath("zipkin-ui")
- .orElse(HttpFileService.forClassPath("zipkin-lens")), CACHE_YEAR);
-
-
+ HttpFileServiceBuilder.forClassPath("zipkin-ui").cacheControl(maxAgeYear).build()
+ .orElse(HttpFileServiceBuilder.forClassPath("zipkin-lens").cacheControl(maxAgeYear).build());
byte[] config = new ObjectMapper().writeValueAsBytes(ui);
return sb -> sb
- .service("/zipkin/config.json",
- HttpFileBuilder.of(HttpData.of(config)).addHeaders(CONFIG_HEADERS).build().asService())
+ .service("/zipkin/config.json", HttpFileBuilder.of(HttpData.of(config))
+ .cacheControl(new ServerCacheControlBuilder().maxAgeSeconds(600).build())
+ .contentType(MediaType.JSON_UTF_8)
+ .build()
+ .asService())
.service("/zipkin/index.html", indexSwitchingService)
// TODO This approach requires maintenance when new UI routes are added. Change to the following:
@@ -162,9 +159,10 @@ String processedIndexHtml(Resource indexHtml) {
.service("/zipkin/dependency", indexSwitchingService)
.service("/zipkin/traceViewer", indexSwitchingService)
- .serviceUnder("/zipkin/", uiFileService)
.service("/favicon.ico", new RedirectService(HttpStatus.FOUND, "/zipkin/favicon.ico"))
- .service("/", new RedirectService(HttpStatus.FOUND, "/zipkin/"));
+ .service("/", new RedirectService(HttpStatus.FOUND, "/zipkin/"))
+ .service("/zipkin", new RedirectService(HttpStatus.FOUND, "/zipkin/"))
+ .serviceUnder("/zipkin/", uiFileService);
}
static class IndexSwitchingService extends AbstractHttpService {
diff --git a/zipkin-autoconfigure/ui/src/test/java/zipkin2/autoconfigure/ui/ITZipkinUiAutoConfiguration.java b/zipkin-autoconfigure/ui/src/test/java/zipkin2/autoconfigure/ui/ITZipkinUiAutoConfiguration.java
index 2b79d180e19..35eb3e8ee02 100644
--- a/zipkin-autoconfigure/ui/src/test/java/zipkin2/autoconfigure/ui/ITZipkinUiAutoConfiguration.java
+++ b/zipkin-autoconfigure/ui/src/test/java/zipkin2/autoconfigure/ui/ITZipkinUiAutoConfiguration.java
@@ -16,7 +16,9 @@
import com.linecorp.armeria.server.Server;
import java.io.IOException;
import java.io.InputStream;
+import java.io.UncheckedIOException;
import java.net.URL;
+import java.util.stream.Stream;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
@@ -52,6 +54,35 @@ public class ITZipkinUiAutoConfiguration {
.isEqualTo("max-age=31536000");
}
+ @Test public void redirectsIndex() throws Exception {
+ String index = get("/zipkin/index.html").body().string();
+
+ client = new OkHttpClient.Builder().followRedirects(true).build();
+
+ Stream.of("/zipkin", "/").forEach(path -> {
+ try {
+ assertThat(get(path).body().string()).isEqualTo(index);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ });
+ }
+
+ /** Browsers honor conditional requests such as eTag. Let's make sure the server does */
+ @Test public void conditionalRequests() throws Exception {
+ Stream.of("/zipkin/config.json", "/zipkin/index.html", "/zipkin/test.txt").forEach(path -> {
+ try {
+ String etag = get(path).header("etag");
+ assertThat(conditionalGet(path, etag).code())
+ .isEqualTo(304);
+ assertThat(conditionalGet(path, "aargh").body().contentLength())
+ .isPositive();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ });
+ }
+
/**
* The test sets the property {@code zipkin.ui.base-path=/foozipkin}, which should reflect in
* index.html
@@ -87,4 +118,11 @@ private Response get(String path) throws IOException {
.url("http://localhost:" + server.activePort().get().localAddress().getPort() + path)
.build()).execute();
}
+
+ private Response conditionalGet(String path, String etag) throws IOException {
+ return client.newCall(new Request.Builder()
+ .url("http://localhost:" + server.activePort().get().localAddress().getPort() + path)
+ .header("If-None-Match", etag)
+ .build()).execute();
+ }
}
diff --git a/zipkin-autoconfigure/ui/src/test/java/zipkin2/autoconfigure/ui/ZipkinUiAutoConfigurationTest.java b/zipkin-autoconfigure/ui/src/test/java/zipkin2/autoconfigure/ui/ZipkinUiAutoConfigurationTest.java
index 90d9227d5ac..23be1e1557e 100644
--- a/zipkin-autoconfigure/ui/src/test/java/zipkin2/autoconfigure/ui/ZipkinUiAutoConfigurationTest.java
+++ b/zipkin-autoconfigure/ui/src/test/java/zipkin2/autoconfigure/ui/ZipkinUiAutoConfigurationTest.java
@@ -63,11 +63,11 @@ public void indexHtmlFromClasspath() {
}
@Test
- public void indexContentType() throws Exception {
+ public void indexContentType() {
context = createContext();
assertThat(
serveIndex().headers().contentType())
- .isEqualTo(MediaType.parse("text/html"));
+ .isEqualTo(MediaType.HTML_UTF_8);
}
@Test
diff --git a/zipkin-server/src/main/java/zipkin2/server/internal/ZipkinServerConfiguration.java b/zipkin-server/src/main/java/zipkin2/server/internal/ZipkinServerConfiguration.java
index d206ff2a480..5df39e9fb63 100644
--- a/zipkin-server/src/main/java/zipkin2/server/internal/ZipkinServerConfiguration.java
+++ b/zipkin-server/src/main/java/zipkin2/server/internal/ZipkinServerConfiguration.java
@@ -15,9 +15,6 @@
import brave.Tracing;
import com.linecorp.armeria.common.HttpMethod;
-import com.linecorp.armeria.common.HttpResponse;
-import com.linecorp.armeria.common.HttpStatus;
-import com.linecorp.armeria.common.MediaType;
import com.linecorp.armeria.server.RedirectService;
import com.linecorp.armeria.server.cors.CorsServiceBuilder;
import com.linecorp.armeria.spring.ArmeriaServerConfigurator;
@@ -30,7 +27,6 @@
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.actuate.health.HealthAggregator;
-import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@@ -61,7 +57,7 @@ public class ZipkinServerConfiguration implements WebMvcConfigurer {
@Autowired(required = false)
MetricsHealthController healthController;
- @Bean ArmeriaServerConfigurator serverConfigurator(PrometheusScrapeEndpoint prom) {
+ @Bean ArmeriaServerConfigurator serverConfigurator() {
return sb -> {
if (httpQuery != null) {
sb.annotatedService(httpQuery);
@@ -73,14 +69,6 @@ public class ZipkinServerConfiguration implements WebMvcConfigurer {
sb.service("/prometheus", new RedirectService("/actuator/prometheus"));
// Redirects the info endpoint for backward compatibility
sb.service("/info", new RedirectService("/actuator/info"));
-
- // TODO: Workaround for https://github.com/line/armeria/issues/1637
- MediaType promMedia = MediaType.parse("text/plain; version=0.0.4; charset=utf-8");
- sb.decorator(
- delegate -> (ctx, req) -> {
- if (!"/actuator/prometheus".equals(req.path())) return delegate.serve(ctx, req);
- return HttpResponse.of(HttpStatus.OK, promMedia, prom.scrape());
- });
};
}
diff --git a/zipkin-server/src/test/java/zipkin2/server/internal/ZipkinServerConfigurationTest.java b/zipkin-server/src/test/java/zipkin2/server/internal/ZipkinServerConfigurationTest.java
index 3bfc412a13c..d9da448d0fc 100644
--- a/zipkin-server/src/test/java/zipkin2/server/internal/ZipkinServerConfigurationTest.java
+++ b/zipkin-server/src/test/java/zipkin2/server/internal/ZipkinServerConfigurationTest.java
@@ -24,7 +24,6 @@
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
import org.springframework.boot.actuate.health.HealthAggregator;
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
-import org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -46,7 +45,6 @@ public class ZipkinServerConfigurationTest {
@Test public void httpCollector_enabledByDefault() {
context.register(
ArmeriaSpringActuatorAutoConfiguration.class,
- PrometheusScrapeEndpointConfiguration.class,
EndpointAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
ZipkinServerConfigurationTest.Config.class,
@@ -58,19 +56,11 @@ public class ZipkinServerConfigurationTest {
assertThat(context.getBean(ZipkinHttpCollector.class)).isNotNull();
}
- // TODO: Remove when removing workaround for https://github.com/line/armeria/issues/1637
- @Deprecated static class PrometheusScrapeEndpointConfiguration {
- @Bean PrometheusScrapeEndpoint prometheusEndpoint() {
- return new PrometheusScrapeEndpoint(null);
- }
- }
-
@Test(expected = NoSuchBeanDefinitionException.class)
public void httpCollector_canDisable() {
TestPropertyValues.of("zipkin.collector.http.enabled:false").applyTo(context);
context.register(
ArmeriaSpringActuatorAutoConfiguration.class,
- PrometheusScrapeEndpointConfiguration.class,
EndpointAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
ZipkinServerConfigurationTest.Config.class,
@@ -85,7 +75,6 @@ public void httpCollector_canDisable() {
@Test public void query_enabledByDefault() {
context.register(
ArmeriaSpringActuatorAutoConfiguration.class,
- PrometheusScrapeEndpointConfiguration.class,
EndpointAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
ZipkinServerConfigurationTest.Config.class,
@@ -101,7 +90,6 @@ public void httpCollector_canDisable() {
TestPropertyValues.of("zipkin.query.enabled:false").applyTo(context);
context.register(
ArmeriaSpringActuatorAutoConfiguration.class,
- PrometheusScrapeEndpointConfiguration.class,
EndpointAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
ZipkinServerConfigurationTest.Config.class,
@@ -121,7 +109,6 @@ public void httpCollector_canDisable() {
TestPropertyValues.of("zipkin.self-tracing.enabled:true").applyTo(context);
context.register(
ArmeriaSpringActuatorAutoConfiguration.class,
- PrometheusScrapeEndpointConfiguration.class,
EndpointAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
ZipkinServerConfigurationTest.Config.class,
@@ -137,7 +124,6 @@ public void httpCollector_canDisable() {
TestPropertyValues.of("zipkin.storage.search-enabled:false").applyTo(context);
context.register(
ArmeriaSpringActuatorAutoConfiguration.class,
- PrometheusScrapeEndpointConfiguration.class,
EndpointAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
ZipkinServerConfigurationTest.Config.class,