You're seeing the release note of an old version. Check out the latest release note.
v0.80.0
February 19, 2019
New features
-
A user now can see the content of HTTP request/response in logs. #1574
ServerBuilder sb = new ServerBuilder();// Enables previewing the content with the maximum length of 100 for textual contents.sb.contentPreview(100);// A user can use their customized previewer factory.sb.contentPreviewerFactory((ctx, headers) -> {return ContentPreviewer.ofBinary(100, byteBuf -> {byte[] contents = new byte[Math.min(byteBuf.readableBytes(), 100)];byteBuf.readBytes(contents);return BaseEncoding.base16().encode(contents);});}); -
Added
ClientRequestContextBuilderandServiceRequestContextBuilder. #1548- A user can create a mock of
RequestContext. - A user can emulate an incoming request and feed it into his or her processing pipeline.
@Testpublic void testService() throws Exception {// GivenHttpRequest req = HttpRequest.of(HttpMethod.POST, "/greet",MediaType.JSON_UTF_8,"{ \"name\": \"foo\" }");ServiceRequestContext sctx = ServiceRequestContext.of(req);// WhenHttpResponse res = service.serve(sctx, req);// ThenAggregatedHttpMessage aggregatedRes = res.aggregate().get();assertEquals(200, aggregatedRes.status().code());} - A user can create a mock of
-
A user can use
@CorsDecoratorin annotated services. #1547sb.annotatedService("/cors6", new Object() {@Get("/any/get")@CorsDecorator(origins = "*", exposedHeaders = { "expose_header_1", "expose_header_2" },allowedRequestHeaders = { "allow_request_1", "allow_request_2" },allowedRequestMethods = HttpMethod.GET, maxAge = 3600,preflightRequestHeaders = {@AdditionalHeader(name = "x-preflight-cors", value = "Hello CORS")})public HttpResponse anyoneGet() {return HttpResponse.of(HttpStatus.OK);}} -
Added
ClientFactoryBuilder.domainNameResolverCustomizer()so that a user can customize the resolver easily. #1553ClientFactory f = new ClientFactoryBuilder().domainNameResolverCustomizer(resolverBuilder -> {resolverBuilder.maxQueriesPerResolve(10);resolverBuilder.traceEnabled(false);}).build(); -
A user can define a custom annotation which attaches other annotations for simplicity. #1560
// Define a custom annotation:@ProducesJson@LoggingDecorator@interface MyApiSpecification {}// Apply it to the annotated HTTP service:@Get("/api")@MyApiSpecification // You can use one annotation which holds other other annotations.public Something getSomething() {} -
Added
@AdditionalHeaderand@AdditionalTrailerto insert headers easily in annotated services. #1555 -
Added a way to add multiple gRPC services with a single method call. #1563
// BeforeGrpcService s = new GrpcServiceBuilder().addService(a).addService(b).build();// AfterGrpcService s = new GrpcServiceBuilder().addServices(a, b).build(); -
Added more shortcut methods for convenience. #1576
HttpRequest req = ...;AggregatedHttpMessage aggregated = ...;MediaType contentType;String content;// BeforecontentType = req.headers().contentType();contentType = aggregated.headers().contentType();content = aggregated.content().toStringUtf8();// AftercontentType = req.contentType();contentType = aggregated.contentType();content = aggregated.contentUtf8(); -
RequestObjectis shown inDocService. #1557 -
Added
verboseSocketExceptionsflag so that a user can ignore harmless socket-related error message. #1577 -
Added automatic directory listing generation to
HttpFileService. #1573 -
Added
armeria-spring-boot-actuatordependency. #1578- Works without Spring Web or Webflux.
-
Added metrics related to timeouts. #1589
-
Added
responseCauseSanitizertoLoggingDecoratorBuilder. #1594- A user can sanitize the stack trace of
RequestLog.responseCause()or avoid logging the stack trace completely.
ServerBuilder sb = ...final Function<Throwable, Throwable> responseCauseSanitizer = cause -> {if (cause instanceof AnticipatedException) {return null; // Do not log when AnticipatedException is raised.}return cause;};sb.decorator(new LoggingServiceBuilder().requestLogLevel(LogLevel.INFO).successfulResponseLogLevel(LogLevel.INFO).responseCauseSanitizer(responseCauseSanitizer).newDecorator()); - A user can sanitize the stack trace of
-
A user can easily send Server-Sent Events. #1551
public class MyAnnotatedService {@Get("/publisher")@ProducesEventStreampublic Publisher<ServerSentEvent<?>> publisher() {return Flux.just(ServerSentEvent.ofData("foo"),ServerSentEvent.ofData("bar"),ServerSentEvent.ofData("baz"),ServerSentEvent.ofData("qux"));}}
Improvements
- User-friendly message when
400 Bad Requesthappens. #1575 - Enabled DNS query traces by default. #1553
- Added
armeria-retry-countheader whenRetryingClientis used. #1593
Bug fixes
- Fixed a bug where
httpStatustag is not set properly. #1559 - Do not set
Content-lengthheader when HTTP trailers exist. #1566 - Fixed a bug where max request length is not set correctly in
GrpcServicewhen the value is0orLong.MAX_VALUE. #1549 - Fixed a but where gRPC JSON marshaller is initialized even when unnecessary. #1558
- Fixed a bug where gRPC callbacks are not executed in order. #1600
Breaking Change
- The
HttpHeadersinAggregatedHttpMessageis immutable.- You should call
headers.toMutable()to set or remove a header.
- You should call
Deprecations
RequestContext.isTimedOut()has been deprecated. #1589- Use
ServiceRequestContext.isTimedOut()instead.
- Use
Dependencies
- Bouncy Castle 1.60 -> 1.61
- Brave 5.6.0 -> 5.6.1
- java-jwt 3.5.0 -> 3.7.0
- Micrometer 1.1.2 -> 1.1.3
- Netty 4.1.32 -> 4.1.33
- Project Reactor 3.2.5 -> 3.2.6
- protobuf-jackson 0.3.0 -> 0.3.1
- RxJava 2.2.5 -> 2.2.6
- Thrift 0.11.0 -> 0.12.0
- Tomcat 9.0.14 -> 9.0.16, 8.5.37 -> 8.5.38
- spring-boot-starter-actuator has been removed from the transitive dependencies.