@Override public MediaType contentType() { return delegate.contentType(); }
@Nullable @VisibleForTesting static MediaType resolveConsumeType(HttpHeaders headers) { final MediaType contentType = headers.contentType(); if (contentType != null) { return contentType; } return null; }
private HttpHeaders addNegotiatedResponseMediaType(ServiceRequestContext ctx, HttpHeaders headers) { final MediaType negotiatedResponseMediaType = ctx.negotiatedResponseMediaType(); if (negotiatedResponseMediaType == null || headers.contentType() != null) { // Do not overwrite 'content-type'. return headers; } return headers.isImmutable() ? HttpHeaders.copyOf(headers).contentType(negotiatedResponseMediaType) : headers.contentType(negotiatedResponseMediaType); }
/** * Returns whether the request should be aggregated. */ static boolean aggregationRequired(AggregationStrategy strategy, HttpRequest req) { requireNonNull(strategy, "strategy"); switch (strategy) { case ALWAYS: return true; case FOR_FORM_DATA: return isFormData(req.headers().contentType()); } return false; }
/** * Creates a new HTTP response of the specified {@link HttpStatus}. * * @param mediaType the {@link MediaType} of the response content * @param content the content of the response * @param trailingHeaders the trailing HTTP headers */ static AggregatedHttpMessage of(HttpStatus status, MediaType mediaType, HttpData content, HttpHeaders trailingHeaders) { requireNonNull(status, "status"); requireNonNull(mediaType, "mediaType"); requireNonNull(content, "content"); requireNonNull(trailingHeaders, "trailingHeaders"); final HttpHeaders headers = HttpHeaders.of(status).contentType(mediaType); return of(headers, content, trailingHeaders); }
/** * Creates a new HTTP response of the specified {@link HttpStatus} and closes the stream. * * @param mediaType the {@link MediaType} of the response content * @param content the content of the response * @param trailingHeaders the trailing HTTP headers */ static HttpResponse of(HttpStatus status, MediaType mediaType, HttpData content, HttpHeaders trailingHeaders) { requireNonNull(status, "status"); requireNonNull(mediaType, "mediaType"); requireNonNull(content, "content"); final HttpHeaders headers = HttpHeaders.of(status).contentType(mediaType); return of(headers, content, trailingHeaders); }
/** * Creates a new HTTP request and closes the stream. * * @param method the HTTP method of the request * @param path the path of the request * @param mediaType the {@link MediaType} of the request content * @param content the content of the request * @param trailingHeaders the trailing HTTP headers */ static HttpRequest of(HttpMethod method, String path, MediaType mediaType, HttpData content, HttpHeaders trailingHeaders) { requireNonNull(method, "method"); requireNonNull(path, "path"); requireNonNull(mediaType, "mediaType"); return of(HttpHeaders.of(method, path).contentType(mediaType), content, trailingHeaders); }
@Nullable private SerializationFormat determineSerializationFormat(HttpRequest req) { final HttpHeaders headers = req.headers(); final MediaType contentType = headers.contentType(); final SerializationFormat serializationFormat; if (contentType != null) { serializationFormat = findSerializationFormat(contentType); if (serializationFormat == null) { return null; } } else { serializationFormat = defaultSerializationFormat(); } return serializationFormat; }
HttpParameters httpParameters() { HttpParameters result = httpParameters; if (result == null) { synchronized (this) { result = httpParameters; if (result == null) { httpParameters = result = httpParametersOf(context.query(), request.headers().contentType(), message); } } } return result; }
@Nullable @Override public Object convertRequest(ServiceRequestContext ctx, AggregatedHttpMessage request, Class<?> expectedResultType) throws Exception { final MediaType mediaType = request.headers().contentType(); if (mediaType != null && mediaType.is(MediaType.PLAIN_TEXT_UTF_8)) { return new Request(request.content().toStringUtf8()); } return RequestConverterFunction.fallthrough(); } }
@Override public void onComplete() { final Iterator<HttpObject> it = received.build().iterator(); final HttpHeaders headers = (HttpHeaders) it.next(); assertThat(headers.status()).isEqualTo(HttpStatus.OK); assertThat(headers.contentType()).isEqualTo(MediaType.JSON_SEQ); // JSON Text Sequences: *(Record Separator[0x1E] JSON-text Line Feed[0x0A]) assertThat(((HttpData) it.next()).array()) .isEqualTo(new byte[] { 0x1E, '\"', 'a', '\"', 0x0A }); assertThat(((HttpData) it.next()).array()) .isEqualTo(new byte[] { 0x1E, '\"', 'b', '\"', 0x0A }); assertThat(((HttpData) it.next()).array()) .isEqualTo(new byte[] { 0x1E, '\"', 'c', '\"', 0x0A }); assertThat(((HttpData) it.next()).isEmpty()).isTrue(); assertThat(it.hasNext()).isFalse(); isFinished.set(true); } });
@Test public void shouldRespondAuthnRequest_HttpPost() throws Exception { final AggregatedHttpMessage resp = client.get("/post").aggregate().join(); assertThat(resp.status()).isEqualTo(HttpStatus.OK); assertThat(resp.headers().contentType()).isEqualTo(MediaType.HTML_UTF_8); final Document doc = Jsoup.parse(resp.content().toStringUtf8()); assertThat(doc.body().attr("onLoad")).isEqualTo("document.forms[0].submit()"); // SAMLRequest will be posted to the IdP's SSO URL. final Element form = doc.body().child(0); assertThat(form.attr("method")).isEqualTo("post"); assertThat(form.attr("action")).isEqualTo("http://idp.example.com/saml/sso/post"); assertThat(form.child(0).attr("name")).isEqualTo(SAML_REQUEST); assertThat(form.child(1).attr("name")).isEqualTo(RELAY_STATE); }
@Test public void shouldConsumeLogoutRequest_HttpPost() throws Exception { final LogoutRequest logoutRequest = getLogoutRequest("http://" + spHostname + ':' + rule.httpPort() + "/saml/slo/post", "http://idp.example.com/post"); final AggregatedHttpMessage msg = sendViaHttpPostBindingProtocol("/saml/slo/post", SAML_REQUEST, logoutRequest); assertThat(msg.status()).isEqualTo(HttpStatus.OK); assertThat(msg.headers().contentType()).isEqualTo(MediaType.HTML_UTF_8); final Document doc = Jsoup.parse(msg.content().toStringUtf8()); assertThat(doc.body().attr("onLoad")).isEqualTo("document.forms[0].submit()"); // SAMLResponse will be posted to the IdP's logout response URL. final Element form = doc.body().child(0); assertThat(form.attr("method")).isEqualTo("post"); assertThat(form.attr("action")).isEqualTo("http://idp.example.com/saml/slo/post"); assertThat(form.child(0).attr("name")).isEqualTo(SAML_RESPONSE); }
@Test public void shouldGetNotFound() { protocols.forEach(scheme -> { final HttpClient client = HttpClient.of(clientFactory, scheme + "://example.com:" + port); assertThat(client.get("/route2").aggregate().join().status()).isEqualTo(HttpStatus.NOT_FOUND); assertThat(client.execute( HttpHeaders.of(HttpMethod.POST, "/route2") .contentType(com.linecorp.armeria.common.MediaType.PLAIN_TEXT_UTF_8), HttpData.of("text".getBytes())).aggregate().join().status()) .isEqualTo(HttpStatus.NOT_FOUND); }); } }
@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."))); }
@Test public void single() { final HttpClient client = HttpClient.of(rule.uri("/single")); AggregatedHttpMessage msg; msg = client.get("/string").aggregate().join(); assertThat(msg.headers().contentType()).isEqualTo(MediaType.PLAIN_TEXT_UTF_8); assertThat(msg.content().toStringUtf8()).isEqualTo("a"); msg = client.get("/json").aggregate().join(); assertThat(msg.headers().contentType()).isEqualTo(MediaType.JSON_UTF_8); assertThatJson(msg.content().toStringUtf8()).isStringEqualTo("a"); msg = client.get("/error").aggregate().join(); assertThat(msg.headers().status()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); }
@Test public void maybe() { final HttpClient client = HttpClient.of(rule.uri("/maybe")); AggregatedHttpMessage msg; msg = client.get("/string").aggregate().join(); assertThat(msg.headers().contentType()).isEqualTo(MediaType.PLAIN_TEXT_UTF_8); assertThat(msg.content().toStringUtf8()).isEqualTo("a"); msg = client.get("/json").aggregate().join(); assertThat(msg.headers().contentType()).isEqualTo(MediaType.JSON_UTF_8); assertThatJson(msg.content().toStringUtf8()).isStringEqualTo("a"); msg = client.get("/empty").aggregate().join(); assertThat(msg.headers().status()).isEqualTo(HttpStatus.OK); assertThat(msg.content().isEmpty()).isTrue(); msg = client.get("/error").aggregate().join(); assertThat(msg.headers().status()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); }
@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 shouldGetHelloFromRouter() throws Exception { protocols.forEach(scheme -> { final HttpClient client = HttpClient.of(clientFactory, scheme + "://example.com:" + port); final AggregatedHttpMessage res = client.get("/route").aggregate().join(); assertThat(res.content().toStringUtf8()).isEqualTo("route"); final AggregatedHttpMessage res2 = client.execute(HttpHeaders.of(HttpMethod.POST, "/route2") .contentType(com.linecorp.armeria.common.MediaType.JSON_UTF_8), HttpData.of("{\"a\":1}".getBytes())).aggregate().join(); assertThatJson(res2.content().toStringUtf8()).isArray() .ofLength(1) .thatContains("route"); }); }
@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."))); }