Your go-to microservice framework for any situation, from the creator of Netty et al. You can build any type of microservice leveraging your favorite technologies, including gRPC, Thrift, Kotlin, Retrofit, Reactive Streams, Spring Boot and Dropwizard.
APACHE-2.0 License
Bot releases are visible (Hide)
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation or other microservice frameworks.
@Path
. #1822 #1870
@Get
@Post
@Path("/a")
@Path("/b")
public String myAwesomeServcie(...) {...}
blockingTaskExecutor
by attaching @Blocking
. #2078, #2187
@Get("/myHeavyTask")
@Blocking
public HttpResponse reallyHeavyComputation(...) {...}
Server
and Date
headers to responses by default. #2137, #2188
Server.builder()
.service(...)
.disableServerHeader()
.disableDateHeader()
.build();
HttpFileService
. #916, #2142
HttpFileServiceBuilder.forClassPath("/")
.entryCacheSpec("maximumSize=512")
.build()
Or, using JVM option:-Dcom.linecorp.armeria.fileServiceCache=maximumSize=1024,expireAfterAccess=600s
HttpTimestampSupplier.currentTime()
to take advantage of it.Map
in RouteResult
. #2153Tag
s is improved by adding Tag
s in ascending order. #2150, #2163DocService
. #2186ServerHttpRequest.getRemoteAddress()
now returns proper address. #2208sslContext
is not configured properly. #1844, #2124(Request|Response)Headers
multiple times using builders. #2190, #2193
ClassCastException
if build()
is called twice.NoRequestContextException
is not raised anymore if you configure the name of the non-request thread.
RequestContextCurrentTraceContext.builder()
.nonRequestThread("RMI TCP Connection")
.build()
NullPointerException
is not raised anymore in Http1ClientCodec
when the server sends multiple responses for one request. #2210EventLoop
by default. #2187
HttpResponse
nor CompletableFuture
, annotated services are run from blockingTaskExecutor
.ServerBuilder.tls()
now throws a checked SSLException
. #2124ServerBuilder.sslContext()
methods are completly removed. #2124This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation or other microservice frameworks.
ServerBuilder sb = new ServerBuilder();
// Register vipService and memberService under '/users' path
sb.annotatedService("/users/vip", vipService)
.annotatedService("/users/members", memberService);
// Decorate all services under '/users' path
sb.decoratorUnder("/users", (delegate, ctx, req) -> {
if (!authenticate(req)) {
return HttpResponse.of(HttpStatus.UNAUTHORIZED);
}
return delegate.serve(ctx, req);
});
You can also use fluent route builder with routeDecorator()
to decorate more than one service by path mapping.
// Decorate services under '/users' path with fluent route builder
sb.routeDecorator()
.pathPrefix("/users")
.build((delegate, ctx, req) -> {
if (!authenticate(req)) {
return HttpResponse.of(HttpStatus.UNAUTHORIZED);
}
return delegate.serve(ctx, req);
});
HttpRequest
and RpcRequest
from RequestContext
so you don’t need to downcast Request
to HttpRequest
or RpcRequest
. #2089 #2120
// Before:
Request req = ctx.request();
if (req instanceof HttpRequest) {
RequestHeaders headers = (HttpRequest) req).headers();
}
// After:
RequestHeaders headers = ctx.request().headers();
// Before:
if (req instanceof RpcRequest) {
String rpcMethod = (RpcRequest) requestContent).method();
}
// After:
// `rpcRequest()` method will return `null` when the request being handled is not
// an RPC request or not decoded into an RPC request yet.
String rpcMethod = ctx.rpcRequest().method();
{Annotated,Grpc,Thrift}ServiceRegisrationBean
for Spring Boot integration. #2100
@Bean
public AnnotatedServiceRegistrationBean annotatedService() {
return new AnnotatedServiceRegistrationBean()
.setServiceName("annotatedService")
.setService(new AnnotatedService())
// Add exmample headers for annotated service
.addExampleHeaders("x-additional-header", "headerVal")
.addExampleHeaders("get", "x-additional-header", "headerVal");
}
builder()
method instead of their *Builder
constructors. #1719 #2085
CircuitBreaker
CircuitBreakerHttpClient
CircuitBreakerRpcClient
DnsAddressEndpointGroup
DnsServiceEndpointGroup
DnsTextEndpointGroup
GrpcService
Server
RetryingHttpClient
RetryingRpcClient
// Before:
Server server = new ServerBuilder()
.service("/hello", (ctx, req) -> HttpResponse.of(OK))
.build();
// After:
Server server = Server.builder()
.service("/hello", (ctx, req) -> HttpResponse.of(OK))
.build();
RequestContextAwareFuture
for the recent changes of CompletableFuture API, thanks to the Multi-Release JAR Files. #1991 #2052 #2127ResponseTimeoutException
is not logged more than once anymore when the response has been timed out. #2000 #2138AbortedStreamException
while sending long-lived requests with RetryingHttpClient
. #2134AbstractBindingBuilder.pathUnder(String prefix)
has been deprecated in favor of pathPrefix(String prefix)
. #2040RouteBuilder.prefix(String prefix, ...)
has been deprecated in favor of pathPrefix(String prefix, ...)
. #2040RouteBuilder.pathWithPrefix(String prefix, String pathPattern)
has been deprecated in favor of path(String prefix, String pathPattern)
. #2040new *Builder()
constructors which are mentioned in 'New Features' have been deprecated in favor of *.builder()
. #1719 #2085armeria-zipkin
has been removed for further clean-up. #2120RequestContext.request()
returns HttpRequest
instead of Request
. #2120
RequestContext.updateRequest()
always updates an HttpRequest
. It returns void
now because it never fails, unless null
is specified.RequestContext.newDerivedContext(Request)
now requires both HttpRequest
and RpcRequest
.NOT_FOUND
status.AbstractStreamMessageDuplicator.close()
does not abort all children StreamMessage
s. #2134
AbstractStreamMessageDuplicator.abort()
to abort all children StreamMessage
s anymore.This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation or other microservice frameworks.
Sampler
from a specification string such as random=0.1
and rate-limited=10
. #2108
Brave{Client,Server}
or Logging{Client,Server}
configurable from external sources such as a configuration file or a system property.Sampler<Object> randomSampler = Sampler.of("random=0.1");
Sampler<Object> rateLimitedSampler = Sampler.of("rate-limited=10");
Sampler<Object> alwaysSampler = Sampler.of("always");
Sampler<Object> neverSampler = Sampler.of("never");
Sampler
specification string in the com.linecorp.armeria.verboseExceptions
system property. #2105 #2111
rate-limited=10
which means the stack trace of the exceptions will be recorded at the maximum rate of 10 exceptions/sec. Previously, the default value of this property was false
, which eliminates all stack traces, which gave our users a hard time figuring out why.@PathPrefix
annotation in annotated services. #2031 #2099
@PathPrefix("/users")
public class MyUserService {
@Get("/{id}") // Mapped to '/users/{id}'
@ProducesJson
public User getUser(@Param int id) { ... }
...
}
Server server = new ServerBuilder()
.annotatedService(new MyUserService())
.build();
HealthCheckService
. #2110armeria-spring-boot-*
. #2106 #2107armeria-spring-boot-actuator-autoconfigure
does not refuse to start anymore when HealthStatusHttpMapper
is missing. #2104Flags.verboseExceptions()
has been replaced with verboseExceptionSampler()
and verboseExceptionSamplerSpec()
. #2111Exceptions.isVerbose()
, which was deprecated previously, has been removed. #2111io.micrometer:micrometer-registry-prometheus
or io.dropwizard.metrics:metrics-json
after upgrading if you were depending on them transitively. #2107This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation or other microservice frameworks.
RequestHeaders.uri()
and HttpRequest.uri()
. #2092
RequestHeaders headers = RequestHeaders.of(HttpMethod.GET, "/foo",
HttpHeaderNames.SCHEME, "https",
HttpHeaderNames.AUTHORITY, "example.com"));
assert headers.uri().equals(URI.create("https://example.com/foo"));
assert HttpRequest.of(header).uri() == headers.uri();
Runnable
of the Thread
created using ThreadFactoryBuilder
. #2047 #2067
ThreadFactories.builder(...)
.eventLoop(true)
.daemon(true)
.priority(...)
.taskFunction(task -> {
// Specify your logic here so it's executed before the Runnable.
task.run();
// Specify your logic here so it's executed after the Runnable.
})
.build();
Server
using Consumer<ServerBuilder>
as well as ArmeriaServerConfigurator
when integrating with Spring Boot. #2070
@Bean
public Consumer<ServerBuilder> customizer() {
return sb -> sb.port(...)
...
.service(...);
}
AnnotatedServiceRegistrationBean
. #1855 #2026
@Bean
public AnnotatedServiceRegistrationBean okService() {
return new AnnotatedServiceRegistrationBean()
.setServiceName("myAnnotatedService")
.setPathPrefix("/my_service")
.setService(new MyAnnotatedService())
.setExampleRequests(Lists.of(
AnnotatedExampleRequest.of("myMethod", "{\"foo\":\"bar\"}")));
}
HttpStatus status = ...
if (!status.isContentAlwaysEmpty()) {
// We may have a body!
}
SettableHealthIndicator
for health check responses when using Spring boot autoconfigure. #2088RequestContext
instead of RequestLog
is used for trace parsing and sampling. #2038EndpointGroup
are notified after the first health check even when all endpoints are unhealthy. #2074 #2075Response
from a WebClient
gets notified when it's complete. #2080 #2087IllegalStateException
that indicates the log should have at least one child is no longer raised when retrying. #2082 #2083DefaultEventLoopScheduler
respects maxNumEventLoopsPerHttpHttp1Endpoint
set from ClientFactoryBuilder
. #2086EventLoopThreadFactory
has been deprecated in favor of ThreadFactories
. #2067
ThreadFactory factory = ThreadFactories.builder("myThread")
.eventLoop(true)
.build();
:authority
header in a request has no effect anymore. The current Endpoint
always determines the authority. #2092
// This does NOT work anymore.
final HttpClient client = HttpClient.of("https://127.0.0.1:8080/");
client.execute(RequestHeaders.of(HttpMethod.GET, "/",
HttpHeaderNames.AUTHORITY, "foo.com"));
// This works.
final HttpClient client =
HttpClient.of(SessionProtocol.HTTPS,
Endpoint.of("foo.com", 8080).withIpAddr("127.0.0.1"));
client.get("/");
ClientOption.HTTP_HEADERS
or {Client,Service}RequestContext.additional{Request,Response}{Headers,Trailers}()
to override the existing headers, including :authority
. #2092
// This works.
final HttpHeaders customHeaders =
HttpHeaders.of(HttpHeaderNames.AUTHORITY, "foo.com");
final HttpClient client =
HttpClient.of("http://127.0.0.1:8080/",
ClientOption.HTTP_HEADERS.newValue(customHeaders));
client.get("/");
// This also works.
final HttpClient client = HttpClient.of("http://127.0.0.1:8080/");
try (SafeCloseable ignored = Clients.withHttpHeader(
HttpHeaderNames.AUTHORITY, "foo.com")) {
client.get("/");
}
ExceptionHandlerFunction.handleExeption()
accepts ServiceRequestContext
instead of RequestContext
. #2060
GrpcServiceRegistrationBean.ExampleRequest
has been removed. Use GrpcExampleRequest
.This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation or other microservice frameworks.
ClientFactoryBuilder builder = ...;
builder.maxNumEventLoopsPerEndpoint(5); // Assign 5 event loops for endpoints. 1 is used by default.
builder.maxNumEventLoopsPerHttp1Endpoint(10); // Assign 10 event loops for HTTP/1.1 endpoints. 1 is used by default.
// You can set a customized function.
builder.maxNumEventLoopsFunction(endpoint -> {
if (endpoint.equals(Endpoint.of("foo.com"))) {
return 5;
}
if (endpoint.host().contains("bar.com")) {
return Integer.MAX_VALUE; // The value will be clamped at the number of event loops.
}
return -1; // Should return 0 or a negative value to use the default value.
});
EventLoopScheduler
which schedules EventLoop
s those handle connections. #1886EndpointGroup
s and Endpoint
s. #1897 #1939
Endpoint foo = ...;
Endpoint bar = ...;
DynamicEndpointGroup group1 = ...;
DynamicEndpointGroup group2 = ...;
EndpointGroup composite = EndpointGroup.of(foo, bar, group1, group2);
Backoff backoff = Backoff.fibonacci(100 /* initial delay millis */,
10000 /* max delay millis */);
HealthCheckedEndpointGroup
. #2019 #2020
HttpClient myClient = ...;
ArmeriaRetrofitBuilder builder = new ArmeriaRetrofitBuilder();
// Use the same settings and decorators with `myClient` when sending requests.
builder.clientOptions(myClient.options());
HealthCheckedEndpointGroupBuilder builder2 = new HealthCheckedEndpointGroupBuilder();
builder2.clientOptions(myClient.options());
Client
and bring the decorating client instance via Unwrappable.as()
or ClientFactory.unwrap()
. #1883 #2018 #2029
HttpClient client = new HttpClientBuilder()
.decorator(LoggingClient.newDecorator())
.build();
LoggingClient unwrapped = client.as(LoggingClient.class).get();
LoggingClient unwrapped2 = clientFactory.unwrap(client, LoggingClient.class).get();
ServerBuilder sb = new ServerBuilder();
Server server = sb.http(0) // Use an ephemeral port.
.build();
...
int port = server.activeLocalPort();
ExponentialBackoff
is improved. #1983gradle run
or gradle bootRun
. #1988ByteBufHttpData
does not leak anymore when an exception is raised by a client-side decorator. #2034NullPointerException
when the remote server requires a protocol downgrade. #2010 #2021EventLoop
handles all requests. Because of that, you may see performance degradation. If you want it to work as before, specify maxNumEventLoopsPerEndpoint
with the number of event loops in ClientFactoryBuilder
.We now use Maven Boms(Bill of Materials) for Jackson, Brave and Netty
This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation or other microservice frameworks.
HealthCheckedEndpointGroup
does not report healthy endpoints as unhealthy anymore. #2004UnaryGrpcClient
now handles gRPC status in HTTP trailer correctly. #1998byte[]
or HttpData
returned by an annotated service method is now handled correctly when @Produces
annotation is used with certain media types. #1999 #2005This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation or other microservice frameworks.
This release updates Netty from 4.1.38 to 4.1.39 to address the HTTP/2 security issues found in its previous versions. Please upgrade as soon as possible if your application serves the traffic from untrusted environment such as the Internet. See Netty 4.1.39 release news and Netflix security bulletins for more information.
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation or other microservice frameworks.
SSLContext
anymore when JRE does not support TLSv1.3 and OpenSSL support is missing. #1984 #1986HealthCheckedEndpointGroup
does not fail with ConcurrentModificationException
anymore in a certain situation. #1989 #1990 #1992This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation or other microservice frameworks.
HttpClient
s for different hosts. #1143 #1343 #1961
HttpClient client = HttpClient.of(); // No base URI specified.
client.get("http://foo.com").aggregate().join();
client.execute(RequestHeaders.of(HttpMethod.GET, "http://bar.com")).aggregate().join();
HttpClient client = HttpClient.of("http://baz.com"); // Base URI specified.
client.get("/index.html").aggregate().join();
client.get("http://qux.com").aggregate().join(); // Can override the base URI.
HealthCheckedEndpointGroup
has been revamped and now supports long-polling when used with Armeria's HealthCheckService
. #1948 #1977 #1982
HealthCheckedEndpointGroup
to detect the server health changes immediately with much fewer number of health check requests.armeria-lphc
, so it is fully backward-compatible with ordinary non-Armeria health check services.EndpointGroup group =
HealthCheckedEndpointGroup.of(
new StaticEndpointGroup(Endpoint.of("foo.com", 8080),
Endpoint.of("bar.com", 8080)),
"/internal/l7check");
EndpointGroupRegistry.register("myGroup", group,
EndpointSelectionStrategy.WEIGHTED_ROUND_ROBIN);
HttpClient client = HttpClient.of("http://group:myGroup");
client.get("/").aggregate().join();
HttpResponse.delayed()
, which may be useful when simulating a slow server. #1935
Server server = new ServerBuilder()
.service("/delayed", (ctx, req) -> HttpResponse.delayed(HttpResponse.of(200),
Duration.ofSeconds(3)))
.build();
MockWebServerExtension
and JUnit 5. #1884 #1935
class MyTest {
@RegisterExtension
static MockWebServerExtension server = new MockWebServerExtension();
@Test
void test() {
server.enqueue(HttpResponse.of(200));
HttpResponse actualRes = HttpClient.of(server.httpUri("/")).get("/");
assertThat(actualRes.aggregate().join().status().code()).isEqualTo(200);
}
}
AsyncCloseable
has been added to provide an asynchronous close operation. #1948
public class IAmCloseable implements AutoCloseable, AsyncCloseable {
@Override
public CompletableFuture<?> closeAsync() {
...
}
@Override
public void close() {
closeAsync().join();
}
}
EventExecutor
when using HttpResponse.from()
. #1937RequestContextCurrentTraceContext
by using setCurrentThreadNotRequestThread()
#1971 #1980
ThreadFactory
like the following:
ThreadFactory factory = (runnable) -> new Thread(new Runnable() {
@Override
public void run() {
RequestContextCurrentTraceContext.setCurrentThreadNotRequestThread(true);
runnable.run();
}
@Override
public String toString() {
return runnable.toString();
}
});
RequestLog.responseCause()
is now recorded correctly for client requests. #1977RetryingClient
now respects the Endpoint
selection order, which was broken since 0.89.0. #1973 #1974HealthCheckedEndpointGroup
are now sent at the correct interval, even if an endpoint is not responsive. #1948ClosedPublisherException
is not raised anymore when HttpResponse
is aborted by the client who issued the request. #1962TE
header, whose absence caused interoperability issues with some gRPC servers, such as Python gRPC server. #1963 #1965Host
headers for HTTP/1 anymore. #1942HealthCheckedEndpointGroup
now waits until the initial Endpoint
s are available from its delegate group. #1940HealthCheckedEndpointGroupBuilder.retryInterval()
has been un-deprecated. #1948HealthCheckedEndpointGroupBuilder.healthCheckPort()
has been deprecated in favor of port()
. #1948CircuitBreakerBuilder.circuitBreakerMapping()
has been deprecated in favor of mapping()
. #1970HttpHealthCheckedEndpointGroup
has been renamed to HealthCheckedEndpointGroup
.
HealthCheckedEndpointGroup
has been renamed to AbstractHealthCheckedEndpointGroup
, and is now extensible enough for you to implement your own health-checking mechanism, such as sending a gRPC/Thrift call.This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation.
Server
in a functional way. #1882 #1900
ServerBuilder sb = new ServerBuilder();
sb.service(...);
// After:
sb.decorator((delegate, ctx, req) -> {
...
return delegate.serve(ctx, req);
});
// Before:
sb.decorator(delegate -> new SimpleServiceDecorator<HttpRequest, HttpResponse>(delegate) {
@Override
public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
...
return delegate().serve(ctx, req);
}
});
HealthCheckService
which has richer functionality than its predecessor HttpHealthCheckService
. #1878
ServerBuilder sb = new ServerBuilder();
sb.service("/internal/l7check",
HealthCheckService.builder()
.checkers(...)
.healthyResponse(...)
.unhealthyResponse(...)
.longPolling(Durations.ofMinutes(1))
.updatable(true)
.build());
EndpointGroup
as the destination.ClientRequestContext.endpoint()
may return null
since this release when Armeria failed to determine the destination host.ClientRequestContext.endpointSelector()
has been added so that you still know which EndpointGroup
you are connecting to.BraveClient
and BraveService
now accept HttpTracing
as well as Tracing
. #1223 #1906
Tracing tracing = ...;
// Server-side
ServerBuilder sb = new ServerBuilder();
//// Before
sb.service("/", myService.decorate(BraveService.newDecorator(tracing)));
//// After
HttpTracing httpTracing = HttpTracing.create(tracing);
sb.service("/", myService.decorate(BraveService.newDecorator(httpTracing)));
// Client-side
HttpClientBuilder cb = new HttpClientBuilder(...);
//// Before
cb.decorator(BraveClient.newDecorator(tracing, "myBackend"));
//// After
cb.decorator(BraveClient.newDecorator(httpTracing.clientOf("myBackend")));
Service
or Client
in a less verbose way by extending new SimpleDecorating*
classes. #1881 #1925
SimpleDecoratingHttpService extends SimpleDecoratingService<HttpRequest, HttpResponse>
SimpleDecoratingRpcService extends SimpleDecoratingService<RpcRequest, RpcResponse>
SimpleDecoratingHttpClient extends SimpleDecoratingClient<HttpRequest, HttpResponse>
SimpleDecoratingRpcClient extends SimpleDecoratingClient<RpcRequest, RpcResponse>
RpcService
has been added for your convenience. #1881 #1925
RpcService extends Service<RpcRequest, RpcResponse>
RequestLog
sanitizer functions has been relaxed to ?
so that a user can write much simpler and more efficient sanitizer function. #1810 #1879
// Before
Function<HttpHeaders, HttpHeaders> sanitizer = headers -> {
return headers.toBuilder().removeAndThen("authorization").build();
};
// After
Function<HttpHeaders, Object> sanitizer = headers -> {
// No need to construct a new HttpHeaders object.
return headers.toBuilder().removeAndThen("authorization").toString();
};
// Even more efficiently
Function<HttpHeaders, Object> sanitizer = headers -> "sanitized!";
ByteBufHttpData.toInputStream()
does not perform extra memory copy anymore. #1918 #1919OPTIONS * HTTP/1.1
instead of HEAD / HTTP/1.1
, so that the initial protocol upgrade does not trigger business logic when a server has business logic bound at /
. #1895 #1896max-age
attribute in a set-cookie
header is now handled correctly when using Spring WebFlux. #1904HttpHealthCheckedEndpoint
does not leak connections and requests after close()
is called. #1899BraveClient
does not trigger RequestLogAvailabilityException
anymore when the request being traced has failed without sending any data. #1911 #1912@ConsumesJson
annotation now accepts JSON documents with any charsets rather than only UTF-8
. #1920IllegalStateException
raised by pushIfAbsent()
is now propagated properly to the CompletableFuture
created by RequestContext.makeContextAware()
. #1920HttpHealthCheckService
and SettableHttpHealthCheckService
have been deprecated in favor of HealthCheckService
and its builder. #1878ClientRequestContext.endpoint()
may return null
since this release. #1917Endpoint
returned by ClientRequestContext.endpoint()
now always refers to a single host, not an EndpointGroup
. #1917
ClientRequestContext.endpointSelector().group()
to retrieve the related EndpointGroup
.This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation.
ClientRequestContext.current()
and ServiceRequestContext.current()
have been added so you don't need to downcast RequestContext
to ClientRequestContext
or ServiceRequestContext
. It also makes sure the current context is client-side (or server-side), preventing a ClassCastException
. #1869 #1872
ClientRequestContext cctx = ClientRequestContext.current();
ServiceReqiestContext sctx = ServiceRequestContext.current();
currentOrNull()
static method has been added to (Client|Service)RequestContext
, which is similar to current()
but returning null
when there's no current context. #1872
// Before:
RequestContext ctx = RequestContext.mapCurrent(Function.identity(), null);
// After:
ServiceRequestContext sctx = ServiceRequestContext.currentOrNull();
AccessLogWriter
s for different services. #1866
Server server = new ServerBuilder()
.route().path("/svc1")
.accessLogWriter(accessLogWriterForService1, true)
.build(service1)
.route().path("/svc2") // Will use the fallbackAccessLogWriter.
.build(service2)
.accessLogWriter(fallbackAccessLogWriter, true)
.build();
Executor
specified in ServerBuilder.blockingTaskExecutor()
will be exposed under executor{name=armeriaBlockingTaskExecutor}
. #1683 #1841Backoff
, which means you can have more flexible delay strategy such as adding jitter. #1846
HttpHealthCheckedEndpointGroup group = new HttpHealthCheckedEndpointGroup(...)
.retryBackoff(Backoff.fixed(10000).withJitter(0.3))
.build();
HealthCheckedEndpointGroup
will now add 20% jitter to the health check request interval.armeria-brave
has been added to replace the deprecated armeria-zipkin
. #1840
com.linecorp.armeria.{common,client,server}.tracing
to com.linecorp.armeria.{common,client,server}.brave
.HttpTracingClient
and HttpTracingService
have been renamed to BraveClient
and BraveService
.retrofit2.Invocation
object associated with the current Retrofit call via InvocationUtil.get(RequestLog)
, which can be useful when building a meter ID prefix. #1591 #1845
public class MyRetrofitMeterIdPrefixFunction implements MeterIdPrefixFunction {
@Override
public MeterIdPrefix apply(MeterRegistry registry, RequestLog log) {
final Invocation invocation = InvocationUtil.getInvocation(log);
final String service;
final String method;
if (invocation != null) {
service = invocation.method().getDeclaringClass().getSimpleName();
method = invocation.method().getName();
} else {
service = "unknown";
method = log.method().name();
}
return new MeterIdPrefix("call", "service", service, "method", method);
}
}
RetrofitMeterIdPrefixFunction
which provides the sensible default MeterIdPrefixFunction
for Retrofit calls.UnprocessedRequestException
to indicate whether the request can be safely retried without worrying about sending the request more than once. #1653 #1848
UnprocessedRequestException.getCause()
is non-null, so you do not need to worry about the case where there is no cause in UnprocessedRequestException
.@Default
annotation with null
value. #1858 #1864DEBUG
level log message which occurs when a client sent an ill-formed Accept
header is now easier to understand. #1849THttpService
now handles HttpStatusException
and HttpResponseException
correctly, which means they will not be translated into a 200 OK
response that contains a TApplicationException
anymore. For example, your Thrift clients will see 503 Service Unavailable
response when your service throws an HttpStatusException.of(503)
rather than 200 OK
. #1839 #1867DocService
debug form will validate the endpoint path properly now. #1856 #1857RequestContextCurrentTraceContext
now calls decorateScope()
when necessary. #1840ssl.keyAlias
property anymore. #1843 #1865ERROR
log message when a client sends a HEAD
request to your Spring WebFlux endpoint. #1847 #1859HttpHealthCheckedEndpointGroupBuilder.retryInterval(Duration)
has been deprecated. Use retryBackoff(Backoff)
. #1846armeria-zipkin
has been deprecated. Use armeria-brave
. #1840javax.annotation-api
-> jakarta.annotation-api
1.3.4This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation.
DocService
debug page. #1815Route
replaces PathMapping
. #1789
ServerBuilder sb = new ServerBuilder();
sb.service(Route.builder()
.path("/greet/{name}")
.consumes(MediaType.JSON)
.produces(MediaType.JSON_UTF_8)
.build(),
(ctx, req) -> HttpResponse.of(HttpStatus.OK,
MediaType.JSON_UTF_8,
...));
AggregatedHttpMessage
has been split into two subtypes: AggregatedHttpRequest
and AggregatedHttpResponse
. #1702 #1795
AggregatedHttpMessage
have been pushed down to the two subtypes. For example, AggregatedHttpMessage.method()
does not exist anymore and you will find it in AggregatedHttpRequest
.AggregatedHttpRequest
or AggregatedHttpResponse
rather than AggregatedHttpMessage
wherever possible for clarity.HttpData
. #1797
HttpData.of()
was not very clear about whether it will wrap the specified bytes or make a copy of them. HttpData.wrap()
and HttpData.copyOf()
removes such ambiguity.
byte[] b = new byte[] { 1, 2, 3 }
HttpData copied = HttpData.copyOf(b);
HttpData wrapped = HttpData.wrap(b);
b[0] = 0;
assert copied.array()[0] == 1;
assert wrapped.array()[0] == 0;
SubscriptionOption
s when subscribing to a StreamMessage
to modify the contract between StreamMessage
and Subscriber
. #1700 #1808
HttpRequest req = ...;
// Subscriber.onError() will be invoked with a CancelledSubscriptionException
// when the Subscription is cancelled.
req.subscribe(mySubscriber, SubscriptionOption.NOTIFY_CANCELLATION);
Endpoint
s loaded from a .properties
file by PropertiesEndpointGroup
are now automatically updated when the .properties
file is modified. Note that the classpath resources are not auto-reloaded and you have to specify a real file as a java.nio.Path
. #1787
PropertiesEndpointGroup endpoints = PropertiesEndpointGroup.of(
Paths.get("/etc/my/endpoints.properties"),
"endpoints.");
Client
by specifying an Endpoint
rather than a URI
. #1743
Endpoint endpoint = Endpoint.of("example.com");
HttpClient client = new HttpClientBuilder(SessionProtocol.HTTPS, endpoint)
...
.build();
DropwizardMeterRegistry
(or PrometheusMeterRegistry
) using DropwizardMeterRegistries.configureRegistry()
(or PrometheusMeterRegistries.configureRegistry()
). Previously, Armeria's default settings were applied only to the MeterRegistry
s created by DropwizardMeterRegistries.newRegistry()
(or PrometheusMeterRegistries.newRegistry()
). #1814 #1820
import io.micrometer.jmx.JmxMeterRegistry;
// JmxMeterRegistry is a subtype of DropwizardMeterRegistry.
JmxMeterRegistry jmxRegistry = new JmxMeterRegistry(...);
DropwizardMeterRegistries.configureRegistry(jmxRegistry);
InvalidSamlRequestException
has been added so that you can tell if a client sent an invalid SAML request from exception type. #1780 #1783RequestContextCurrentTraceContext
cannot find the current RequestContext
. #1800#
and /
are now preserved correctly. #1805Metadata
is now supported. #1788 #1790/
). #1785ServiceRequestContext.addAdditionalResponseTrailer()
are not ignored anymore. #1782BeforeAll
and AfterAll
rather than on Each
. #1801spring-boot-webflux-starter
does not fail to start anymore even if more than one MeterRegistry
exist. #1791HttpData.offset()
has been deprecated. It always returns 0
. #1771 #1797HttpData.of()
methods have been deprecated in favor of HttpData.wrap()
and/or HttpData.copyOf()
. #1797trailingHeaders()
methods in AggregatedHttpMessage
and HttpResult
have been deprecated in favor of trailers()
. #1795StreamMessage
methods which accept boolean withPooledObjects
have been deprecated. Use the methods that accept SubscriptionOption
and specify SubscriptionOption.WITH_POOLED_OBJECTS
. #1700AggregatedHttpMessage
has been split into two subtypes. See 'New features' for more information. #1702 #1795PathMapping
and its related classes have been replaced with Route
and its related classes. See 'New features' for more information. #1789
ServiceWithPathMappings
has been replaced with ServiceWithRoutes
.ClientCacheControl
and ServerCacheControl
have been moved to the com.linecorp.armeria.common
package. #1813 #1816This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation.
#
and /
are now preserved correctly. #1805This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation.
byte[]
, HttpData
, String
or CharSequence
regardless of the content-type
header. #1584, #1745DocService
using COPY AS A CURL COMMAND
button. #196, #1747AbstractUnsafeUnaryGrpcService
. This is for advanced users only. #1766-Dcom.linecorp.armeria.dumpOpenSslInfo=true
. #1777HttpTracingClient
even when the client is used outside of Armeria server. #1767, #1768RequestLogAvailabilityException
is no longer raised in HttpTracling(Client|Service)
when a request timed out. #1769, #1775:scheme
and :authority
headers are set for every received request in the server. #1773, #1776newDecoder()
in StreamDecoderFactory
now takes a ByteBufAllocator
. #1770This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation.
You can now bind your Service to a certain HTTP method or enable HTTP content-type negotiation very easily with the new ServerBuilder.route()
method. #1737
ServerBuilder sb = new ServerBuilder();
sb.route()
.get("/users/{id}")
.delete("/users/{id}")
.post("/users")
.consumes(MediaType.JSON)
.produces(MediaType.JSON_UTF_8)
.build(new MyUserService());
// You can also configure using a lambda expression.
sb.withRoute(b -> {
b.path("/foo")
.build(new MyFooService());
});
It is now also possible to specify different settings for different services using the new route()
method. It means you can specify a large timeout for a certain service only conveniently. #1737
ServerBuilder sb = new ServerBuilder();
sb.route()
.path("/long_poll")
.requestTimeoutMillis(0) // Disable timeout for /service.
.build(new MyLongPollingService());
sb.route()
.path("/get_now")
.build(new MyOtherService()); // Use the default timeout.
```java
We revamped our HttpHeaders
API to make it cleaner and safer. #1731
HttpHeaders
has been split into three types:
RequestHeaders
for request headers with :method
and :path
headerResponseHeaders
for response headers with :status
headerHttpHeaders
for trailers and other headersRequestHeaders
and ResponseHeaders
extend HttpHeaders
.HttpHeaders
and its subtypes are immutable and thus must be built using a factory method or a builder.RequestHeaders reqHdrs = RequestHeaders.of(HttpMethod.GET, "/get",
HttpHeaderNames.ACCEPT, MediaType.JSON_UTF_8);
RequestHeaders newReqHdrs = reqHdrs.toBuilder()
.add("foo", "bar")
.build();
ResponseHeaders resHdrs = ResponseHeaders.of(200 /* OK */);
HttpHeaders hdrs = HttpHeaders.builder()
.add("alice", "bob");
.build();
HttpHeaders newHdrs = hdrs.withMutations(builder -> {
builder.add("charlie", "debora");
});
HttpHeaders
Javadoc for more examples.You can now test your Armeria app with JUnit 5. A new module armeria-testing-junit5
has been added with the following extensions: #1736
com.linecorp.armeria.testing.junit.server.ServerExtension
com.linecorp.armeria.testing.junit.server.SelfSignedCertificateExtension
com.linecorp.armeria.testing.junit.common.EventLoopGroupExtension
com.linecorp.armeria.testing.junit.common.EventLoopExtension
You can now customize the behavior of gRPC JSON marshaller. #1696 #1753
ServerBuilder sb = new ServerBuilder();
sb.service(new GrpcServiceBuilder()
.addService(new MyServiceImpl())
.supportedSerializationFormats(GrpcSerializationFormats.values())
.jsonMarshallerCustomizer(marshaller -> {
marshaller.preservingProtoFieldNames(true);
})
.build());
You can now write a unary gRPC client without depending on grpc-java at all. #1703 #1748 #1751
HelloRequest req = HelloRequest.newBuilder()
.setName("Alice")
.build();
UnaryGrpcClient client = new UnaryGrpcClient(HttpClient.of("http://127.0.0.1:8080"));
byte[] resBytes = client.execute("/com.example.HelloService/Greet",
req.toByteArray()).join();
HelloResponse res = HelloResponse.parseFrom(resBytes);
You can now use GrpcServiceRegistrationBean
to register a gRPC service when using Spring Boot integration. #1749
@Bean
public GrpcServiceRegistrationBean helloService() {
return new GrpcServiceRegistrationBean()
.setServiceName("helloService")
.setService(new GrpcServiceBuilder()
.addService(new HelloService())
.supportedSerializationFormats(GrpcSerializationFormats.values())
.enableUnframedRequests(true)
.build())
.setDecorators(LoggingService.newDecorator())
.setExampleRequests(List.of(ExampleRequest.of(HelloServiceGrpc.SERVICE_NAME,
"Hello",
HelloRequest.newBuilder()
.setName("Armeria")
.build())));
}
You can now use wildcard
pattern when specifying built-in properties in Logback RequestContextExportingAppender
. #489 #1742
CorsDecorator
more than once. #1740HttpTracingClient
and HttpTracingService
now adds a valid addressable http.url
tag. #1733 #1762SessionProtocol
and SerializationFormat
are now added to http.protocol
and http.serfmt
tag instead.armeria-testing-junit4
. Please update your project dependencies. #1736HttpHeaders
as a parameter or a return value have been changed due to the revamped HttpHeaders
API. #1731ServerBuilder
methods were removed:
virtualHost(VirtualHost)
defaultVirtualHost(VirtualHost)
The default prefix found in various configuration properties has been deprecated. Use the property setters without the default prefix. #1737
ServerBuilder sb = new ServerBuilder();
// Do NOT use this:
sb.defaultRequestTimeout(...);
// Use this:
sb.requestTimeout(...);
HttpHeaders.EMPTY
has been deprecated. Use HttpHeaders.of()
.
This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
Armeria is an open-source asynchronous HTTP/2 RPC/REST client/server library built on top of Java 8, Netty, Thrift and gRPC. Its primary goal is to help engineers build high-performance asynchronous microservices that use HTTP/2 as a session layer protocol. Visit the official web site and follow @armeria_project to check out many cool features you can't find in the official gRPC/Thrift implementation.
RequestLog
API, including DNS lookup and socket connect time. #1692
HttpClient client = new HttpClientBuilder("https://example.com/")
.decorator((delegate, ctx, req) -> {
ctx.log().addListener(log -> {
ClientConnectionTimings timings = ClientConnectionTimings.get(log);
System.err.printf("Total time taken: %d ns%n",
timings.connectionAcquisitionDurationNanos());
System.err.printf("DNS lookup: %d ns%n",
timings.dnsResolutionDurationNanos());
System.err.printf("Socket connect:: %d ns%n",
timings.socketConnectDurationNanos());
}, RequestLogAvailability.REQUEST_START);
return delegate.execute(ctx, req);
})
.build();
client.get("/");
SslContext
more conveniently. #1717
ServerBuilder sb = new ServerBuilder();
sb.tls(certChainFile, keyFile, tlsContextBuilder -> {
// Use JDK SSLEngine instead of OpenSSL.
tlsContextBuilder.sslProvider(SslProvider.JDK);
});
Server.stop()
is now able to stop its blockingTaskExecutor
. You have to specify whether to stop the blockingTaskExecutor
you specified or not when calling ServerBuilder.blockingTaskExecutor()
from this release. #1685 #1707
ServerBuilder sb = new ServerBuilder();
// The thread pool will be terminated when the server stops.
sb.blockingTaskExecutor(Executors.newFixedThreadPool(100), true);
RedirectService
has been improved with some API changes. #1725 #1726
RedirectService
preserves the query string by default. The query string of the old location was dropped previously.preserveQueryString
constructor parameter. Specifying false
will let you go back to the previous behavior.SettableHealthChecker
has been improved with some API changes. #1714
SettableHealthChecker
's initial healthiness is now true
. It was false
previously.SettableHealthChecker
.
SettableHealthChecker myHealthChecker = new SettableHealthChecker(false);
ServerBuilder sb = new ServerBuilder();
sb.service("/monitor/health", new HttpHealthCheckService(myHealthChecker));
SettableHealthChecker.setHealthy(boolean)
is now chainable. #1714
// Same with: new SettableHealthChecker(false)
SettableHealthChecker myHealthChecker = new SettableHealthChecker().setHealthy(false);
ServerBuilder sb = new ServerBuilder();
// Add two services under /foo and /bar.
sb.service("prefix:/foo", fooService);
sb.service("prefix:/bar", barService);
// Enable CORS for:
// - GET and POST requests for all resources under http://example.com/foo/
// - GET request for all resources under http://example.com/bar/
sb.decorator(CorsServiceBuilder.forOrigins("http://example.com")
.pathMapping("prefix:/foo")
.allowCredentials()
.allowRequestMethods(HttpMethod.GET, HttpMethod.POST)
.andForOrigins("http://example.com")
.pathMapping("prefix:/bar")
.allowCredentials()
.allowRequestMethods(HttpMethod.GET)
.and()
.newDecorator());
sb.annotatedService(
@CorsDecorator(
origins = "http://example.com",
pathPatterns = "prefix:/foo",
credentialsAllowed = true,
allowedRequestMethods = { HttpMethod.GET, HttpMethod.POST })
@CorsDecorator(
origins = "http://example.com",
pathPatterns = "prefix:/bar",
credentialsAllowed = true,
allowedRequestMethods = { HttpMethod.GET })
new Object() {
...
});
armeria-grpc-protocol
which provides a core functionality required for building a gRPC service, which does not depend on io.grpc:grpc-java
but only on com.google.protobuf:protobuf-java
.AbstractUnaryGrpcService
which allows you to implement a unary gRPC easily without depending on io.grpc:grpc-java
.
class MyUnaryGrpcService extends AbstractUnaryGrpcService {
@Override
protected CompletableFuture<byte[]> handleMessage(byte[] message) {
final MyGrpcRequest req;
try {
req = MyGrpcRequest.parseFrom(message);
} catch (InvalidProtocolBufferException e) {
throw new UncheckedIOException(e);
}
MyGrpcResponse res = MyGrpcResponse.newBuilder()...build();
return CompletableFuture.completedFuture(res.toByteArray());
}
}
# Your application.yml:
armeria:
ports:
- port: 8080
protocol: HTTP
compression:
enabled: true
mime-types: text/*, application/json
excluded-user-agents: some-user-agent, another-user-agent
minResponseSize: 1KB
TwoElementFixedStreamMessage
no longer throws an IllegalReferenceCountException
. #1687 #1695DnsEndpointGroup
does not ignore the search
directive in /etc/resolv.conf
anymore. This fix should be useful for users in Kubernetes environment. #1694 #1697DocService
no longer raises a NullPointerException
for a certain gRPC service metadata. #1705 #1715THttpService
no longer fails to load the service metadata when .thrift
file was compiled with the private-members
option. #1728 #1729THttpService
no longer fails to load the service metadata when .thrift
file defines a service that extends other service. #1734HttpTracingClient
and HttpTracingService
do not fill service name automatically with host names or IP addresses anymore. #1706com.linecorp.armeria.useOpenSsl
flag properly. #1713ServerBuilder.blockingTaskExecutor(Executor)
has been deprecated. Use ServerBuilder.blockingTaskExecutor(Executor, boolean)
. #1685 #1707TextFormatter.epoch()
and appendEpoch()
have been deprecated. Use TextFormatter.epochMillis()
and appendEpochMillis()
. #1692SettableHealthChecker
is now true
. #1714RedirectService
preserves the query string by default. The query string of the old location was dropped previously. #1725 #1726This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:
armeria-spring-boot-autoconfigure
. #1663
# Your application.yml
armeria:
ports:
- port: 8080
protocol: HTTP
- ip: 127.0.0.1
port: 8081
protocol:HTTP
- port: 8443
protocol: HTTPS
ssl:
key-alias: "host.name.com"
key-store: "keystore.jks"
key-store-password: "changeme"
trust-store: "truststore.jks"
trust-store-password: "changeme"
InvalidResponseHeadersException
. #1668EventLoopThread
now implements NonBlocking
tag interface using in Project Reactor. #1665
Schedulers.isInNonBlockingThread()
returns true
when you call in the Armeria EventLoop
s.DocService
. #1667HttpHeaderNames.PREFER
again. #1669IllegalReferenceCountException
is no longer raised when you enable content previews on the client-side. #1690DocService
. #1689doStart()
and doStop()
methods in StartStopSupport
now take a parameter which might be used as a startup and shutdown argument.
DocServiceFilter
when building a DocService
. ServerBuilder sb = new ServerBuilder();
...
sb.serviceUnder("/docs", new DocServiceBuilder()
// Include Thrift services and Annotated services.
.include(DocServiceFilter.ofThrift().or(DocServiceFilter.ofAnnotated()))
// Exclude the method whose name is "foo" in Thrift services.
.exclude(DocServiceFilter.ofThrift().and(DocServiceFilter.ofMethodName("foo")))
.build());
HttpHeaderNames
now forks from Guava's HttpHeaders
instead of Netty's HttpHeaderNames
SystemInfo
utility class in order to get the system information. #1656
// Java version
SystemInfo.javaVersion();
// Hostname
SystemInfo.hostname();
// The current process ID
SystemInfo.pid();
// The current time in microseconds
SystemInfo.currentTimeMicros();
HttpFile
resource path. #1661 #1650
// Will strip the leading slash
HttpFile.ofResource(ClassLoader.getSystemClassLoader(), "/java/lang/Object.class");
ByteBuf
s are no longer leaked when you use Spring WebFlux integration. #1658ByteBuf
if a client closes a connection before reading the body of an HTTP response.DocServicePlugin
interface now has name()
method and generateSpecification()
method signature has changed. #1609
// Before:
ServiceSpecification generateSpecification(Set<ServiceConfig> serviceConfigs);
// After:
String name();
ServiceSpecification generateSpecification(Set<ServiceConfig> serviceConfigs, DocServiceFilter filter);
HttpHeaderNames
were removed, although it is very unlikely to be used by users: #1660Keep-Alive
Proxy-Connection
Content-Transfer-Encoding
cache-control
header value programmatically. #1615
HttpHeaders headers = HttpHeaders.of();
HttpFileBuilder fileBuilder = HttpFileBuilder.of(...);
HttpFileServiceBuilder fileServiceBuilder = HttpFileServiceBuilder.forFileSystem(...);
// Before:
headers.set(HttpHeaderNames.CACHE_CONTROL, "no-cache, no-store, must-revalidate"));
fileBuilder.setHeader(HttpHeaderNames.CACHE_CONTROL,
"max-age=86400, no-cache, must-revalidate");
fileServiceBuilder.setHeader(HttpHeaderNames.CACHE_CONTROL, "public, max-age=3600");
// After:
headers.setObject(HttpHeaderNames.CACHE_CONTROL, ServerCacheControl.DISABLED);
fileBuilder.cacheControl(new ServerCacheControlBuilder()
.maxAgeSeconds(86400)
.noCache()
.mustRevalidate()
.build());
fileServiceBuilder.cacheControl(new ServerCacheControlBuilder()
.cachePublic()
.maxAgeSeconds(3600)
.build());
ServerBuilder sb = new ServerBuilder();
sb.service(new GrpcServiceBuilder().addService(new MyHelloService())
.addService(ProtoReflectionService.newInstance())
.build());
StreamMessage.drailAll(...)
to simply collect all the elements from the StreamMessage
. #1620
HttpResponse res = HttpResponse.of(HttpHeaders.of(HttpStatus.OK)
.contentType(PLAIN_TEXT_UTF_8),
HttpData.ofUtf8("bob"),
HttpHeaders.of(CONTENT_MD5, "hash"));
// Simply collect all the elements.
List<HttpObject> drained = res.drainAll().join();
assertThat(drained).containsExactly(
HttpHeaders.of(HttpStatus.OK)
.contentType(PLAIN_TEXT_UTF_8),
HttpData.of(StandardCharsets.UTF_8, "bob"),
HttpHeaders.of(CONTENT_MD5, "hash"));
RequestLog
. #1614SamlService
to inform the reasons of the failure. #1629end-of-line
character. #1610ServiceWithPathMappings
. #1627contentPreview
is not working correctly. #1624StackOverFlowError
is raised while finding annotations in AnnotationUtil
. #1635HttpHeaders
is added to get()
in HttpVfs
as a parameter. #1615
HttpHeaders
when building an HttpFile
.