/** * Sets the 'content-length' header to the response. */ private static void setContentLength(HttpRequest req, HttpHeaders headers, int contentLength) { // https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 // prohibits to send message body for below cases. // and in those cases, content should be empty. if (req.method() == HttpMethod.HEAD || ArmeriaHttpUtil.isContentAlwaysEmpty(headers.status())) { return; } headers.setInt(HttpHeaderNames.CONTENT_LENGTH, contentLength); }
@Override public void messageRead(ByteBufOrStream message) { // We know there is only one message in total, so don't bother with checking endOfStream // We also know that we don't support compression, so this is always a ByteBuffer. final HttpData unframedContent = new ByteBufHttpData(message.buf(), true); unframedHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, unframedContent.length()); res.complete(HttpResponse.of(unframedHeaders, unframedContent)); }
/** * Creates a new HTTP message. * * @param informationals the informational class (1xx) HTTP headers * @param headers the HTTP headers * @param content the content of the HTTP message * @param trailingHeaders the trailing HTTP headers */ static AggregatedHttpMessage of(Iterable<HttpHeaders> informationals, HttpHeaders headers, HttpData content, HttpHeaders trailingHeaders) { requireNonNull(informationals, "informationals"); requireNonNull(headers, "headers"); requireNonNull(content, "content"); requireNonNull(trailingHeaders, "trailingHeaders"); // Set the 'content-length' header if possible. final HttpStatus status = headers.status(); final HttpHeaders newHeaders; if (status != null) { // Response newHeaders = setOrRemoveContentLength(headers, content, trailingHeaders); } else { // Request newHeaders = headers.toMutable(); if (content.isEmpty()) { newHeaders.remove(CONTENT_LENGTH); } else { newHeaders.setInt(CONTENT_LENGTH, content.length()); } } return new DefaultAggregatedHttpMessage(ImmutableList.copyOf(informationals), newHeaders, content, trailingHeaders); }
private void fail(int id, HttpResponseStatus status) { discarding = true; req = null; final HttpData data = HttpData.ofUtf8(status.toString()); final com.linecorp.armeria.common.HttpHeaders headers = com.linecorp.armeria.common.HttpHeaders.of(status.code()); headers.set(HttpHeaderNames.CONNECTION, "close"); headers.setObject(HttpHeaderNames.CONTENT_TYPE, MediaType.PLAIN_TEXT_UTF_8); headers.setInt(HttpHeaderNames.CONTENT_LENGTH, data.length()); writer.writeHeaders(id, 1, headers, false); writer.writeData(id, 1, data, true).addListener(ChannelFutureListener.CLOSE); }
HttpHeaders.of(status) .contentType(mediaType) .setInt(HttpHeaderNames.CONTENT_LENGTH, content.length());
headers.remove(CONTENT_LENGTH); } else { headers.setInt(CONTENT_LENGTH, content.length());
@Test public void missingContentType() throws Exception { final HttpRequest req = HttpRequest.of(HttpMethod.POST, "/grpc.testing.TestService.UnaryCall"); final ServiceRequestContext ctx = ServiceRequestContext.of(req); final HttpResponse response = grpcService.doPost(ctx, req); assertThat(response.aggregate().get()).isEqualTo(AggregatedHttpMessage.of( HttpHeaders.of(HttpStatus.UNSUPPORTED_MEDIA_TYPE) .contentType(MediaType.PLAIN_TEXT_UTF_8) .setInt(HttpHeaderNames.CONTENT_LENGTH, 39), HttpData.ofUtf8("Missing or invalid Content-Type header."))); }
@Test public void badContentType() throws Exception { final HttpRequest req = HttpRequest.of( HttpHeaders.of(HttpMethod.POST, "/grpc.testing.TestService.UnaryCall") .contentType(MediaType.JSON_UTF_8)); final ServiceRequestContext ctx = ServiceRequestContext.of(req); final HttpResponse response = grpcService.doPost(ctx, req); assertThat(response.aggregate().get()).isEqualTo(AggregatedHttpMessage.of( HttpHeaders.of(HttpStatus.UNSUPPORTED_MEDIA_TYPE) .contentType(MediaType.PLAIN_TEXT_UTF_8) .setInt(HttpHeaderNames.CONTENT_LENGTH, 39), HttpData.ofUtf8("Missing or invalid Content-Type header."))); }
mutable.setInt(HttpHeaderNames.CONTENT_LENGTH, content.length()); return mutable.asImmutable(); } else {
@Test public void pathMissingSlash() throws Exception { final HttpRequest req = HttpRequest.of( HttpHeaders.of(HttpMethod.POST, "/grpc.testing.TestService.UnaryCall") .set(HttpHeaderNames.CONTENT_TYPE, "application/grpc+proto")); final PathMappingResult pathMappingResult = PathMappingResult.of("grpc.testing.TestService.UnaryCall"); final ServiceRequestContext ctx = ServiceRequestContextBuilder.of(req) .pathMappingResult(pathMappingResult) .build(); final HttpResponse response = grpcService.doPost(ctx, req); assertThat(response.aggregate().get()).isEqualTo(AggregatedHttpMessage.of( HttpHeaders.of(HttpStatus.BAD_REQUEST) .contentType(MediaType.PLAIN_TEXT_UTF_8) .setInt(HttpHeaderNames.CONTENT_LENGTH, 13), HttpData.ofUtf8("Invalid path."))); }
@Test public void missingMethod() throws Exception { final HttpRequest req = HttpRequest.of( HttpHeaders.of(HttpMethod.POST, "/grpc.testing.TestService/FooCall") .set(HttpHeaderNames.CONTENT_TYPE, "application/grpc+proto")); final PathMappingResult pathMappingResult = PathMappingResult.of("/grpc.testing.TestService/FooCall"); final ServiceRequestContext ctx = ServiceRequestContextBuilder.of(req) .pathMappingResult(pathMappingResult) .build(); final HttpResponse response = grpcService.doPost(ctx, req); assertThat(response.aggregate().get()).isEqualTo(AggregatedHttpMessage.of( HttpHeaders.of(HttpStatus.OK) .set(HttpHeaderNames.CONTENT_TYPE, "application/grpc+proto") .set(HttpHeaderNames.of("grpc-status"), "12") .set(HttpHeaderNames.of("grpc-message"), "Method not found: grpc.testing.TestService/FooCall") .setInt(HttpHeaderNames.CONTENT_LENGTH, 0), HttpData.EMPTY_DATA)); }
@Override public void messageRead(ByteBufOrStream message) { // We know there is only one message in total, so don't bother with checking endOfStream // We also know that we don't support compression, so this is always a ByteBuffer. final HttpData unframedContent = new ByteBufHttpData(message.buf(), true); unframedHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, unframedContent.length()); res.complete(HttpResponse.of(unframedHeaders, unframedContent)); }