diff --git a/http/http-client-annotation-processor/src/main/java/ru/tinkoff/kora/http/client/annotation/processor/ClientClassGenerator.java b/http/http-client-annotation-processor/src/main/java/ru/tinkoff/kora/http/client/annotation/processor/ClientClassGenerator.java index 63c623146..51cee4373 100644 --- a/http/http-client-annotation-processor/src/main/java/ru/tinkoff/kora/http/client/annotation/processor/ClientClassGenerator.java +++ b/http/http-client-annotation-processor/src/main/java/ru/tinkoff/kora/http/client/annotation/processor/ClientClassGenerator.java @@ -11,7 +11,7 @@ import ru.tinkoff.kora.http.client.common.HttpClientException; import ru.tinkoff.kora.http.client.common.HttpClientResponseException; import ru.tinkoff.kora.http.client.common.annotation.ResponseCodeMapper; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper; import ru.tinkoff.kora.http.client.common.response.HttpClientResponse; import ru.tinkoff.kora.http.client.common.response.HttpClientResponseMapper; @@ -91,15 +91,15 @@ private MethodSpec buildMethod(MethodData methodData) { var httpRoute = method.getAnnotation(HttpRoute.class); b.addCode(""" var _client = this.$L; - var _requestBuilder = new $T($S, this.$LUrl) + var _requestBuilder = $T.of($S, this.$LUrl) .requestTimeout(this.$L); - """, methodClientName, HttpClientRequestBuilder.class, httpRoute.method(), method.getSimpleName(), methodRequestTimeout); + """, methodClientName, HttpClientRequest.class, httpRoute.method(), method.getSimpleName(), methodRequestTimeout); for (var parameter : methodData.parameters()) { if (parameter instanceof Parameter.PathParameter path) { if (requiresConverter(path.parameter().asType())) { - b.addCode("_requestBuilder.templateParam($S, $L.convert($L));\n", path.pathParameterName(), getConverterName(methodData, path.parameter()), path.parameter()); + b.addCode("_requestBuilder.pathParam($S, $L.convert($L));\n", path.pathParameterName(), getConverterName(methodData, path.parameter()), path.parameter()); } else { - b.addCode("_requestBuilder.templateParam($S, $T.toString($L));\n", path.pathParameterName(), Objects.class, path.parameter()); + b.addCode("_requestBuilder.pathParam($S, $T.toString($L));\n", path.pathParameterName(), Objects.class, path.parameter()); } } if (parameter instanceof Parameter.HeaderParameter header) { diff --git a/http/http-client-annotation-processor/src/test/java/ru/tinkoff/kora/http/client/annotation/processor/client/ClientWithMappers.java b/http/http-client-annotation-processor/src/test/java/ru/tinkoff/kora/http/client/annotation/processor/client/ClientWithMappers.java index 920841c88..c27dbf7ae 100644 --- a/http/http-client-annotation-processor/src/test/java/ru/tinkoff/kora/http/client/annotation/processor/client/ClientWithMappers.java +++ b/http/http-client-annotation-processor/src/test/java/ru/tinkoff/kora/http/client/annotation/processor/client/ClientWithMappers.java @@ -5,7 +5,7 @@ import ru.tinkoff.kora.common.Tag; import ru.tinkoff.kora.http.client.common.annotation.HttpClient; import ru.tinkoff.kora.http.client.common.annotation.ResponseCodeMapper; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper; import ru.tinkoff.kora.http.client.common.response.HttpClientResponse; import ru.tinkoff.kora.http.client.common.response.HttpClientResponseMapper; @@ -54,7 +54,7 @@ record Contributor(String login, int contributions) {} class IssueRequestMapper implements HttpClientRequestMapper { @Override - public HttpClientRequestBuilder apply(Request request) { + public HttpClientRequest.Builder apply(Request request) { return request.builder().body("TEST".getBytes(StandardCharsets.UTF_8)); } } diff --git a/http/http-client-async/src/main/java/ru/tinkoff/kora/http/client/async/AsyncHttpClient.java b/http/http-client-async/src/main/java/ru/tinkoff/kora/http/client/async/AsyncHttpClient.java index 0a5d49580..e9cd17109 100644 --- a/http/http-client-async/src/main/java/ru/tinkoff/kora/http/client/async/AsyncHttpClient.java +++ b/http/http-client-async/src/main/java/ru/tinkoff/kora/http/client/async/AsyncHttpClient.java @@ -55,7 +55,7 @@ private Mono processRequest(Context context, HttpClientReque for (var header : request.headers()) { clientHeaders.add(header.getKey(), header.getValue()); } - var uri = Uri.create(request.resolvedUri()); + var uri = Uri.create(request.uriResolved()); var requestBuilder = new RequestBuilder(request.method()) .setUri(uri) .setHeaders(clientHeaders); diff --git a/http/http-client-async/src/main/java/ru/tinkoff/kora/http/client/async/AsyncHttpClientHeaders.java b/http/http-client-async/src/main/java/ru/tinkoff/kora/http/client/async/AsyncHttpClientHeaders.java index d5c5dddd9..100a3a865 100644 --- a/http/http-client-async/src/main/java/ru/tinkoff/kora/http/client/async/AsyncHttpClientHeaders.java +++ b/http/http-client-async/src/main/java/ru/tinkoff/kora/http/client/async/AsyncHttpClientHeaders.java @@ -10,6 +10,7 @@ import java.util.Set; public class AsyncHttpClientHeaders implements HttpHeaders { + private final io.netty.handler.codec.http.HttpHeaders headers; public AsyncHttpClientHeaders(io.netty.handler.codec.http.HttpHeaders headers) { @@ -62,4 +63,9 @@ public Map.Entry> next() { } }; } + + @Override + public String toString() { + return headers.toString(); + } } diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/FormMultipartClientRequestMapper.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/FormMultipartClientRequestMapper.java index dcd2588b5..c63df6d70 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/FormMultipartClientRequestMapper.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/FormMultipartClientRequestMapper.java @@ -1,12 +1,12 @@ package ru.tinkoff.kora.http.client.common.form; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper; import ru.tinkoff.kora.http.common.form.FormMultipart; public final class FormMultipartClientRequestMapper implements HttpClientRequestMapper { @Override - public HttpClientRequestBuilder apply(Request request) { + public HttpClientRequest.Builder apply(Request request) { return MultipartWriter.write(request.builder(), request.parameter().parts()); } } diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/FormUrlEncodedClientRequestMapper.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/FormUrlEncodedClientRequestMapper.java index f5afc6bf7..569e24a7c 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/FormUrlEncodedClientRequestMapper.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/FormUrlEncodedClientRequestMapper.java @@ -1,12 +1,12 @@ package ru.tinkoff.kora.http.client.common.form; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper; import ru.tinkoff.kora.http.common.form.FormUrlEncoded; public final class FormUrlEncodedClientRequestMapper implements HttpClientRequestMapper { @Override - public HttpClientRequestBuilder apply(Request request) { + public HttpClientRequest.Builder apply(Request request) { var writer = new UrlEncodedWriter(); for (var part : request.parameter()) { for (var value : part.values()) { diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/MultipartWriter.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/MultipartWriter.java index 7291f2708..61abd4f63 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/MultipartWriter.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/MultipartWriter.java @@ -2,7 +2,7 @@ import reactor.core.Fuseable; import reactor.core.publisher.Flux; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; import ru.tinkoff.kora.http.common.form.FormMultipart; import java.nio.ByteBuffer; @@ -13,11 +13,11 @@ public class MultipartWriter { private static final ByteBuffer RN_BUF = StandardCharsets.US_ASCII.encode("\r\n"); - public static HttpClientRequestBuilder write(HttpClientRequestBuilder b, List parts) { + public static HttpClientRequest.Builder write(HttpClientRequest.Builder b, List parts) { return write(b, "blob:" + UUID.randomUUID(), parts); } - public static HttpClientRequestBuilder write(HttpClientRequestBuilder b, String boundary, List parts) { + public static HttpClientRequest.Builder write(HttpClientRequest.Builder b, String boundary, List parts) { var boundaryBuff = StandardCharsets.US_ASCII.encode("--" + boundary); var body = Flux.fromIterable(parts).concatMap(part -> { diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/UrlEncodedWriter.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/UrlEncodedWriter.java index 8131c89f7..0f438c2a8 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/UrlEncodedWriter.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/form/UrlEncodedWriter.java @@ -1,6 +1,7 @@ package ru.tinkoff.kora.http.client.common.form; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; + +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; import java.io.ByteArrayOutputStream; import java.net.URLEncoder; @@ -18,7 +19,7 @@ public void add(String key, String value) { this.baos.writeBytes(URLEncoder.encode(value, StandardCharsets.UTF_8).getBytes(StandardCharsets.UTF_8)); } - public HttpClientRequestBuilder write(HttpClientRequestBuilder b) { + public HttpClientRequest.Builder write(HttpClientRequest.Builder b) { var data = this.baos.toByteArray(); return b .header("content-type", "application/x-www-form-urlencoded") diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequest.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequest.java index b3224cea6..b624141f9 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequest.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequest.java @@ -4,90 +4,127 @@ import ru.tinkoff.kora.http.common.HttpHeaders; import ru.tinkoff.kora.http.common.HttpMethod; -import javax.annotation.Nullable; +import javax.annotation.Nonnull; import java.nio.ByteBuffer; +import java.time.Duration; +import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.UUID; public interface HttpClientRequest { + String method(); String uriTemplate(); - List queryParams(); + String uriResolved(); + + Map> queryParams(); - List templateParams(); + Map pathParams(); HttpHeaders headers(); Flux body(); - String resolvedUri(); - String authority(); String operation(); + /** + * @return request timeout in millis + */ int requestTimeout(); - record TemplateParam(String name, String value) {} - - record QueryParam(String name, @Nullable String value) {} - - default HttpClientRequestBuilder toBuilder() { + default Builder toBuilder() { return new HttpClientRequestBuilder(this); } - static HttpClientRequestBuilder get(String path) { + static Builder get(String path) { return new HttpClientRequestBuilder(HttpMethod.GET, path); } - static HttpClientRequestBuilder head(String path) { + static Builder head(String path) { return new HttpClientRequestBuilder(HttpMethod.HEAD, path); } - static HttpClientRequestBuilder post(String path) { + static Builder post(String path) { return new HttpClientRequestBuilder(HttpMethod.POST, path); } - static HttpClientRequestBuilder put(String path) { + static Builder put(String path) { return new HttpClientRequestBuilder(HttpMethod.PUT, path); } - static HttpClientRequestBuilder delete(String path) { + static Builder delete(String path) { return new HttpClientRequestBuilder(HttpMethod.DELETE, path); } - static HttpClientRequestBuilder connect(String path) { + static Builder connect(String path) { return new HttpClientRequestBuilder(HttpMethod.CONNECT, path); } - static HttpClientRequestBuilder options(String path) { + static Builder options(String path) { return new HttpClientRequestBuilder(HttpMethod.OPTIONS, path); } - static HttpClientRequestBuilder trace(String path) { + static Builder trace(String path) { return new HttpClientRequestBuilder(HttpMethod.TRACE, path); } - static HttpClientRequestBuilder patch(String path) { + static Builder patch(String path) { return new HttpClientRequestBuilder(HttpMethod.PATCH, path); } - static HttpClientRequestBuilder of(String method, String path) { + static Builder of(String method, String path) { return new HttpClientRequestBuilder(method, path); } + interface Builder { + + Builder uriTemplate(String uriTemplate); + + Builder queryParam(String name); + + Builder queryParam(String name, String value); + + Builder queryParam(String name, Collection value); + + Builder queryParam(String name, Integer value); + + Builder queryParam(String name, Long value); + + Builder queryParam(String name, Boolean value); + + Builder queryParam(String name, UUID value); + + Builder pathParam(String name, @Nonnull String value); - record Default( - String method, - String uriTemplate, - List queryParams, - List templateParams, - HttpHeaders headers, - Flux body, - int requestTimeout, - String resolvedUri, - String authority, - String operation - ) implements HttpClientRequest {} + Builder pathParam(String name, @Nonnull Collection value); + + Builder pathParam(String name, int value); + + Builder pathParam(String name, long value); + + Builder pathParam(String name, boolean value); + + Builder pathParam(String name, @Nonnull UUID value); + + Builder header(String name, String value); + + Builder requestTimeout(int timeoutInMillis); + + Builder requestTimeout(Duration requestTimeout); + + Builder body(Flux body); + + Builder body(ByteBuffer body); + + Builder body(byte[] body); + + Builder headers(HttpHeaders headers); + + HttpClientRequest build(); + } } diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestBuilder.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestBuilder.java index 7edc0acf8..f3c561a4f 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestBuilder.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestBuilder.java @@ -3,201 +3,248 @@ import reactor.core.publisher.Flux; import ru.tinkoff.kora.http.common.HttpHeaders; +import javax.annotation.Nonnull; import java.net.URI; import java.net.URLEncoder; import java.nio.ByteBuffer; +import java.time.Duration; import java.util.*; import static java.nio.charset.StandardCharsets.UTF_8; -public class HttpClientRequestBuilder { - private String method; +final class HttpClientRequestBuilder implements HttpClientRequest.Builder { + private final String method; private String uriTemplate; - private List templateParams = new ArrayList<>(); - private List queryParams = new ArrayList<>(); - private HashMap> headers = new HashMap<>(); + private Map pathParams = new LinkedHashMap<>(); + private Map> queryParams = new LinkedHashMap<>(); + private Map> headers = new LinkedHashMap<>(); private Flux body = Flux.empty(); private int requestTimeout = -1; - public HttpClientRequestBuilder(String method, String uriTemplate) { + HttpClientRequestBuilder(String method, String uriTemplate) { this.method = method; this.uriTemplate = uriTemplate; } - public HttpClientRequestBuilder(HttpClientRequest httpClientRequest) { + HttpClientRequestBuilder(HttpClientRequest httpClientRequest) { this.method = httpClientRequest.method(); this.uriTemplate = httpClientRequest.uriTemplate(); - this.templateParams = httpClientRequest.templateParams(); + this.pathParams = httpClientRequest.pathParams(); this.queryParams = httpClientRequest.queryParams(); this.headers = fromHeaders(httpClientRequest.headers()); this.body = httpClientRequest.body(); this.requestTimeout = httpClientRequest.requestTimeout(); } - + @Override public HttpClientRequestBuilder uriTemplate(String uriTemplate) { this.uriTemplate = uriTemplate; - - return this; - } - - public HttpClientRequestBuilder templateParam(String name, String value) { - this.templateParams.add(new HttpClientRequest.TemplateParam(name, value)); - return this; } - public HttpClientRequestBuilder queryParam(String name, int value) { - this.queryParams.add(new HttpClientRequest.QueryParam(name, Integer.toString(value))); - - return this; + @Override + public HttpClientRequestBuilder queryParam(String name, Integer value) { + if (value == null) { + return queryParam(name); + } + return queryParamNotNull(name, Integer.toString(value)); } - public HttpClientRequestBuilder queryParam(String name, long value) { - this.queryParams.add(new HttpClientRequest.QueryParam(name, Long.toString(value))); - - return this; + @Override + public HttpClientRequestBuilder queryParam(String name, Long value) { + if (value == null) { + return queryParam(name); + } + return queryParamNotNull(name, Long.toString(value)); } - public HttpClientRequestBuilder queryParam(String name, boolean value) { - this.queryParams.add(new HttpClientRequest.QueryParam(name, Boolean.toString(value))); - - return this; + @Override + public HttpClientRequestBuilder queryParam(String name, Boolean value) { + if (value == null) { + return queryParam(name); + } + return queryParamNotNull(name, Boolean.toString(value)); } + @Override public HttpClientRequestBuilder queryParam(String name, String value) { - this.queryParams.add(new HttpClientRequest.QueryParam(name, Objects.requireNonNull(value))); - - return this; + if (value == null) { + return queryParam(name); + } + return queryParamNotNull(name, value); } + @Override public HttpClientRequestBuilder queryParam(String name, UUID value) { - this.queryParams.add(new HttpClientRequest.QueryParam(name, value.toString())); - - return this; - } - - public HttpClientRequestBuilder queryParam(String name, Collection value) { - if (value.isEmpty()) { - return this.queryParam(name); - } - for (var val : value) { - this.queryParams.add(new HttpClientRequest.QueryParam(name, val)); + if (value == null) { + return queryParam(name); } - return this; + return queryParamNotNull(name, value.toString()); } + @Override public HttpClientRequestBuilder queryParam(String name) { - this.queryParams.add(new HttpClientRequest.QueryParam(name, null)); + this.queryParams.computeIfAbsent(name, k -> new ArrayList<>()); return this; } - public HttpClientRequestBuilder templateParam(String name, List value) { - this.templateParams.add(new HttpClientRequest.TemplateParam(name, String.join(",", value))); + @Override + public HttpClientRequestBuilder queryParam(String name, Collection values) { + if (values == null || values.isEmpty()) { + return queryParam(name); + } + this.queryParams.compute(name, (k, v) -> { + if (v == null) { + return new ArrayList<>(values); + } else { + v.addAll(values); + return v; + } + }); return this; } - public HttpClientRequestBuilder templateParam(String name, Integer value) { - this.templateParams.add(new HttpClientRequest.TemplateParam(name, value.toString())); + private HttpClientRequestBuilder queryParamNotNull(String name, @Nonnull String value) { + this.queryParams.compute(name, (k, v) -> { + if (v == null) { + final List values = new ArrayList<>(1); + values.add(value); + return values; + } else { + v.add(value); + return v; + } + }); return this; } - public HttpClientRequestBuilder templateParam(String name, Long value) { - this.templateParams.add(new HttpClientRequest.TemplateParam(name, value.toString())); + @Override + public HttpClientRequestBuilder pathParam(String name, @Nonnull String value) { + this.pathParams.put(name, value); + return this; + } + @Override + public HttpClientRequestBuilder pathParam(String name, @Nonnull Collection value) { + this.pathParams.put(name, String.join(",", value)); return this; } - public HttpClientRequestBuilder templateParam(String name, Boolean value) { - this.templateParams.add(new HttpClientRequest.TemplateParam(name, value.toString())); + @Override + public HttpClientRequestBuilder pathParam(String name, int value) { + this.pathParams.put(name, String.valueOf(value)); + return this; + } + @Override + public HttpClientRequestBuilder pathParam(String name, long value) { + this.pathParams.put(name, String.valueOf(value)); return this; } - public HttpClientRequestBuilder templateParam(String name, UUID value) { - this.templateParams.add(new HttpClientRequest.TemplateParam(name, value.toString())); + @Override + public HttpClientRequestBuilder pathParam(String name, boolean value) { + this.pathParams.put(name, String.valueOf(value)); + return this; + } + @Override + public HttpClientRequestBuilder pathParam(String name, @Nonnull UUID value) { + this.pathParams.put(name, value.toString()); return this; } + @Override public HttpClientRequestBuilder header(String name, String value) { var headers = this.headers.computeIfAbsent(name.toLowerCase(), k -> new ArrayList<>(1)); headers.add(value); - return this; } + @Override public HttpClientRequestBuilder requestTimeout(int requestTimeout) { this.requestTimeout = requestTimeout; + return this; + } + @Override + public HttpClientRequestBuilder requestTimeout(Duration requestTimeout) { + this.requestTimeout = requestTimeout.toMillisPart(); return this; } + @Override public HttpClientRequestBuilder body(Flux body) { this.body = body; - return this; } + @Override public HttpClientRequestBuilder body(ByteBuffer body) { this.body = Flux.just(body); - return this; } + @Override public HttpClientRequestBuilder body(byte[] body) { this.body = Flux.just(ByteBuffer.wrap(body)); - return this; } + @Override public HttpClientRequestBuilder headers(HttpHeaders headers) { this.headers = fromHeaders(headers); - return this; } + @Override public HttpClientRequest build() { - var resolvedUri = resolveUri(this.uriTemplate, this.templateParams, this.queryParams); + var resolvedUri = resolveUri(this.uriTemplate, this.pathParams, this.queryParams); var uri = URI.create(resolvedUri); var authority = uri.getAuthority(); var operation = operation(this.method, this.uriTemplate, uri); - return new HttpClientRequest.Default( - this.method, this.uriTemplate, this.queryParams, this.templateParams, toHeaders(this.headers), this.body, this.requestTimeout, resolvedUri, authority, operation + return new HttpClientRequestImpl( + this.method, this.uriTemplate, resolvedUri, Map.copyOf(this.queryParams), Map.copyOf(this.pathParams), toHeaders(this.headers), this.body, this.requestTimeout, authority, operation ); } - private static String resolveUri(String uriTemplate, List templateParams, List queryParams) { + private static String resolveUri(String uriTemplate, Map pathParams, Map> queryParams) { var template = uriTemplate; - if (!templateParams.isEmpty()) { - for (var i = templateParams.listIterator(templateParams.size()); i.hasPrevious(); ) { - var entry = i.previous(); - template = template.replace("{" + entry.name() + "}", URLEncoder.encode(entry.value(), UTF_8)); + if (!pathParams.isEmpty()) { + for (var entry : pathParams.entrySet()) { + template = template.replace("{" + entry.getKey() + "}", URLEncoder.encode(entry.getValue(), UTF_8)); } } + if (queryParams.isEmpty()) { return template; } + var delimeter = template.contains("?") ? (template.endsWith("?") ? "" : "&") : "?"; + var sb = new StringBuilder(template) .append(delimeter); - var firstEntry = queryParams.get(0); - sb.append(URLEncoder.encode(firstEntry.name(), UTF_8)); - if (firstEntry.value() != null) { - sb.append('=').append(URLEncoder.encode(firstEntry.value(), UTF_8)); - } - for (var i = 1; i < queryParams.size(); i++) { - var entry = queryParams.get(i); - sb.append('&').append(URLEncoder.encode(entry.name(), UTF_8)); - if (entry.value() != null) { - sb.append('=').append(URLEncoder.encode(entry.value(), UTF_8)); + + boolean isFirstQueryParam = true; + for (var entry : queryParams.entrySet()) { + for (String value : entry.getValue()) { + if (isFirstQueryParam) { + sb.append('='); + isFirstQueryParam = false; + } else { + sb.append('&'); + } + + sb.append(URLEncoder.encode(entry.getKey(), UTF_8)) + .append('=').append(URLEncoder.encode(value, UTF_8)); } } + return sb.toString(); } @@ -226,5 +273,4 @@ private static HashMap> fromHeaders(HttpHeaders headers) { private static HttpHeaders toHeaders(Map> map) { return HttpHeaders.of(map.entrySet().toArray(Map.Entry[]::new)); } - } diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestImpl.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestImpl.java new file mode 100644 index 000000000..0e4266e08 --- /dev/null +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestImpl.java @@ -0,0 +1,25 @@ +package ru.tinkoff.kora.http.client.common.request; + +import reactor.core.publisher.Flux; +import ru.tinkoff.kora.http.common.HttpHeaders; + +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; + +record HttpClientRequestImpl(String method, + String uriTemplate, + String uriResolved, + Map> queryParams, + Map pathParams, + HttpHeaders headers, + Flux body, + int requestTimeout, + String authority, + String operation) implements HttpClientRequest { + + @Override + public String toString() { + return method.toUpperCase() + " " + uriResolved; + } +} diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestMapper.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestMapper.java index 97e99a0c0..b7e67bb72 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestMapper.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/request/HttpClientRequestMapper.java @@ -3,7 +3,8 @@ import ru.tinkoff.kora.common.Mapping; public interface HttpClientRequestMapper extends Mapping.MappingFunction { - record Request(HttpClientRequestBuilder builder, T parameter) {} - HttpClientRequestBuilder apply(Request request); + record Request(HttpClientRequest.Builder builder, T parameter) {} + + HttpClientRequest.Builder apply(Request request); } diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/response/BlockingHttpResponse.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/response/BlockingHttpResponse.java index c45f47ec7..40bbe282d 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/response/BlockingHttpResponse.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/response/BlockingHttpResponse.java @@ -10,6 +10,7 @@ import java.io.InputStream; public interface BlockingHttpResponse extends AutoCloseable { + int code(); HttpHeaders headers(); diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/response/HttpClientResponse.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/response/HttpClientResponse.java index bfc460b92..d59da783d 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/response/HttpClientResponse.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/response/HttpClientResponse.java @@ -7,6 +7,7 @@ import java.nio.ByteBuffer; public interface HttpClientResponse { + int code(); HttpHeaders headers(); diff --git a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/telemetry/DefaultHttpClientTelemetry.java b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/telemetry/DefaultHttpClientTelemetry.java index 97239b332..04aa9d107 100644 --- a/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/telemetry/DefaultHttpClientTelemetry.java +++ b/http/http-client-common/src/main/java/ru/tinkoff/kora/http/client/common/telemetry/DefaultHttpClientTelemetry.java @@ -38,12 +38,12 @@ public DefaultHttpClientTelemetry(@Nullable HttpClientTracer tracing, @Nullable public HttpServerTelemetryContext get(Context ctx, HttpClientRequest request) { var startTime = System.nanoTime(); var method = request.method(); - var uri = URI.create(request.resolvedUri()); + var uri = URI.create(request.uriResolved()); var host = uri.getHost(); var scheme = uri.getScheme(); var operation = request.operation(); var authority = request.authority(); - var resolvedUri = request.resolvedUri(); + var resolvedUri = request.uriResolved(); var target = operation.substring(method.length() + 1); var createSpanResult = this.tracing == null ? null : this.tracing.createSpan(ctx, request); diff --git a/http/http-client-jdk/src/main/java/ru/tinkoff/kora/http/client/jdk/JdkHttpClient.java b/http/http-client-jdk/src/main/java/ru/tinkoff/kora/http/client/jdk/JdkHttpClient.java index 6a3dc6608..b8078b48d 100644 --- a/http/http-client-jdk/src/main/java/ru/tinkoff/kora/http/client/jdk/JdkHttpClient.java +++ b/http/http-client-jdk/src/main/java/ru/tinkoff/kora/http/client/jdk/JdkHttpClient.java @@ -35,7 +35,7 @@ public JdkHttpClient(java.net.http.HttpClient client) { public Mono execute(HttpClientRequest request) { return Mono.deferContextual(ctxView -> { var httpClientRequest = HttpRequest.newBuilder() - .uri(URI.create(request.resolvedUri())); + .uri(URI.create(request.uriResolved())); if (request.requestTimeout() > 0) { httpClientRequest.timeout(Duration.ofMillis(request.requestTimeout())); } @@ -81,7 +81,7 @@ public Mono execute(HttpClientRequest request) { public BlockingHttpResponse executeBlocking(HttpClientRequest request) { var httpClientRequest = HttpRequest.newBuilder() - .uri(URI.create(request.resolvedUri())); + .uri(URI.create(request.uriResolved())); if (request.requestTimeout() > 0) { httpClientRequest.timeout(Duration.ofMillis(request.requestTimeout())); } diff --git a/http/http-client-jdk/src/main/java/ru/tinkoff/kora/http/client/jdk/JdkHttpClientHeaders.java b/http/http-client-jdk/src/main/java/ru/tinkoff/kora/http/client/jdk/JdkHttpClientHeaders.java index 8cf01ab00..f70bca3e3 100644 --- a/http/http-client-jdk/src/main/java/ru/tinkoff/kora/http/client/jdk/JdkHttpClientHeaders.java +++ b/http/http-client-jdk/src/main/java/ru/tinkoff/kora/http/client/jdk/JdkHttpClientHeaders.java @@ -8,9 +8,8 @@ import java.util.List; import java.util.Map; -; - public class JdkHttpClientHeaders implements HttpHeaders { + private final Map> headers; public JdkHttpClientHeaders(java.net.http.HttpHeaders headers) { @@ -43,4 +42,9 @@ public int size() { public Iterator>> iterator() { return this.headers.entrySet().iterator(); } + + @Override + public String toString() { + return headers.toString(); + } } diff --git a/http/http-client-symbol-processor/src/main/kotlin/ru/tinkoff/kora/http/client/symbol/processor/ClientClassGenerator.kt b/http/http-client-symbol-processor/src/main/kotlin/ru/tinkoff/kora/http/client/symbol/processor/ClientClassGenerator.kt index d2d9bd8e8..7f4701cb2 100644 --- a/http/http-client-symbol-processor/src/main/kotlin/ru/tinkoff/kora/http/client/symbol/processor/ClientClassGenerator.kt +++ b/http/http-client-symbol-processor/src/main/kotlin/ru/tinkoff/kora/http/client/symbol/processor/ClientClassGenerator.kt @@ -17,7 +17,7 @@ import ru.tinkoff.kora.http.client.common.HttpClientException import ru.tinkoff.kora.http.client.common.HttpClientResponseException import ru.tinkoff.kora.http.client.common.annotation.ResponseCodeMapper import ru.tinkoff.kora.http.client.common.annotation.ResponseCodeMapper.ResponseCodeMappers -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper import ru.tinkoff.kora.http.client.common.response.HttpClientResponse import ru.tinkoff.kora.http.client.common.response.HttpClientResponseMapper @@ -146,9 +146,9 @@ class ClientClassGenerator(private val resolver: Resolver) { b.addStatement("val _client = %L", methodClientName) val isRBMutable = methodData.parameters.any { it is Parameter.BodyParameter } b.addStatement( - "%L _requestBuilder = %T(%S, %LUrl)", + "%L _requestBuilder = %T.of(%S, %LUrl)", if (isRBMutable) "var" else "val", - HttpClientRequestBuilder::class, + HttpClientRequest::class, httpRoute.method, method.simpleName.asString() ) @@ -157,10 +157,10 @@ class ClientClassGenerator(private val resolver: Resolver) { if (parameter is Parameter.PathParameter) { val parameterType = parameter.parameter.type.resolve() if (!requiresConverter(parameterType)) { - b.addCode("_requestBuilder.templateParam(%S, %T.toString(%L))\n", parameter.pathParameterName, Objects::class, parameter.parameter.name!!.asString()) + b.addCode("_requestBuilder.pathParam(%S, %T.toString(%L))\n", parameter.pathParameterName, Objects::class, parameter.parameter.name!!.asString()) } else { b.addStatement( - "_requestBuilder.templateParam(%S, %L.convert(%L))", + "_requestBuilder.pathParam(%S, %L.convert(%L))", parameter.pathParameterName, getConverterName(methodData, parameter.parameter), parameter.parameter.name!!.asString() diff --git a/http/http-client-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/client/symbol/processor/client/ClientWithMappers.kt b/http/http-client-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/client/symbol/processor/client/ClientWithMappers.kt index c00c05417..28eac1fe3 100644 --- a/http/http-client-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/client/symbol/processor/client/ClientWithMappers.kt +++ b/http/http-client-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/client/symbol/processor/client/ClientWithMappers.kt @@ -5,7 +5,7 @@ import ru.tinkoff.kora.common.Mapping import ru.tinkoff.kora.common.Tag import ru.tinkoff.kora.http.client.common.annotation.HttpClient import ru.tinkoff.kora.http.client.common.annotation.ResponseCodeMapper -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper import ru.tinkoff.kora.http.client.common.response.HttpClientResponse import ru.tinkoff.kora.http.client.common.response.HttpClientResponseMapper @@ -51,7 +51,7 @@ interface ClientWithMappers { } class IssueRequestMapper : HttpClientRequestMapper { - override fun apply(request: HttpClientRequestMapper.Request): HttpClientRequestBuilder { + override fun apply(request: HttpClientRequestMapper.Request): HttpClientRequest.Builder { return request.builder().body("TEST".toByteArray(StandardCharsets.UTF_8)) } } diff --git a/http/http-common/src/main/java/ru/tinkoff/kora/http/common/HttpHeaders.java b/http/http-common/src/main/java/ru/tinkoff/kora/http/common/HttpHeaders.java index 0f7b57108..ef564b5c7 100644 --- a/http/http-common/src/main/java/ru/tinkoff/kora/http/common/HttpHeaders.java +++ b/http/http-common/src/main/java/ru/tinkoff/kora/http/common/HttpHeaders.java @@ -1,13 +1,11 @@ package ru.tinkoff.kora.http.common; +import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; public interface HttpHeaders extends Iterable>> { - HttpHeaders EMPTY = new HttpHeadersImpl(); @Nullable String getFirst(String name); @@ -15,12 +13,12 @@ public interface HttpHeaders extends Iterable>> { @Nullable List get(String name); + int size(); + default boolean has(String key) { return getFirst(key) != null; } - int size(); - default Set names() { var names = new HashSet(); for (var stringListEntry : this) { @@ -61,12 +59,18 @@ default HttpHeaders without(String key) { } @SafeVarargs - static HttpHeaders of(Map.Entry>... entries) { + static HttpHeaders of(@Nonnull Map.Entry>... entries) { return new HttpHeadersImpl(entries); } + static HttpHeaders of(@Nonnull Map headers) { + final Map> headersMap = new HashMap<>(headers.size()); + headers.forEach((k,v) -> headersMap.put(k,List.of(v))); + return new HttpHeadersImpl(headersMap); + } + static HttpHeaders of() { - return EMPTY; + return HttpHeadersImpl.EMPTY; } static HttpHeaders of(String k1, String v1) { diff --git a/http/http-common/src/main/java/ru/tinkoff/kora/http/common/HttpHeadersImpl.java b/http/http-common/src/main/java/ru/tinkoff/kora/http/common/HttpHeadersImpl.java index db9b85d0c..0fd6cf0ec 100644 --- a/http/http-common/src/main/java/ru/tinkoff/kora/http/common/HttpHeadersImpl.java +++ b/http/http-common/src/main/java/ru/tinkoff/kora/http/common/HttpHeadersImpl.java @@ -4,7 +4,10 @@ import javax.annotation.Nullable; import java.util.*; -class HttpHeadersImpl implements HttpHeaders { +final class HttpHeadersImpl implements HttpHeaders { + + static final HttpHeaders EMPTY = new HttpHeadersImpl(); + private final Map> values; @SafeVarargs @@ -71,4 +74,9 @@ public Set names() { public Iterator>> iterator() { return this.values.entrySet().iterator(); } + + @Override + public String toString() { + return values.toString(); + } } diff --git a/http/http-server-annotation-processor/src/main/java/ru/tinkoff/kora/http/server/annotation/processor/RequestHandlerGenerator.java b/http/http-server-annotation-processor/src/main/java/ru/tinkoff/kora/http/server/annotation/processor/RequestHandlerGenerator.java index d369dbf67..caff431f9 100644 --- a/http/http-server-annotation-processor/src/main/java/ru/tinkoff/kora/http/server/annotation/processor/RequestHandlerGenerator.java +++ b/http/http-server-annotation-processor/src/main/java/ru/tinkoff/kora/http/server/annotation/processor/RequestHandlerGenerator.java @@ -11,7 +11,6 @@ import ru.tinkoff.kora.http.server.common.HttpServerRequestHandler; import ru.tinkoff.kora.http.server.common.HttpServerResponse; import ru.tinkoff.kora.http.server.common.HttpServerResponseEntity; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import ru.tinkoff.kora.http.server.common.handler.*; import javax.annotation.Nullable; @@ -140,9 +139,9 @@ private CodeBlock buildRequestHandler(TypeElement controller, RequestMappingData controllerCall = CodeBlock.of(""" _executor.execute(() -> { _controller.$L($L); - return new $T(200, "application/octet-stream", $T.of(), $T.allocate(0)); + return $T.of(200, "application/octet-stream", $T.allocate(0)); }) - """, requestMappingData.executableElement().getSimpleName(), executeParameters, SimpleHttpServerResponse.class, HttpHeaders.class, ByteBuffer.class); + """, requestMappingData.executableElement().getSimpleName(), executeParameters, HttpServerResponse.class, ByteBuffer.class); } else if (isNullable) { controllerCall = CodeBlock.of("_executor.execute(() -> $T.ofNullable(_controller.$L($L)))\n", Optional.class, requestMappingData.executableElement().getSimpleName(), executeParameters); } else { @@ -151,7 +150,7 @@ private CodeBlock buildRequestHandler(TypeElement controller, RequestMappingData } else if (isMonoVoid) { controllerCall = CodeBlock.builder() .add("$T.deferContextual(_ctx -> _controller.$L($L))\n", Mono.class, requestMappingData.executableElement().getSimpleName(), executeParameters) - .add(" .thenReturn(new $T(200, \"application/octet-stream\", $T.of(), $T.allocate(0)))", SimpleHttpServerResponse.class, HttpHeaders.class, ByteBuffer.class) + .add(" .thenReturn($T.of(200, \"application/octet-stream\", $T.allocate(0)))", HttpServerResponse.class, ByteBuffer.class) .build(); } else { controllerCall = CodeBlock.of("$T.deferContextual(_ctx -> _controller.$L($L))", Mono.class, requestMappingData.executableElement().getSimpleName(), executeParameters); diff --git a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/MultipleParamsController.java b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/MultipleParamsController.java index 2bcc3d7e9..7bb760928 100644 --- a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/MultipleParamsController.java +++ b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/MultipleParamsController.java @@ -20,7 +20,7 @@ public static final class Param1Mapping implements HttpServerRequestMapper apply(HttpServerRequest request) { if (request.headers().getFirst("Test-Header") == null) { - throw HttpServerResponseException.of(null, 400, "TEST"); + throw new HttpServerResponseException(400, "TEST"); } return Mono.just(new Param1()); } diff --git a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/TestControllerWithDifferentTypes.java b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/TestControllerWithDifferentTypes.java index eabbcc5b4..792bd7bbc 100644 --- a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/TestControllerWithDifferentTypes.java +++ b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/TestControllerWithDifferentTypes.java @@ -7,7 +7,6 @@ import ru.tinkoff.kora.http.common.annotation.HttpRoute; import ru.tinkoff.kora.http.server.common.HttpServerRequest; import ru.tinkoff.kora.http.server.common.HttpServerResponse; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import ru.tinkoff.kora.http.server.common.annotation.HttpController; import java.nio.ByteBuffer; @@ -21,14 +20,14 @@ public class TestControllerWithDifferentTypes { @HttpRoute(method = GET, path = "/") Mono getRoot() { - var response = new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), UTF_8.encode("Hello world")); + var response = HttpServerResponse.of(200, "text/plain", UTF_8.encode("Hello world")); return Mono.delay(Duration.ofMillis(1)).thenReturn(response); } @HttpRoute(method = GET, path = "/somePage") Mono getSomePage(HttpServerRequest httpServerRequest) { - var response = new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), UTF_8.encode("Hello world")); + var response = HttpServerResponse.of(200, "text/plain", UTF_8.encode("Hello world")); return Mono.delay(Duration.ofMillis(1)).thenReturn(response); } diff --git a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/TestControllerWithMappers.java b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/TestControllerWithMappers.java index d793ba66d..805a5f9d7 100644 --- a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/TestControllerWithMappers.java +++ b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/controller/TestControllerWithMappers.java @@ -7,7 +7,6 @@ import ru.tinkoff.kora.http.common.annotation.HttpRoute; import ru.tinkoff.kora.http.server.common.HttpServerRequest; import ru.tinkoff.kora.http.server.common.HttpServerResponse; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import ru.tinkoff.kora.http.server.common.annotation.HttpController; import ru.tinkoff.kora.http.server.common.handler.HttpServerRequestMapper; import ru.tinkoff.kora.http.server.common.handler.HttpServerResponseMapper; @@ -40,14 +39,14 @@ public Mono apply(HttpServerRequest request) { public static class StringResponseMapper implements HttpServerResponseMapper { @Override public Mono apply(String result) { - return Mono.just(new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), UTF_8.encode(result))); + return Mono.just(HttpServerResponse.of(200, "text/plain", UTF_8.encode(result))); } } public static class ByteArrayResponseMapper implements HttpServerResponseMapper { @Override public Mono apply(String result) { - return Mono.just(new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), UTF_8.encode(result))); + return Mono.just(HttpServerResponse.of(200, "text/plain", UTF_8.encode(result))); } } } diff --git a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/Mappers.java b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/Mappers.java index 7441f44bc..a94404133 100644 --- a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/Mappers.java +++ b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/Mappers.java @@ -13,7 +13,6 @@ import ru.tinkoff.kora.http.server.common.HttpServerRequest; import ru.tinkoff.kora.http.server.common.HttpServerResponse; import ru.tinkoff.kora.http.server.common.HttpServerResponseEntity; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import ru.tinkoff.kora.http.server.common.handler.*; import java.lang.reflect.InvocationTargetException; @@ -134,9 +133,8 @@ private static HttpServerRequestMapper jsonRequestMapper(Type someEntityC return request -> Mono.just(null); } - private static HttpServerResponseMapper jsonResponseMapper(TypeRef someEntityClass) { - return result -> Mono.just(new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.EMPTY, ByteBuffer.wrap(result.toString().getBytes(StandardCharsets.UTF_8)))); + return result -> Mono.just(HttpServerResponse.of(200, "text/plain", result.toString().getBytes(StandardCharsets.UTF_8))); } private static HttpServerResponseMapper noopResponseMapper() { @@ -152,11 +150,11 @@ private static HttpServerRequestMapper stringRequestMapper() { } private static HttpServerResponseMapper voidResponseMapper() { - return result -> Mono.just(new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), null)); + return result -> Mono.just(HttpServerResponse.of(200, "text/plain")); } private static HttpServerResponseMapper stringResponseMapper() { - return result -> Mono.just(new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), StandardCharsets.UTF_8.encode(result != null ? result : "null"))); + return result -> Mono.just(HttpServerResponse.of(200, "text/plain", StandardCharsets.UTF_8.encode(result != null ? result : "null"))); } private static HttpServerRequestMapper integerRequestMapper() { @@ -164,7 +162,7 @@ private static HttpServerRequestMapper integerRequestMapper() { } private static HttpServerResponseMapper integerResponseMapper() { - return r -> Mono.just(new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), StandardCharsets.UTF_8.encode(r.toString()))); + return r -> Mono.just(HttpServerResponse.of(200, "text/plain", StandardCharsets.UTF_8.encode(r.toString()))); } private static HttpServerRequestMapper byteBufferPublisherRequestMapper() { @@ -176,7 +174,7 @@ private static HttpServerRequestMapper byteArrayRequestMapper() { } private static HttpServerResponseMapper byteArrayResponseMapper() { - return r -> Mono.just(new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap(r))); + return r -> Mono.just(HttpServerResponse.of(200, "text/plain", r)); } private static StringParameterReader readableEntityStringReader() { diff --git a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/SimpleHttpServerRequest.java b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/SimpleHttpServerRequest.java index 9fafa299d..e417afea4 100644 --- a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/SimpleHttpServerRequest.java +++ b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/SimpleHttpServerRequest.java @@ -5,10 +5,7 @@ import ru.tinkoff.kora.http.server.common.HttpServerRequest; import java.nio.ByteBuffer; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -39,7 +36,7 @@ public String path() { @Override public HttpHeaders headers() { - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({"unchecked"}) Map.Entry>[] entries = new Map.Entry[headers.length]; for (int i = 0; i < headers.length; i++) { entries[i] = Map.entry(headers[i].getKey(), List.of(headers[i].getValue())); @@ -48,7 +45,7 @@ public HttpHeaders headers() { } @Override - public Map> queryParams() { + public Map> queryParams() { var questionMark = path.indexOf('?'); if (questionMark < 0) { return Map.of(); @@ -58,14 +55,14 @@ public Map> queryParams() { .map(param -> { var eq = param.indexOf('='); if (eq <= 0) { - return Map.entry(param, new ArrayDeque(0)); + return Map.entry(param, new ArrayList(0)); } var name = param.substring(0, eq); var value = param.substring(eq + 1); - return Map.entry(name, new ArrayDeque<>(List.of(value))); + return Map.entry(name, List.of(value)); }) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (d1, d2) -> { - var d3 = new ArrayDeque<>(d1); + var d3 = new ArrayList<>(d1); d3.addAll(d2); return d3; })); diff --git a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/TestHttpServer.java b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/TestHttpServer.java index f694b3e2f..ff5eb1e58 100644 --- a/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/TestHttpServer.java +++ b/http/http-server-annotation-processor/src/test/java/ru/tinkoff/kora/http/server/annotation/processor/server/TestHttpServer.java @@ -7,7 +7,6 @@ import ru.tinkoff.kora.http.server.annotation.processor.HttpControllerProcessor; import ru.tinkoff.kora.http.server.common.HttpServerRequestHandler; import ru.tinkoff.kora.http.server.common.HttpServerResponse; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -41,7 +40,7 @@ public final HttpResponseAssert invoke(String method, String path, byte[] body, return new HttpResponseAssert(response); } } - return new HttpResponseAssert(new SimpleHttpServerResponse(404, "text/plain", HttpHeaders.of(), null)); + return new HttpResponseAssert(HttpServerResponse.of(404, "text/plain")); } private Map extractRouteParams(String routeTemplate, String path) { diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/ContentType.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/ContentType.java new file mode 100644 index 000000000..584f154a1 --- /dev/null +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/ContentType.java @@ -0,0 +1,38 @@ +package ru.tinkoff.kora.http.server.common; + +import javax.annotation.Nonnull; +import java.nio.charset.Charset; + +public enum ContentType { + + TEXT_JSON("text/json"), + TEXT_PLAIN("text/plain"), + TEXT_PLAIN_UTF_8("text/plain; charset=utf-8"), + APPLICATION_JSON("application/json"), + APPLICATION_JSON_UTF_8("application/json; charset=utf-8"), + APPLICATION_YAML("application/x-yaml"), + APPLICATION_YAML_UTF_8("application/x-yaml; charset=utf-8"), + APPLICATION_OCTET_STREAM("application/octet-stream"); + + private final String value; + + ContentType(String value) { + this.value = value; + } + + @Nonnull + public String value() { + return value; + } + + @Nonnull + public String charset(Charset charset) { + return value + "; charset=" + charset.name(); + } + + @Nonnull + @Override + public String toString() { + return value; + } +} diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerModule.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerModule.java index 9331ad2bc..f4e1955dc 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerModule.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerModule.java @@ -71,15 +71,15 @@ default HttpServerRequestMapper byteArrayRequestMapper() { } default HttpServerResponseMapper byteBufBodyResponseMapper() { - return r -> Mono.just(new SimpleHttpServerResponse(200, "application/octet-stream", HttpHeaders.EMPTY, r)); + return r -> Mono.just(HttpServerResponse.of(200, "application/octet-stream", r)); } default HttpServerResponseMapper byteArrayResponseMapper() { - return r -> Mono.just(new SimpleHttpServerResponse(200, "application/octet-stream", HttpHeaders.EMPTY, ByteBuffer.wrap(r))); + return r -> Mono.just(HttpServerResponse.of(200, "application/octet-stream", r)); } default HttpServerResponseMapper stringResponseMapper() { - return r -> Mono.just(new SimpleHttpServerResponse(200, "text/plain; charset=utf-8", HttpHeaders.EMPTY, ByteBuffer.wrap(r.getBytes(StandardCharsets.UTF_8)))); + return r -> Mono.just(HttpServerResponse.of(200, "text/plain; charset=utf-8", r.getBytes(StandardCharsets.UTF_8))); } default HttpServerResponseMapper> httpServerResponseEntityMapper(HttpServerResponseMapper delegate) { diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerRequest.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerRequest.java index 12a54a5e5..61cd44e13 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerRequest.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerRequest.java @@ -4,19 +4,20 @@ import ru.tinkoff.kora.http.common.HttpHeaders; import java.nio.ByteBuffer; -import java.util.Collection; +import java.util.List; import java.util.Map; public interface HttpServerRequest { + String method(); String path(); - HttpHeaders headers(); - - Map> queryParams(); + Map> queryParams(); Map pathParams(); + HttpHeaders headers(); + Flux body(); } diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponse.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponse.java index dcd05355f..3d9a79beb 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponse.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponse.java @@ -1,11 +1,13 @@ package ru.tinkoff.kora.http.server.common; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import ru.tinkoff.kora.http.common.HttpHeaders; import java.nio.ByteBuffer; public interface HttpServerResponse { + int code(); int contentLength(); @@ -15,4 +17,60 @@ public interface HttpServerResponse { HttpHeaders headers(); Flux body(); + + static HttpServerResponse of(int code, String contentType) { + return new HttpServerResponseImpl(code, HttpHeaders.of(), contentType, 0, Flux.empty()); + } + + static HttpServerResponse of(int code, ContentType contentType) { + return new HttpServerResponseImpl(code, HttpHeaders.of(), contentType.value(), 0, Flux.empty()); + } + + static HttpServerResponse of(int code, String contentType, HttpHeaders headers) { + return new HttpServerResponseImpl(code, headers, contentType, 0, Flux.empty()); + } + + static HttpServerResponse of(int code, ContentType contentType, HttpHeaders headers) { + return new HttpServerResponseImpl(code, headers, contentType.value(), 0, Flux.empty()); + } + + static HttpServerResponse of(int code, String contentType, byte[] body) { + return new HttpServerResponseImpl(code, HttpHeaders.of(), contentType, body.length, Flux.just(ByteBuffer.wrap(body))); + } + + static HttpServerResponse of(int code, ContentType contentType, byte[] body) { + return new HttpServerResponseImpl(code, HttpHeaders.of(), contentType.value(), body.length, Flux.just(ByteBuffer.wrap(body))); + } + + static HttpServerResponse of(int code, String contentType, ByteBuffer body) { + return new HttpServerResponseImpl(code, HttpHeaders.of(), contentType, body.remaining(), Mono.fromCallable(body::slice).flux()); + } + + static HttpServerResponse of(int code, ContentType contentType, ByteBuffer body) { + return new HttpServerResponseImpl(code, HttpHeaders.of(), contentType.value(), body.remaining(), Mono.fromCallable(body::slice).flux()); + } + + static HttpServerResponse of(int code, String contentType, HttpHeaders headers, byte[] body) { + return new HttpServerResponseImpl(code, headers, contentType, body.length, Flux.just(ByteBuffer.wrap(body))); + } + + static HttpServerResponse of(int code, ContentType contentType, HttpHeaders headers, byte[] body) { + return new HttpServerResponseImpl(code, headers, contentType.value(), body.length, Flux.just(ByteBuffer.wrap(body))); + } + + static HttpServerResponse of(int code, String contentType, HttpHeaders headers, ByteBuffer body) { + return new HttpServerResponseImpl(code, headers, contentType, body.remaining(), Mono.fromCallable(body::slice).flux()); + } + + static HttpServerResponse of(int code, ContentType contentType, HttpHeaders headers, ByteBuffer body) { + return new HttpServerResponseImpl(code, headers, contentType.value(), body.remaining(), Mono.fromCallable(body::slice).flux()); + } + + static HttpServerResponse of(int code, String contentType, HttpHeaders headers, int contentLength, Flux body) { + return new HttpServerResponseImpl(code, headers, contentType, contentLength, body); + } + + static HttpServerResponse of(int code, ContentType contentType, HttpHeaders headers, int contentLength, Flux body) { + return new HttpServerResponseImpl(code, headers, contentType.value(), contentLength, body); + } } diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponseException.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponseException.java index 226c345c6..87f7372f6 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponseException.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponseException.java @@ -9,63 +9,61 @@ import static java.nio.charset.StandardCharsets.UTF_8; public class HttpServerResponseException extends RuntimeException implements HttpServerResponse { - private final int code; - private final String contentType; - private final ByteBuffer body; - private final HttpHeaders headers; - public HttpServerResponseException(int code, String contentType, String message, ByteBuffer body, HttpHeaders headers) { - this(null, message, code, contentType, body, headers); + private final HttpServerResponse response; + + public HttpServerResponseException(int code, String message) { + super(message); + this.response = HttpServerResponse.of(code, ContentType.TEXT_PLAIN_UTF_8, UTF_8.encode(message)); } - public HttpServerResponseException(@Nullable Throwable cause, String message, int code, String contentType, ByteBuffer body, HttpHeaders headers) { + public HttpServerResponseException(int code, String message, Throwable cause) { super(message, cause); - this.code = code; - this.contentType = contentType; - this.body = body.slice(); - this.headers = headers; + this.response = HttpServerResponse.of(code, ContentType.TEXT_PLAIN_UTF_8, UTF_8.encode(message)); + } + + public HttpServerResponseException(int code, Throwable cause) { + super(cause.getMessage(), cause); + this.response = HttpServerResponse.of(code, ContentType.TEXT_PLAIN_UTF_8, UTF_8.encode(cause.getMessage())); } - public static HttpServerResponseException of(int code, String text) { - return of(null, code, text); + public HttpServerResponseException(HttpServerResponse response, String message) { + super(message); + this.response = response; } - public static HttpServerResponseException of(@Nullable Throwable cause, int code, String text) { - return new HttpServerResponseException(cause, text, code, "text/plain; charset=utf-8", UTF_8.encode(text), HttpHeaders.of()); + public HttpServerResponseException(HttpServerResponse response, String message, Throwable cause) { + super(message, cause); + this.response = response; } @Override public int code() { - return this.code; + return response.code(); } @Override public int contentLength() { - return this.body.remaining(); + return response.contentLength(); } @Override public String contentType() { - return this.contentType; + return response.contentType(); } @Override public HttpHeaders headers() { - return this.headers; + return response.headers(); } @Override public Flux body() { - return Flux.just(this.body.slice()); + return response.body(); } @Override public String toString() { - return "HttpResponseException{" + - "message=" + getMessage() + - "code=" + code + - ", contentType='" + contentType + '\'' + - ", headers=" + headers + - '}'; + return response.toString(); } } diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponseImpl.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponseImpl.java new file mode 100644 index 000000000..134acd4d7 --- /dev/null +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/HttpServerResponseImpl.java @@ -0,0 +1,24 @@ +package ru.tinkoff.kora.http.server.common; + +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import ru.tinkoff.kora.http.common.HttpHeaders; + +import javax.annotation.Nullable; +import java.nio.ByteBuffer; + +record HttpServerResponseImpl(int code, + HttpHeaders headers, + String contentType, + int contentLength, + Flux body) implements HttpServerResponse { + + @Override + public String toString() { + return "HttpServerResponse{code=" + code + + ", contentType=" + contentType + + ", contentLength=" + contentLength + + ", headers=" + headers + + '}'; + } +} diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/PrivateApiHandler.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/PrivateApiHandler.java index 9ed6215c0..0230257ed 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/PrivateApiHandler.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/PrivateApiHandler.java @@ -54,7 +54,7 @@ public Publisher handle(String path) { return this.liveness(); } - return Mono.just(new SimpleHttpServerResponse(404, PLAIN_TEXT_CONTENT_TYPE, HttpHeaders.of(), ByteBuffer.wrap("Private api path not found".getBytes(StandardCharsets.UTF_8)))); + return Mono.just(HttpServerResponse.of(404, PLAIN_TEXT_CONTENT_TYPE, "Private api path not found".getBytes(StandardCharsets.UTF_8))); } private Publisher metrics() { @@ -62,7 +62,7 @@ private Publisher metrics() { .map(PrivateApiMetrics::scrape) .orElse(""); var body = ByteBuffer.wrap(response.getBytes(StandardCharsets.UTF_8)); - return Mono.just(new SimpleHttpServerResponse(200, "text/plain; charset=utf-8", HttpHeaders.of(), body)); + return Mono.just(HttpServerResponse.of(200, "text/plain; charset=utf-8", body)); } private Publisher readiness() { @@ -79,24 +79,24 @@ private Publisher handleProbes(All> var probe = probePromise.get(); if (!probe.isPresent()) { var body = ByteBuffer.wrap("Probe is not ready yet".getBytes(StandardCharsets.UTF_8)); - return Mono.just(new SimpleHttpServerResponse(503, PLAIN_TEXT_CONTENT_TYPE, HttpHeaders.of(), body)); + return Mono.just(HttpServerResponse.of(503, PLAIN_TEXT_CONTENT_TYPE, body)); } return performProbe.apply(probe.get()).map(failure -> { var body = ByteBuffer.wrap(failure.getBytes(StandardCharsets.UTF_8)); - return new SimpleHttpServerResponse(503, PLAIN_TEXT_CONTENT_TYPE, HttpHeaders.of(), body); + return HttpServerResponse.of(503, PLAIN_TEXT_CONTENT_TYPE, body); }); }) .next() .switchIfEmpty(Mono.defer(() -> { var body = ByteBuffer.wrap("OK".getBytes(StandardCharsets.UTF_8)); - return Mono.just(new SimpleHttpServerResponse(200, PLAIN_TEXT_CONTENT_TYPE, HttpHeaders.of(), body)); + return Mono.just(HttpServerResponse.of(200, PLAIN_TEXT_CONTENT_TYPE, body)); })) .timeout(Duration.ofSeconds(30)) .onErrorResume(err -> { String message = "Probe failed: " + err.getMessage(); var body = ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8)); - return Mono.just(new SimpleHttpServerResponse(503, PLAIN_TEXT_CONTENT_TYPE, HttpHeaders.of(), body)); + return Mono.just(HttpServerResponse.of(503, PLAIN_TEXT_CONTENT_TYPE, body)); }); } } diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/SimpleHttpServerResponse.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/SimpleHttpServerResponse.java deleted file mode 100644 index c553b028b..000000000 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/SimpleHttpServerResponse.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.tinkoff.kora.http.server.common; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import ru.tinkoff.kora.http.common.HttpHeaders; - -import javax.annotation.Nullable; -import java.nio.ByteBuffer; - -public record SimpleHttpServerResponse(int code, String contentType, HttpHeaders headers, int contentLength, Flux body) implements HttpServerResponse { - public SimpleHttpServerResponse(int code, String contentType, HttpHeaders headers, @Nullable ByteBuffer bodyBuffer) { - this( - code, - contentType, - headers, - bodyBuffer == null ? 0 : bodyBuffer.remaining(), - bodyBuffer == null ? Flux.empty() : Mono.fromCallable(bodyBuffer::slice).flux() - ); - } -} diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/form/FormUrlEncodedServerRequestMapper.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/form/FormUrlEncodedServerRequestMapper.java index 3aedaa26c..3bde42af4 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/form/FormUrlEncodedServerRequestMapper.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/form/FormUrlEncodedServerRequestMapper.java @@ -19,7 +19,7 @@ public Mono apply(HttpServerRequest request) { var contentType = request.headers().getFirst("content-type"); if (contentType == null || !contentType.equalsIgnoreCase("application/x-www-form-urlencoded")) { request.body().subscribe(); - return Mono.error(HttpServerResponseException.of(415, "Expected content type: 'application/x-www-form-urlencoded'")); + return Mono.error(new HttpServerResponseException(415, "Expected content type: 'application/x-www-form-urlencoded'")); } return ReactorUtils.toByteArrayMono(request.body()).map(bytes -> { var str = new String(bytes, StandardCharsets.UTF_8); diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/form/MultipartReader.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/form/MultipartReader.java index 76098ec2c..980f63d9a 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/form/MultipartReader.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/form/MultipartReader.java @@ -19,11 +19,12 @@ public class MultipartReader { public static Flux read(HttpServerRequest r) { var contentType = r.headers().getFirst("content-type"); if (contentType == null) { - throw HttpServerResponseException.of(400, "content-type header is required"); + throw new HttpServerResponseException(400, "content-type header is required"); } + var m = boundaryPattern.matcher(contentType); if (!m.matches()) { - throw HttpServerResponseException.of(400, "content-type header is invalid"); + throw new HttpServerResponseException(400, "content-type header is invalid"); } var boundary = m.group("boundary"); return r.body().flatMap(new MultipartDecoder(boundary)); @@ -67,16 +68,16 @@ public Flux apply(ByteBuffer byteBuffer) { break loop; } if (this.buf.get(this.readPosition) != '-' || this.buf.get(this.readPosition + 1) != '-') { - return Flux.error(HttpServerResponseException.of(400, "Invalid beginning of multipart body")); + return Flux.error(new HttpServerResponseException(400, "Invalid beginning of multipart body")); } readPosition += 2; this.buf.get(readPosition, this.boundaryBuf); if (!Arrays.equals(this.boundary, this.boundaryBuf)) { - return Flux.error(HttpServerResponseException.of(400, "Invalid beginning of multipart body")); + return Flux.error(new HttpServerResponseException(400, "Invalid beginning of multipart body")); } readPosition += this.boundary.length; if (this.buf.get(readPosition) != '\r' || this.buf.get(readPosition + 1) != '\n') { - return Flux.error(HttpServerResponseException.of(400, "Invalid beginning of multipart body")); + return Flux.error(new HttpServerResponseException(400, "Invalid beginning of multipart body")); } readPosition += 2; this.readPosition = readPosition; @@ -96,7 +97,7 @@ public Flux apply(ByteBuffer byteBuffer) { } else { var contentDisposition = this.parseContentDisposition(); if (contentDisposition == null) { - return Flux.error(HttpServerResponseException.of(400, "Multipart part is missing content-disposition header")); + return Flux.error(new HttpServerResponseException(400, "Multipart part is missing content-disposition header")); } this.currentContentDisposition = contentDisposition; this.state = State.READ_BODY; diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/EnumStringParameterReader.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/EnumStringParameterReader.java index 6d499daf1..3068d1527 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/EnumStringParameterReader.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/EnumStringParameterReader.java @@ -20,7 +20,7 @@ public EnumStringParameterReader(T[] values, Function mapper) { public T read(String string) { var value = this.values.get(string); if (value == null) { - throw HttpServerResponseException.of(400, "Invalid value '%s'. Valid values are: %s".formatted(string, this.values.keySet())); + throw new HttpServerResponseException(400, "Invalid value '%s'. Valid values are: %s".formatted(string, this.values.keySet())); } return value; } diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/HttpServerResponseEntityMapper.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/HttpServerResponseEntityMapper.java index f8543e036..7a191c8b8 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/HttpServerResponseEntityMapper.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/HttpServerResponseEntityMapper.java @@ -4,7 +4,6 @@ import ru.tinkoff.kora.http.common.HttpHeaders; import ru.tinkoff.kora.http.server.common.HttpServerResponse; import ru.tinkoff.kora.http.server.common.HttpServerResponseEntity; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import java.util.List; import java.util.Map; @@ -26,7 +25,7 @@ public Mono apply(HttpServerResponseEntity resu } else if (response.headers().size() == 0) { headers = result.headers(); } else { - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({"unchecked"}) Map.Entry>[] entries = new Map.Entry[response.headers().size() + result.headers().size()]; var i = 0; for (var entry : response.headers()) { @@ -39,7 +38,7 @@ public Mono apply(HttpServerResponseEntity resu headers = HttpHeaders.of(entries); } - return new SimpleHttpServerResponse( + return HttpServerResponse.of( result.code(), response.contentType(), headers, diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/RequestHandlerUtils.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/RequestHandlerUtils.java index 3df64ca86..f58b35a13 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/RequestHandlerUtils.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/RequestHandlerUtils.java @@ -26,7 +26,7 @@ private RequestHandlerUtils() {} public static String parseStringPathParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = request.pathParams().get(name); if (result == null) { - throw HttpServerResponseException.of(400, "Path parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Path parameter '%s' is required".formatted(name)); } return result; } @@ -35,53 +35,53 @@ public static String parseStringPathParameter(HttpServerRequest request, String public static UUID parseUUIDPathParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = request.pathParams().get(name); if (result == null) { - throw HttpServerResponseException.of(400, "Path parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Path parameter '%s' is required".formatted(name)); } try { return UUID.fromString(result); } catch (IllegalArgumentException e) { - throw HttpServerResponseException.of(400, "Path parameter '%s' has invalid value '%s'".formatted(name, result)); + throw new HttpServerResponseException(400, "Path parameter '%s' has invalid value '%s'".formatted(name, result)); } } public static int parseIntegerPathParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = request.pathParams().get(name); if (result == null) { - throw HttpServerResponseException.of(400, "Path parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Path parameter '%s' is required".formatted(name)); } try { return Integer.parseInt(result); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Path parameter '%s' has invalid value '%s'".formatted(name, result)); + throw new HttpServerResponseException(400, "Path parameter '%s' has invalid value '%s'".formatted(name, result)); } } public static long parseLongPathParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = request.pathParams().get(name); if (result == null) { - throw HttpServerResponseException.of(400, "Path parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Path parameter '%s' is required".formatted(name)); } try { return Long.parseLong(result); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Path parameter %s(%s) has invalid value".formatted(name, result)); + throw new HttpServerResponseException(400, "Path parameter %s(%s) has invalid value".formatted(name, result)); } } public static double parseDoublePathParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = request.pathParams().get(name); if (result == null) { - throw HttpServerResponseException.of(400, "Path parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Path parameter '%s' is required".formatted(name)); } try { return Double.parseDouble(result); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Path parameter %s(%s) has invalid value".formatted(name, result)); + throw new HttpServerResponseException(400, "Path parameter %s(%s) has invalid value".formatted(name, result)); } } @@ -89,13 +89,13 @@ public static double parseDoublePathParameter(HttpServerRequest request, String public static > T parseEnumPathParameter(HttpServerRequest request, Class enumType, String name) throws HttpServerResponseException { var result = request.pathParams().get(name); if (result == null) { - throw HttpServerResponseException.of(400, "Path parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Path parameter '%s' is required".formatted(name)); } try { return Enum.valueOf(enumType, result); } catch (Exception exception) { - throw HttpServerResponseException.of(400, "Path parameter %s(%s) has invalid value".formatted(name, result)); + throw new HttpServerResponseException(400, "Path parameter %s(%s) has invalid value".formatted(name, result)); } } @@ -106,7 +106,7 @@ public static > T parseEnumPathParameter(HttpServerRequest req public static String parseStringHeaderParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = request.headers().get(name); if (result == null) { - throw HttpServerResponseException.of(400, "Header '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Header '%s' is required".formatted(name)); } return String.join(", ", result); } @@ -123,7 +123,7 @@ public static String parseOptionalStringHeaderParameter(HttpServerRequest reques public static List parseStringListHeaderParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalStringListHeaderParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Header '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Header '%s' is required".formatted(name)); } return result; @@ -146,18 +146,18 @@ public static List parseOptionalStringListHeaderParameter(HttpServerRequ public static int parseIntegerHeaderParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = request.headers().get(name); if (result == null || result.isEmpty()) { - throw HttpServerResponseException.of(400, "Header '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Header '%s' is required".formatted(name)); } var first = result.iterator().next().trim(); if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Header '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Header '%s' has invalid blank string value".formatted(name)); } try { return Integer.parseInt(first); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Header %s(%s) has invalid value".formatted(name, first)); + throw new HttpServerResponseException(400, "Header %s(%s) has invalid value".formatted(name, first)); } } @@ -170,20 +170,20 @@ public static Integer parseOptionalIntegerHeaderParameter(HttpServerRequest requ var first = result.iterator().next().trim(); if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Header '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Header '%s' has invalid blank string value".formatted(name)); } try { return Integer.parseInt(first); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Header %s(%s) has invalid value".formatted(name, first)); + throw new HttpServerResponseException(400, "Header %s(%s) has invalid value".formatted(name, first)); } } public static List parseIntegerListHeaderParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalIntegerListHeaderParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Header '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Header '%s' is required".formatted(name)); } return result; } @@ -203,13 +203,13 @@ public static List parseOptionalIntegerListHeaderParameter(HttpServerRe for (String s : split) { s = s.trim(); if (s.isEmpty()) { - throw HttpServerResponseException.of(400, "Header %s(%s) has invalid value".formatted(name, header)); + throw new HttpServerResponseException(400, "Header %s(%s) has invalid value".formatted(name, header)); } try { result.add(Integer.parseInt(s)); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Header %s(%s) has invalid value".formatted(name, s)); + throw new HttpServerResponseException(400, "Header %s(%s) has invalid value".formatted(name, s)); } } } @@ -225,7 +225,7 @@ public static List parseOptionalIntegerListHeaderParameter(HttpServerRe public static UUID parseUuidQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalUuidQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; @@ -240,13 +240,13 @@ public static UUID parseOptionalUuidQueryParameter(HttpServerRequest request, St var first = result.iterator().next().trim(); if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return UUID.fromString(first); } catch (IllegalArgumentException e) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid value '%s'".formatted(name, result)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid value '%s'".formatted(name, result)); } } @@ -254,7 +254,7 @@ public static UUID parseOptionalUuidQueryParameter(HttpServerRequest request, St public static String parseStringQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalStringQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; @@ -273,7 +273,7 @@ public static String parseOptionalStringQueryParameter(HttpServerRequest request public static int parseIntegerQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalIntegerQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -287,20 +287,20 @@ public static Integer parseOptionalIntegerQueryParameter(HttpServerRequest reque var first = result.iterator().next().trim(); if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return Integer.parseInt(first); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, first)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, first)); } } public static long parseLongQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalLongQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -314,13 +314,13 @@ public static Long parseOptionalLongQueryParameter(HttpServerRequest request, St var first = result.iterator().next().trim(); if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return Long.parseLong(first); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, first)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, first)); } } @@ -328,7 +328,7 @@ public static Long parseOptionalLongQueryParameter(HttpServerRequest request, St public static > T parseEnumQueryParameter(HttpServerRequest request, Class type, String name) throws HttpServerResponseException { var result = parseOptionalEnumQueryParameter(request, type, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -342,20 +342,20 @@ public static > T parseOptionalEnumQueryParameter(HttpServerRe var first = result.iterator().next().trim(); if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return Enum.valueOf(type, first); } catch (Exception exception) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, result)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, result)); } } public static boolean parseBooleanQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalBooleanQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -369,21 +369,21 @@ public static Boolean parseOptionalBooleanQueryParameter(HttpServerRequest reque var first = result.iterator().next().trim(); if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { // todo return Boolean.parseBoolean(first); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, first)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, first)); } } public static double parseDoubleQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalDoubleQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -397,13 +397,13 @@ public static Double parseOptionalDoubleQueryParameter(HttpServerRequest request var first = result.iterator().next().trim(); if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return Double.parseDouble(first); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, first)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, first)); } } @@ -414,7 +414,7 @@ public static Double parseOptionalDoubleQueryParameter(HttpServerRequest request public static List parseIntegerListQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalIntegerListQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -431,13 +431,13 @@ public static List parseOptionalIntegerListQueryParameter(HttpServerReq .map(v -> { v = v.trim(); if (v.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return Integer.parseInt(v); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, v)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, v)); } }) .toList(); @@ -447,7 +447,7 @@ public static List parseOptionalIntegerListQueryParameter(HttpServerReq public static List parseUuidListQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalUuidListQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -464,13 +464,13 @@ public static List parseOptionalUuidListQueryParameter(HttpServerRequest r .map(v -> { v = v.trim(); if (v.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return UUID.fromString(v); } catch (IllegalArgumentException e) { - throw HttpServerResponseException.of(400, "Path parameter '%s' has invalid value '%s'".formatted(name, result)); + throw new HttpServerResponseException(400, "Path parameter '%s' has invalid value '%s'".formatted(name, result)); } }) .toList(); @@ -480,7 +480,7 @@ public static List parseOptionalUuidListQueryParameter(HttpServerRequest r public static List parseStringListQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalStringListQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -499,7 +499,7 @@ public static List parseOptionalStringListQueryParameter(HttpServerReque public static List parseLongListQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalLongListQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -516,13 +516,13 @@ public static List parseOptionalLongListQueryParameter(HttpServerRequest r .map(v -> { v = v.trim(); if (v.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return Long.parseLong(v); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, v)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, v)); } }) .toList(); @@ -532,7 +532,7 @@ public static List parseOptionalLongListQueryParameter(HttpServerRequest r public static List parseDoubleListQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalDoubleListQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -549,13 +549,13 @@ public static List parseOptionalDoubleListQueryParameter(HttpServerReque .map(v -> { v = v.trim(); if (v.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return Double.parseDouble(v); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, v)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, v)); } }) .toList(); @@ -565,7 +565,7 @@ public static List parseOptionalDoubleListQueryParameter(HttpServerReque public static List parseBooleanListQueryParameter(HttpServerRequest request, String name) throws HttpServerResponseException { var result = parseOptionalBooleanListQueryParameter(request, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -582,13 +582,13 @@ public static List parseOptionalBooleanListQueryParameter(HttpServerReq .map(v -> { v = v.trim(); if (v.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return Boolean.parseBoolean(v); } catch (NumberFormatException e) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, v)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, v)); } }) .toList(); @@ -598,7 +598,7 @@ public static List parseOptionalBooleanListQueryParameter(HttpServerReq public static > List parseEnumListQueryParameter(HttpServerRequest request, Class type, String name) throws HttpServerResponseException { var result = parseOptionalEnumListQueryParameter(request, type, name); if (result == null) { - throw HttpServerResponseException.of(400, "Query parameter '%s' is required".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' is required".formatted(name)); } return result; } @@ -615,13 +615,13 @@ public static > List parseOptionalEnumListQueryParameter(Ht .map(v -> { v = v.trim(); if (v.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '%s' has invalid blank string value".formatted(name)); + throw new HttpServerResponseException(400, "Query parameter '%s' has invalid blank string value".formatted(name)); } try { return Enum.valueOf(type, v); } catch (Exception exception) { - throw HttpServerResponseException.of(400, "Query parameter %s(%s) has invalid value".formatted(name, result)); + throw new HttpServerResponseException(400, "Query parameter %s(%s) has invalid value".formatted(name, result)); } }) .collect(Collectors.toList()); diff --git a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/StringParameterReader.java b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/StringParameterReader.java index 629efa7f9..0950d3d45 100644 --- a/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/StringParameterReader.java +++ b/http/http-server-common/src/main/java/ru/tinkoff/kora/http/server/common/handler/StringParameterReader.java @@ -12,7 +12,7 @@ static StringParameterReader of(Function converter, String err try { return converter.apply(string); } catch (Exception e) { - throw HttpServerResponseException.of(e, 400, errorMessage); + throw new HttpServerResponseException(400, errorMessage, e); } }; } @@ -22,7 +22,7 @@ static StringParameterReader of(Function converter, Function> NOT_FOUND_HANDLER = request -> - Mono.just(new SimpleHttpServerResponse(404, "application/octet-stream", HttpHeaders.of(), null)); + Mono.just(HttpServerResponse.of(404, "application/octet-stream")); private final Map>> pathTemplateMatcher; private final PathTemplateMatcher> allMethodMatchers; @@ -80,7 +80,7 @@ public int handlersSize() { return this.handlers.size(); } - public record PublicApiRequest(String method, String path, String hostName, String scheme, HttpHeaders headers, Map> queryParams, Flux body) {} + public record PublicApiRequest(String method, String path, String hostName, String scheme, HttpHeaders headers, Map> queryParams, Flux body) {} public void process(PublicApiRequest routerRequest, HttpServerResponseSender responseSender) { final Function> handlerFunction; @@ -93,7 +93,7 @@ public void process(PublicApiRequest routerRequest, HttpServerResponseSender res var allMethodMatch = allMethodMatchers.match(routerRequest.path); if (allMethodMatch != null) { var allowed = String.join(", ", allMethodMatch.value()); - handlerFunction = request -> Mono.just(new SimpleHttpServerResponse(405, "application/octet-stream", HttpHeaders.of("allow", allowed), null)); + handlerFunction = request -> Mono.just(HttpServerResponse.of(405, "application/octet-stream", HttpHeaders.of("allow", allowed))); routeTemplate = allMethodMatch.matchedTemplate(); templateParameters = Map.of(); } else { @@ -108,7 +108,6 @@ public void process(PublicApiRequest routerRequest, HttpServerResponseSender res } var request = new Request(routerRequest.method(), routerRequest.path(), routeTemplate, routerRequest.headers(), routerRequest.queryParams(), templateParameters, routerRequest.body()); - var ctx = this.telemetry.get().get(routerRequest, routeTemplate); var method = routerRequest.method; @@ -120,7 +119,7 @@ public void process(PublicApiRequest routerRequest, HttpServerResponseSender res error -> { var response = error instanceof HttpServerResponse httpServerResponse ? httpServerResponse - : new SimpleHttpServerResponse(500, "text/plain", HttpHeaders.of(), StandardCharsets.UTF_8.encode( + : HttpServerResponse.of(500, "text/plain", StandardCharsets.UTF_8.encode( Objects.requireNonNullElse(error.getMessage(), "Unknown error") )); this.sendResponse(ctx, responseSender, response, error); @@ -129,7 +128,7 @@ public void process(PublicApiRequest routerRequest, HttpServerResponseSender res } catch (Throwable error) { var response = error instanceof HttpServerResponse httpServerResponse ? httpServerResponse - : new SimpleHttpServerResponse(500, "text/plain", HttpHeaders.of(), StandardCharsets.UTF_8.encode( + : HttpServerResponse.of(500, "text/plain", StandardCharsets.UTF_8.encode( Objects.requireNonNullElse(error.getMessage(), "Unknown error") )); this.sendResponse(ctx, responseSender, response, error); @@ -146,7 +145,7 @@ private void sendResponse(HttpServerTelemetry.HttpServerTelemetryContext ctx, Ht } ctx.close(success.code(), resultCode, ex); } else if (result instanceof HttpServerResponseSender.ResponseBodyErrorBeforeCommit responseBodyError) { - var newResponse = new SimpleHttpServerResponse(500, "text/plain", HttpHeaders.of(), StandardCharsets.UTF_8.encode( + var newResponse = HttpServerResponse.of(500, "text/plain", StandardCharsets.UTF_8.encode( Objects.requireNonNullElse(responseBodyError.error().getMessage(), "Unknown error") )); responseSender.send(newResponse).subscribe(v -> { @@ -166,16 +165,13 @@ private String operation(String method, String routeTemplate) { return method + " " + routeTemplate; } - private record Request( - String method, - String path, - @Nullable String matchedTemplate, - HttpHeaders headers, - Map> queryParams, - Map pathParams, - Flux body) - - implements HttpServerRequest { + private record Request(String method, + String path, + @Nullable String matchedTemplate, + HttpHeaders headers, + Map> queryParams, + Map pathParams, + Flux body) implements HttpServerRequest { } private interface RequestHandler extends BiFunction>, Mono> {} diff --git a/http/http-server-common/src/main/kotlin/ru/tinkoff/kora/http/server/common/handler/ParameterExtractors.kt b/http/http-server-common/src/main/kotlin/ru/tinkoff/kora/http/server/common/handler/ParameterExtractors.kt index dbf1cad9d..7551ae3d4 100644 --- a/http/http-server-common/src/main/kotlin/ru/tinkoff/kora/http/server/common/handler/ParameterExtractors.kt +++ b/http/http-server-common/src/main/kotlin/ru/tinkoff/kora/http/server/common/handler/ParameterExtractors.kt @@ -7,86 +7,86 @@ import java.util.* @Throws(HttpServerResponseException::class) fun extractStringPathParameter(request: HttpServerRequest, name: String): String { - return request.pathParams()[name] ?: throw HttpServerResponseException.of(400, "Path parameter '$name' is required") + return request.pathParams()[name] ?: throw HttpServerResponseException(400, "Path parameter '$name' is required") } @Throws(HttpServerResponseException::class) fun extractUUIDPathParameter(request: HttpServerRequest, name: String): UUID { - var result = request.pathParams()[name] ?: throw HttpServerResponseException.of(400, "Path parameter '$name' is required") + var result = request.pathParams()[name] ?: throw HttpServerResponseException(400, "Path parameter '$name' is required") result = result.trim() if (result.isEmpty()) { - throw HttpServerResponseException.of(400, "Path parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Path parameter '$name' has invalid blank string value") } return try { UUID.fromString(result) } catch (e: IllegalArgumentException) { - throw HttpServerResponseException.of(400, "Path parameter '$name($result)' has invalid value") + throw HttpServerResponseException(400, "Path parameter '$name($result)' has invalid value") } } @Throws(HttpServerResponseException::class) fun extractIntPathParameter(request: HttpServerRequest, name: String): Int { - var result = request.pathParams()[name] ?: throw HttpServerResponseException.of(400, "Path parameter '$name' is required") + var result = request.pathParams()[name] ?: throw HttpServerResponseException(400, "Path parameter '$name' is required") result = result.trim() if (result.isEmpty()) { - throw HttpServerResponseException.of(400, "Path parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Path parameter '$name' has invalid blank string value") } return try { result.toInt() } catch (e: NumberFormatException) { - throw HttpServerResponseException.of(400, "Path parameter '$name($result)' has invalid value") + throw HttpServerResponseException(400, "Path parameter '$name($result)' has invalid value") } } @Throws(HttpServerResponseException::class) fun extractLongPathParameter(request: HttpServerRequest, name: String): Long { - var result = request.pathParams()[name] ?: throw HttpServerResponseException.of(400, "Path parameter '$name' is required") + var result = request.pathParams()[name] ?: throw HttpServerResponseException(400, "Path parameter '$name' is required") result = result.trim() if (result.isEmpty()) { - throw HttpServerResponseException.of(400, "Path parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Path parameter '$name' has invalid blank string value") } return try { result.toLong() } catch (e: NumberFormatException) { - throw HttpServerResponseException.of(400, "Path parameter '$name($result)' has invalid value") + throw HttpServerResponseException(400, "Path parameter '$name($result)' has invalid value") } } @Throws(HttpServerResponseException::class) fun extractDoublePathParameter(request: HttpServerRequest, name: String): Double { - var result = request.pathParams()[name] ?: throw HttpServerResponseException.of(400, "Path parameter '$name' is required") + var result = request.pathParams()[name] ?: throw HttpServerResponseException(400, "Path parameter '$name' is required") result = result.trim() if (result.isEmpty()) { - throw HttpServerResponseException.of(400, "Path parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Path parameter '$name' has invalid blank string value") } return try { result.toDouble() } catch (e: NumberFormatException) { - throw HttpServerResponseException.of(400, "Path parameter '$name($result)' has invalid value") + throw HttpServerResponseException(400, "Path parameter '$name($result)' has invalid value") } } @Throws(HttpServerResponseException::class) fun ?> extractEnumPathParameter(request: HttpServerRequest, enumType: Class?, name: String): T { - var result = request.pathParams()[name] ?: throw HttpServerResponseException.of(400, "Path parameter '$name' is required") + var result = request.pathParams()[name] ?: throw HttpServerResponseException(400, "Path parameter '$name' is required") result = result.trim() if (result.isEmpty()) { - throw HttpServerResponseException.of(400, "Path parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Path parameter '$name' has invalid blank string value") } return try { java.lang.Enum.valueOf(enumType, result) } catch (exception: Exception) { - throw HttpServerResponseException.of(400, "Path parameter '$name($result)' has invalid value") + throw HttpServerResponseException(400, "Path parameter '$name($result)' has invalid value") } } @@ -95,7 +95,7 @@ fun ?> extractEnumPathParameter(request: HttpServerRequest, enumType */ @Throws(HttpServerResponseException::class) fun extractStringHeaderParameter(request: HttpServerRequest, name: String): String { - val result = request.headers()[name] ?: throw HttpServerResponseException.of(400, "Header '$name' is required") + val result = request.headers()[name] ?: throw HttpServerResponseException(400, "Header '$name' is required") return result.joinToString(", ") } @@ -107,7 +107,7 @@ fun extractNullableStringHeaderParameter(request: HttpServerRequest, name: Strin @Throws(HttpServerResponseException::class) fun extractStringListHeaderParameter(request: HttpServerRequest, name: String): List { - return extractNullableStringListHeaderParameter(request, name) ?: throw HttpServerResponseException.of(400, "Header '$name' is required") + return extractNullableStringListHeaderParameter(request, name) ?: throw HttpServerResponseException(400, "Header '$name' is required") } @Throws(HttpServerResponseException::class) @@ -127,7 +127,7 @@ fun extractNullableStringListHeaderParameter(request: HttpServerRequest, name: S fun extractStringQueryParameter(request: HttpServerRequest, name: String): String { val result = request.queryParams()[name] if (result.isNullOrEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + throw HttpServerResponseException(400, "Query parameter '$name' is required") } return result.iterator().next() } @@ -140,7 +140,7 @@ fun extractNullableStringQueryParameter(request: HttpServerRequest, name: String @Throws(HttpServerResponseException::class) fun extractStringListQueryParameter(request: HttpServerRequest, name: String): List { - val result = request.queryParams()[name] ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + val result = request.queryParams()[name] ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") return if (result.isEmpty()) emptyList() else result.toMutableList().toList() } @@ -152,7 +152,7 @@ fun extractNullableStringListQueryParameter(request: HttpServerRequest, name: St @Throws(HttpServerResponseException::class) fun extractUUIDQueryParameter(request: HttpServerRequest, name: String): UUID { - return extractNullableUUIDQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableUUIDQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -164,19 +164,19 @@ fun extractNullableUUIDQueryParameter(request: HttpServerRequest, name: String): val first = result.iterator().next().trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } return try { UUID.fromString(first) } catch (e: IllegalArgumentException) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } @Throws(HttpServerResponseException::class) fun extractUUIDListQueryParameter(request: HttpServerRequest, name: String): List { - return extractNullableUUIDListQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableUUIDListQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -186,13 +186,13 @@ fun extractNullableUUIDListQueryParameter(request: HttpServerRequest, name: Stri .map { val first = it.trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } try { UUID.fromString(first) } catch (e: IllegalArgumentException) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } .toList() @@ -200,7 +200,7 @@ fun extractNullableUUIDListQueryParameter(request: HttpServerRequest, name: Stri @Throws(HttpServerResponseException::class) fun extractIntQueryParameter(request: HttpServerRequest, name: String): Int { - return extractNullableIntQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableIntQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -212,19 +212,19 @@ fun extractNullableIntQueryParameter(request: HttpServerRequest, name: String): val first = result.iterator().next().trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } return try { first.toInt() } catch (e: NumberFormatException) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } @Throws(HttpServerResponseException::class) fun extractIntListQueryParameter(request: HttpServerRequest, name: String): List { - return extractNullableIntListQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableIntListQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -233,20 +233,20 @@ fun extractNullableIntListQueryParameter(request: HttpServerRequest, name: Strin return result.mapNotNull { v -> val first = v.trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } try { first.toInt() } catch (e: NumberFormatException) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } } @Throws(HttpServerResponseException::class) fun extractLongQueryParameter(request: HttpServerRequest, name: String): Long { - return extractNullableLongQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableLongQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -258,19 +258,19 @@ fun extractNullableLongQueryParameter(request: HttpServerRequest, name: String): val first = result.iterator().next().trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } return try { first.toLong() } catch (e: NumberFormatException) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } @Throws(HttpServerResponseException::class) fun extractLongListQueryParameter(request: HttpServerRequest, name: String): List { - return extractNullableLongListQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableLongListQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -279,20 +279,20 @@ fun extractNullableLongListQueryParameter(request: HttpServerRequest, name: Stri return result.mapNotNull { v -> val first = v.trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } try { first.toLong() } catch (e: NumberFormatException) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } } @Throws(HttpServerResponseException::class) fun extractDoubleQueryParameter(request: HttpServerRequest, name: String): Double { - return extractNullableDoubleQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableDoubleQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -304,19 +304,19 @@ fun extractNullableDoubleQueryParameter(request: HttpServerRequest, name: String val first = result.iterator().next().trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } return try { first.toDouble() } catch (e: NumberFormatException) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } @Throws(HttpServerResponseException::class) fun extractDoubleListQueryParameter(request: HttpServerRequest, name: String): List { - return extractNullableDoubleListQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableDoubleListQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -325,20 +325,20 @@ fun extractNullableDoubleListQueryParameter(request: HttpServerRequest, name: St return result.mapNotNull { v -> val first = v.trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } try { first.toDouble() } catch (e: NumberFormatException) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } } @Throws(HttpServerResponseException::class) fun extractBooleanQueryParameter(request: HttpServerRequest, name: String): Boolean { - return extractNullableBooleanQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableBooleanQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -350,19 +350,19 @@ fun extractNullableBooleanQueryParameter(request: HttpServerRequest, name: Strin val first = result.iterator().next().trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } return try { first.toBoolean() } catch (e: Exception) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } @Throws(HttpServerResponseException::class) fun extractBooleanListQueryParameter(request: HttpServerRequest, name: String): List { - return extractNullableBooleanListQueryParameter(request, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableBooleanListQueryParameter(request, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -371,20 +371,20 @@ fun extractNullableBooleanListQueryParameter(request: HttpServerRequest, name: S return result.mapNotNull { v -> val first = v.trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } try { first.toBoolean() } catch (e: Exception) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } } @Throws(HttpServerResponseException::class) fun ?> extractEnumQueryParameter(request: HttpServerRequest, type: Class?, name: String): T { - return extractNullableEnumQueryParameter(request, type, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableEnumQueryParameter(request, type, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -396,19 +396,19 @@ fun ?> extractNullableEnumQueryParameter(request: HttpServerRequest, val first = result.iterator().next().trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } return try { java.lang.Enum.valueOf(type, first) } catch (exception: Exception) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } @Throws(HttpServerResponseException::class) fun ?> extractEnumListQueryParameter(request: HttpServerRequest, type: Class, name: String): List { - return extractNullableEnumListQueryParameter(request, type, name) ?: throw HttpServerResponseException.of(400, "Query parameter '$name' is required") + return extractNullableEnumListQueryParameter(request, type, name) ?: throw HttpServerResponseException(400, "Query parameter '$name' is required") } @Throws(HttpServerResponseException::class) @@ -417,13 +417,13 @@ fun ?> extractNullableEnumListQueryParameter(request: HttpServerRequ return result.mapNotNull { v -> val first = v.trim() if (first.isEmpty()) { - throw HttpServerResponseException.of(400, "Query parameter '$name' has invalid blank string value") + throw HttpServerResponseException(400, "Query parameter '$name' has invalid blank string value") } try { java.lang.Enum.valueOf(type, v) } catch (e: Exception) { - throw HttpServerResponseException.of(400, "Query parameter '$name($first)' has invalid value") + throw HttpServerResponseException(400, "Query parameter '$name($first)' has invalid value") } } } diff --git a/http/http-server-common/src/test/java/ru/tinkoff/kora/http/server/common/form/MultipartReaderTest.java b/http/http-server-common/src/test/java/ru/tinkoff/kora/http/server/common/form/MultipartReaderTest.java index 331939e38..b2fbfd82d 100644 --- a/http/http-server-common/src/test/java/ru/tinkoff/kora/http/server/common/form/MultipartReaderTest.java +++ b/http/http-server-common/src/test/java/ru/tinkoff/kora/http/server/common/form/MultipartReaderTest.java @@ -10,10 +10,7 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -265,7 +262,7 @@ public String path() { @Override public HttpHeaders headers() { - @SuppressWarnings({"unchecked", "rawtypes"}) + @SuppressWarnings({"unchecked"}) Map.Entry>[] entries = new Map.Entry[headers.length]; for (int i = 0; i < headers.length; i++) { entries[i] = Map.entry(headers[i].getKey(), List.of(headers[i].getValue())); @@ -274,7 +271,7 @@ public HttpHeaders headers() { } @Override - public Map> queryParams() { + public Map> queryParams() { var questionMark = path.indexOf('?'); if (questionMark < 0) { return Map.of(); @@ -284,14 +281,14 @@ public Map> queryParams() { .map(param -> { var eq = param.indexOf('='); if (eq <= 0) { - return Map.entry(param, new ArrayDeque(0)); + return Map.entry(param, new ArrayList(0)); } var name = param.substring(0, eq); var value = param.substring(eq + 1); - return Map.entry(name, new ArrayDeque<>(List.of(value))); + return Map.entry(name, new ArrayList<>(List.of(value))); }) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (d1, d2) -> { - var d3 = new ArrayDeque<>(d1); + var d3 = new ArrayList<>(d1); d3.addAll(d2); return d3; })); diff --git a/http/http-server-common/src/test/java/ru/tinkoff/kora/http/server/common/router/PublicApiHandlerTest.java b/http/http-server-common/src/test/java/ru/tinkoff/kora/http/server/common/router/PublicApiHandlerTest.java index 10cde00d2..265ff600f 100644 --- a/http/http-server-common/src/test/java/ru/tinkoff/kora/http/server/common/router/PublicApiHandlerTest.java +++ b/http/http-server-common/src/test/java/ru/tinkoff/kora/http/server/common/router/PublicApiHandlerTest.java @@ -9,8 +9,8 @@ import ru.tinkoff.kora.application.graph.ValueOf; import ru.tinkoff.kora.http.common.HttpHeaders; import ru.tinkoff.kora.http.server.common.HttpServerRequestHandler; +import ru.tinkoff.kora.http.server.common.HttpServerResponse; import ru.tinkoff.kora.http.server.common.HttpServerResponseSender; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import ru.tinkoff.kora.http.server.common.handler.HttpServerRequestHandlerImpl; import ru.tinkoff.kora.http.server.common.telemetry.HttpServerTelemetry; @@ -52,14 +52,14 @@ void testWildcard() { var responseSender = mock(HttpServerResponseSender.class); when(responseSender.send(any())).thenReturn(Mono.just(new HttpServerResponseSender.Success(200))); - var request = new PublicApiHandler.PublicApiRequest("POST", "/test", "test", "http", HttpHeaders.EMPTY, Map.of(), Flux.empty()); + var request = new PublicApiHandler.PublicApiRequest("POST", "/test", "test", "http", HttpHeaders.of(), Map.of(), Flux.empty()); handler.process(request, responseSender); verify(responseSender).send(argThat(argument -> argument.code() == 200)); } private HttpServerRequestHandler handler(String method, String route) { - return new HttpServerRequestHandlerImpl(method, route, httpServerRequest -> Mono.just(new SimpleHttpServerResponse(200, "application/octet-stream", HttpHeaders.EMPTY, null))); + return new HttpServerRequestHandlerImpl(method, route, httpServerRequest -> Mono.just(HttpServerResponse.of(200, "application/octet-stream"))); } private ValueOf valueOf(T object) { diff --git a/http/http-server-common/src/testFixtures/java/ru/tinkoff/kora/http/server/common/HttpServerTestKit.java b/http/http-server-common/src/testFixtures/java/ru/tinkoff/kora/http/server/common/HttpServerTestKit.java index d298fb499..bcf392243 100644 --- a/http/http-server-common/src/testFixtures/java/ru/tinkoff/kora/http/server/common/HttpServerTestKit.java +++ b/http/http-server-common/src/testFixtures/java/ru/tinkoff/kora/http/server/common/HttpServerTestKit.java @@ -172,7 +172,7 @@ void testReadinessFailureOnUninitializedProbe() throws IOException { @Test void testHelloWorld() throws IOException { - var httpResponse = new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8))); + var httpResponse = HttpServerResponse.of(200, "text/plain", "hello world".getBytes(StandardCharsets.UTF_8)); var handler = handler(GET, "/", request -> Mono.delay(Duration.ofMillis(ThreadLocalRandom.current().nextInt(100, 500))).thenReturn(httpResponse)); this.startServer(handler); @@ -193,7 +193,7 @@ void testHelloWorld() throws IOException { void serverWithBigResponse() throws IOException { var data = new byte[10 * 1024 * 1024]; ThreadLocalRandom.current().nextBytes(data); - var httpResponse = new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), 10 * 1024 * 1024, Mono.fromCallable(() -> ByteBuffer.wrap(data)) + var httpResponse = HttpServerResponse.of(200, "text/plain", HttpHeaders.of(), 10 * 1024 * 1024, Mono.fromCallable(() -> ByteBuffer.wrap(data)) .delayElement(Duration.ofMillis(100)) .flux()); var handler = handler(GET, "/", request -> Mono.delay(Duration.ofMillis(ThreadLocalRandom.current().nextInt(100, 500))).thenReturn(httpResponse)); @@ -222,7 +222,7 @@ void testStreamResult() throws IOException { System.arraycopy(bytes, 0, data, i * 1024, 1024); } - var httpResponse = new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), 102400, Flux.fromIterable(dataList).map(ByteBuffer::wrap)); + var httpResponse = HttpServerResponse.of(200, "text/plain", HttpHeaders.of(), 102400, Flux.fromIterable(dataList).map(ByteBuffer::wrap)); var handler = handler(GET, "/", request -> Mono.delay(Duration.ofMillis(ThreadLocalRandom.current().nextInt(100, 500))).thenReturn(httpResponse)); this.startServer(handler); @@ -241,7 +241,7 @@ void testStreamResult() throws IOException { @Test void testHelloWorldParallel() throws ExecutionException, InterruptedException { - var httpResponse = new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8))); + var httpResponse = HttpServerResponse.of(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8))); var handler = handler(GET, "/", request -> Mono.delay(Duration.ofMillis(ThreadLocalRandom.current().nextInt(100, 500))).thenReturn(httpResponse)); this.startServer(handler); @@ -283,7 +283,7 @@ public void onResponse(@Nonnull Call call, @Nonnull Response response) throws IO @Test void testUnknownPath() throws IOException { - var httpResponse = new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8))); + var httpResponse = HttpServerResponse.of(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8))); var handler = handler(GET, "/", request -> Mono.delay(Duration.ofMillis(ThreadLocalRandom.current().nextInt(100, 500))).thenReturn(httpResponse)); this.startServer(handler); @@ -388,7 +388,7 @@ void testExceptionOnFirstResponseBodyPart() throws IOException { @Test void testHttpResponseExceptionOnHandle() throws IOException { var handler = handler(GET, "/", request -> { - throw HttpServerResponseException.of(400, "test"); + throw new HttpServerResponseException(400, "test"); }); this.startServer(handler); @@ -406,7 +406,7 @@ void testHttpResponseExceptionOnHandle() throws IOException { @Test void testHttpResponseExceptionInResult() throws IOException { - var handler = handler(GET, "/", request -> Mono.error(HttpServerResponseException.of(400, "test"))); + var handler = handler(GET, "/", request -> Mono.error(new HttpServerResponseException(400, "test"))); this.startServer(handler); var request = request("/") @@ -472,7 +472,7 @@ void testErrorWithEmptyMessage() throws IOException { @Test void testEmptyBodyHandling() throws IOException { var handler = handler(POST, "/", request -> ReactorUtils.toByteArrayMono(request.body()) - .thenReturn(new SimpleHttpServerResponse( + .thenReturn(HttpServerResponse.of( 200, "application/octet-stream", HttpHeaders.of(), @@ -492,7 +492,7 @@ void testEmptyBodyHandling() throws IOException { @Test void testRequestBody() throws IOException { - var httpResponse = new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8))); + var httpResponse = HttpServerResponse.of(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8))); var executor = Executors.newSingleThreadExecutor(); var size = 20 * 1024 * 1024; var handler = handler(POST, "/", request -> Mono.create(sink -> { @@ -524,7 +524,7 @@ void testRequestBody() throws IOException { @Test void testInterceptor() throws IOException { - var httpResponse = new SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8))); + var httpResponse = HttpServerResponse.of(200, "text/plain", HttpHeaders.of(), ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8))); var handler = handler(GET, "/", request -> Mono.delay(Duration.ofMillis(ThreadLocalRandom.current().nextInt(100, 500))).thenReturn(httpResponse)); var interceptor1 = new HttpServerInterceptor() { @Override @@ -532,7 +532,7 @@ public Mono intercept(HttpServerRequest request, Function intercept(HttpServerRequest request, Function { override fun apply(request: HttpServerRequest): Mono { if (request.headers().getFirst("Test-Header") == null) { - throw HttpServerResponseException.of( + throw HttpServerResponseException( 400, "TEST" ) diff --git a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/controllers/TestControllerWithDifferentTypes.kt b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/controllers/TestControllerWithDifferentTypes.kt index e8a8f172e..73ff819d5 100644 --- a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/controllers/TestControllerWithDifferentTypes.kt +++ b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/controllers/TestControllerWithDifferentTypes.kt @@ -8,7 +8,6 @@ import ru.tinkoff.kora.http.common.HttpMethod import ru.tinkoff.kora.http.common.annotation.HttpRoute import ru.tinkoff.kora.http.server.common.HttpServerRequest import ru.tinkoff.kora.http.server.common.HttpServerResponse -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse import ru.tinkoff.kora.http.server.common.annotation.HttpController import java.nio.ByteBuffer import java.nio.charset.StandardCharsets @@ -16,11 +15,10 @@ import java.nio.charset.StandardCharsets @HttpController open class TestControllerWithDifferentTypes { @HttpRoute(method = HttpMethod.GET, path = "/") - open suspend fun getRoot(): SimpleHttpServerResponse { - val response = SimpleHttpServerResponse( + open suspend fun getRoot(): HttpServerResponse { + val response = HttpServerResponse.of( 200, "text/plain", - HttpHeaders.of(), StandardCharsets.UTF_8.encode("Hello world") ) delay(1) @@ -29,7 +27,7 @@ open class TestControllerWithDifferentTypes { @HttpRoute(method = HttpMethod.GET, path = "/somePage") open suspend fun getSomePage(httpServerRequest: HttpServerRequest?): HttpServerResponse { - val response = SimpleHttpServerResponse(200, "text/plain", HttpHeaders.of(), StandardCharsets.UTF_8.encode("Hello world")) + val response = HttpServerResponse.of(200, "text/plain", StandardCharsets.UTF_8.encode("Hello world")) delay(1000) return response diff --git a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/controllers/TestControllerWithMappers.kt b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/controllers/TestControllerWithMappers.kt index 4574ca98e..b1ad2b644 100644 --- a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/controllers/TestControllerWithMappers.kt +++ b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/controllers/TestControllerWithMappers.kt @@ -8,7 +8,6 @@ import ru.tinkoff.kora.http.common.HttpMethod import ru.tinkoff.kora.http.common.annotation.HttpRoute import ru.tinkoff.kora.http.server.common.HttpServerRequest import ru.tinkoff.kora.http.server.common.HttpServerResponse -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse import ru.tinkoff.kora.http.server.common.annotation.HttpController import ru.tinkoff.kora.http.server.common.handler.HttpServerRequestMapper import ru.tinkoff.kora.http.server.common.handler.HttpServerResponseMapper @@ -51,10 +50,9 @@ open class TestControllerWithMappers { class StringResponseMapper : HttpServerResponseMapper { override fun apply(result: String?): Mono { return Mono.just( - SimpleHttpServerResponse( + HttpServerResponse.of( 200, "text/plain", - HttpHeaders.of(), StandardCharsets.UTF_8.encode(result) ) ) diff --git a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/Mappers.java b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/Mappers.java index 223e2e3a7..3d410c729 100644 --- a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/Mappers.java +++ b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/Mappers.java @@ -11,7 +11,6 @@ import ru.tinkoff.kora.http.server.common.HttpServerRequest; import ru.tinkoff.kora.http.server.common.HttpServerResponse; import ru.tinkoff.kora.http.server.common.HttpServerResponseEntity; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import ru.tinkoff.kora.http.server.common.handler.BlockingRequestExecutor; import ru.tinkoff.kora.http.server.common.handler.HttpServerRequestMapper; import ru.tinkoff.kora.http.server.common.handler.HttpServerResponseEntityMapper; diff --git a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/Mappers.kt b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/Mappers.kt index 529333075..8de49b138 100644 --- a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/Mappers.kt +++ b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/Mappers.kt @@ -10,7 +10,6 @@ import ru.tinkoff.kora.http.common.HttpHeaders import ru.tinkoff.kora.http.server.common.HttpServerRequest import ru.tinkoff.kora.http.server.common.HttpServerResponse import ru.tinkoff.kora.http.server.common.HttpServerResponseEntity -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse import ru.tinkoff.kora.http.server.common.handler.* import ru.tinkoff.kora.http.server.symbol.processor.controllers.ReadableEntity import ru.tinkoff.kora.http.server.symbol.processor.controllers.SomeEntity @@ -117,7 +116,7 @@ object Mappers { if (responseType == Integer::class.java) { return integerResponseMapper() } - if (responseType == HttpServerResponse::class.java || responseType == SimpleHttpServerResponse::class.java) { + if (responseType == HttpServerResponse::class.java) { return noopResponseMapper() } if (responseType == SomeEntity::class.java) { @@ -150,11 +149,10 @@ object Mappers { private fun jsonResponseMapper(someEntityClass: TypeRef): HttpServerResponseMapper { return HttpServerResponseMapper { result -> Mono.just( - SimpleHttpServerResponse( + HttpServerResponse.of( 200, "text/plain", - HttpHeaders.EMPTY, - ByteBuffer.wrap(result.toString().toByteArray(StandardCharsets.UTF_8)) + result.toString().toByteArray(StandardCharsets.UTF_8) ) ) } @@ -183,11 +181,9 @@ object Mappers { private fun voidResponseMapper(): HttpServerResponseMapper { return HttpServerResponseMapper { result: Unit? -> Mono.just( - SimpleHttpServerResponse( + HttpServerResponse.of( 200, - "text/plain", - HttpHeaders.of(), - null + "text/plain" ) ) } @@ -196,10 +192,9 @@ object Mappers { private fun stringResponseMapper(): HttpServerResponseMapper { return HttpServerResponseMapper { result: String? -> Mono.just( - SimpleHttpServerResponse( + HttpServerResponse.of( 200, "text/plain", - HttpHeaders.of(), StandardCharsets.UTF_8.encode(result ?: "null") ) ) @@ -215,10 +210,9 @@ object Mappers { private fun integerResponseMapper(): HttpServerResponseMapper { return HttpServerResponseMapper { r: Int -> Mono.just( - SimpleHttpServerResponse( + HttpServerResponse.of( 200, "text/plain", - HttpHeaders.of(), StandardCharsets.UTF_8.encode(r.toString()) ) ) diff --git a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/SimpleHttpServerRequest.kt b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/SimpleHttpServerRequest.kt index 7370338e1..0572f2a75 100644 --- a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/SimpleHttpServerRequest.kt +++ b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/SimpleHttpServerRequest.kt @@ -5,6 +5,7 @@ import ru.tinkoff.kora.http.common.HttpHeaders import ru.tinkoff.kora.http.server.common.HttpServerRequest import java.nio.ByteBuffer import java.util.* +import kotlin.collections.ArrayList internal class SimpleHttpServerRequest( private val method: String, @@ -33,13 +34,13 @@ internal class SimpleHttpServerRequest( return HttpHeaders.of(*entries) } - override fun queryParams(): Map> { + override fun queryParams(): Map> { val questionMark = path.indexOf('?') if (questionMark < 0) { return mapOf() } val params = path.substring(questionMark + 1) - val result = mutableMapOf>() + val result = mutableMapOf>() params.split("&".toRegex()).forEach { param -> val eq = param.indexOf('=') if (eq <= 0) { @@ -47,7 +48,7 @@ internal class SimpleHttpServerRequest( } val name = param.substring(0, eq) val value = param.substring(eq + 1) - result[name]?.add(value) ?: result.put(name, ArrayDeque().apply { this.add(value) }) + result[name]?.add(value) ?: result.put(name, ArrayList().apply { this.add(value) }) } return result } diff --git a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/TestHttpServer.kt b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/TestHttpServer.kt index f56d8cd90..0d524ff76 100644 --- a/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/TestHttpServer.kt +++ b/http/http-server-symbol-processor/src/test/kotlin/ru/tinkoff/kora/http/server/symbol/processor/server/TestHttpServer.kt @@ -6,7 +6,6 @@ import reactor.core.publisher.Mono import ru.tinkoff.kora.http.common.HttpHeaders import ru.tinkoff.kora.http.server.common.HttpServerRequestHandler import ru.tinkoff.kora.http.server.common.HttpServerResponse -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse import ru.tinkoff.kora.http.server.symbol.procesor.HttpControllerProcessorProvider import ru.tinkoff.kora.ksp.common.symbolProcess import java.lang.invoke.MethodHandles @@ -41,7 +40,7 @@ class TestHttpServer(private val requestHandlers: List? { diff --git a/http/http-server-undertow/src/main/java/ru/tinkoff/kora/http/server/undertow/UndertowHttpHeaders.java b/http/http-server-undertow/src/main/java/ru/tinkoff/kora/http/server/undertow/UndertowHttpHeaders.java index 487fa91b4..49bfb2931 100644 --- a/http/http-server-undertow/src/main/java/ru/tinkoff/kora/http/server/undertow/UndertowHttpHeaders.java +++ b/http/http-server-undertow/src/main/java/ru/tinkoff/kora/http/server/undertow/UndertowHttpHeaders.java @@ -10,6 +10,7 @@ import java.util.Map; public class UndertowHttpHeaders implements HttpHeaders { + private final HeaderMap headerMap; public UndertowHttpHeaders(HeaderMap headerMap) { @@ -58,4 +59,9 @@ public Map.Entry> next() { } }; } + + @Override + public String toString() { + return headerMap.toString(); + } } diff --git a/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/client/JacksonHttpClientRequestMapper.java b/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/client/JacksonHttpClientRequestMapper.java index 113ef8739..a5a822dc7 100644 --- a/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/client/JacksonHttpClientRequestMapper.java +++ b/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/client/JacksonHttpClientRequestMapper.java @@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.ObjectWriter; import ru.tinkoff.kora.application.graph.TypeRef; import ru.tinkoff.kora.http.client.common.HttpClientEncoderException; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper; public class JacksonHttpClientRequestMapper implements HttpClientRequestMapper { @@ -21,7 +21,7 @@ public JacksonHttpClientRequestMapper(ObjectMapper objectMapper, TypeReference request) { + public HttpClientRequest.Builder apply(Request request) { try { var bytes = this.objectWriter.writeValueAsBytes(request.parameter()); return request.builder().body(bytes) diff --git a/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/server/JacksonHttpServerRequestMapper.java b/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/server/JacksonHttpServerRequestMapper.java index 8805fa506..d23bdef92 100644 --- a/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/server/JacksonHttpServerRequestMapper.java +++ b/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/server/JacksonHttpServerRequestMapper.java @@ -24,7 +24,7 @@ public Mono apply(HttpServerRequest request) { try { sink.next(this.objectMapper.readValue(bytes)); } catch (Exception e) { - var httpException = HttpServerResponseException.of(e, 400, e.getMessage()); + var httpException = new HttpServerResponseException(400, e.getMessage(), e); sink.error(httpException); } }); diff --git a/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/server/JacksonHttpServerResponseMapper.java b/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/server/JacksonHttpServerResponseMapper.java index 2ea0d946b..4f3e10766 100644 --- a/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/server/JacksonHttpServerResponseMapper.java +++ b/json/jackson-module/src/main/java/ru/tinkoff/kora/json/jackson/module/http/server/JacksonHttpServerResponseMapper.java @@ -7,7 +7,6 @@ import ru.tinkoff.kora.application.graph.TypeRef; import ru.tinkoff.kora.http.common.HttpHeaders; import ru.tinkoff.kora.http.server.common.HttpServerResponse; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import ru.tinkoff.kora.http.server.common.handler.HttpServerResponseMapper; import java.nio.ByteBuffer; @@ -23,7 +22,7 @@ public JacksonHttpServerResponseMapper(ObjectMapper objectMapper, TypeRef typ public Mono apply(Object result) { return Mono.fromCallable(() -> { var resultBytes = this.objectMapper.writeValueAsBytes(result); - return new SimpleHttpServerResponse(200, "application/json", HttpHeaders.of(), resultBytes.length, Flux.just(ByteBuffer.wrap(resultBytes))); + return HttpServerResponse.of(200, "application/json", resultBytes); }); } } diff --git a/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/client/JsonHttpClientRequestMapper.java b/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/client/JsonHttpClientRequestMapper.java index 0873ce10f..ffd284cbe 100644 --- a/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/client/JsonHttpClientRequestMapper.java +++ b/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/client/JsonHttpClientRequestMapper.java @@ -1,7 +1,7 @@ package ru.tinkoff.kora.json.module.http.client; import ru.tinkoff.kora.http.client.common.HttpClientEncoderException; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper; import ru.tinkoff.kora.json.common.JsonWriter; @@ -15,7 +15,7 @@ public JsonHttpClientRequestMapper(JsonWriter jsonWriter) { } @Override - public HttpClientRequestBuilder apply(Request request) { + public HttpClientRequest.Builder apply(Request request) { try { var bytes = this.jsonWriter.toByteArray(request.parameter()); return request.builder().body(bytes) diff --git a/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonReaderHttpServerRequestMapper.java b/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonReaderHttpServerRequestMapper.java index c514416c5..f350529b5 100644 --- a/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonReaderHttpServerRequestMapper.java +++ b/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonReaderHttpServerRequestMapper.java @@ -21,7 +21,7 @@ public Mono apply(HttpServerRequest request) { try { sink.next(this.reader.read(bytes)); } catch (Exception e) { - var httpException = HttpServerResponseException.of(e, 400, e.getMessage()); + var httpException = new HttpServerResponseException(400, e); sink.error(httpException); } }); diff --git a/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonStringParameterReader.java b/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonStringParameterReader.java index 4b9090937..4cfe9a138 100644 --- a/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonStringParameterReader.java +++ b/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonStringParameterReader.java @@ -19,7 +19,7 @@ public T read(String string) { try { return this.reader.read(JsonCommonModule.JSON_FACTORY.createParser(string)); } catch (IOException e) { - throw HttpServerResponseException.of(400, e.getMessage()); + throw new HttpServerResponseException(400, e.getMessage()); } } } diff --git a/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonWriterHttpServerResponseMapper.java b/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonWriterHttpServerResponseMapper.java index 455a21bbb..3807ff832 100644 --- a/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonWriterHttpServerResponseMapper.java +++ b/json/json-module/src/main/java/ru/tinkoff/kora/json/module/http/server/JsonWriterHttpServerResponseMapper.java @@ -4,7 +4,6 @@ import reactor.core.publisher.Mono; import ru.tinkoff.kora.http.common.HttpHeaders; import ru.tinkoff.kora.http.server.common.HttpServerResponse; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import ru.tinkoff.kora.http.server.common.handler.HttpServerResponseMapper; import ru.tinkoff.kora.json.common.JsonWriter; @@ -22,7 +21,7 @@ public Mono apply(T result) { return Mono.fromCallable(() -> { var bytes = JsonWriterHttpServerResponseMapper.this.writer.toByteArray(result); var byteBuffer = ByteBuffer.wrap(bytes); - return new SimpleHttpServerResponse(200, "application/json", HttpHeaders.of(), bytes.length, Flux.just(byteBuffer)); + return HttpServerResponse.of(200, "application/json", byteBuffer); }); } } diff --git a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaClientRequestMappers.mustache b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaClientRequestMappers.mustache index 06af1e50e..3b6f1b7b2 100644 --- a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaClientRequestMappers.mustache +++ b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaClientRequestMappers.mustache @@ -3,7 +3,7 @@ package {{package}}; import ru.tinkoff.kora.http.client.common.form.UrlEncodedWriter; import ru.tinkoff.kora.http.client.common.form.MultipartWriter; import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; import reactor.core.publisher.Mono; @ru.tinkoff.kora.common.annotation.Generated("openapi generator kora client"){{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}} @@ -29,7 +29,7 @@ public interface {{classname}}ClientRequestMappers { {{/vendorExtensions.requiresFormParamMappers}} @Override - public HttpClientRequestBuilder apply(HttpClientRequestMapper.Request<{{classname}}.{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}FormParam> request) { + public HttpClientRequest.Builder apply(HttpClientRequestMapper.Request<{{classname}}.{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}FormParam> request) { {{#vendorExtensions.urlEncodedForm}} var b = new UrlEncodedWriter();{{#formParams}} if (request.parameter().{{paramName}}() != null) { diff --git a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerRequestMappers.mustache b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerRequestMappers.mustache index 496e01c55..a3d430c4c 100644 --- a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerRequestMappers.mustache +++ b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerRequestMappers.mustache @@ -3,6 +3,7 @@ package {{package}}; import ru.tinkoff.kora.http.server.common.form.MultipartReader; import ru.tinkoff.kora.http.server.common.handler.HttpServerRequestMapper; import ru.tinkoff.kora.http.server.common.HttpServerRequest; +import ru.tinkoff.kora.http.server.common.HttpServerResponseException; import reactor.core.publisher.Mono; @ru.tinkoff.kora.common.annotation.Generated("openapi generator kora client"){{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}} @@ -40,7 +41,7 @@ public interface {{classname}}ServerRequestMappers { {{/isArray}}{{^isArray}} {{#required}} if ({{paramName}}Part == null || {{paramName}}Part.values().isEmpty()) { - sink.error(ru.tinkoff.kora.http.server.common.HttpServerResponseException.of(400, "Form field '{{baseName}}' is required")); + sink.error(new HttpServerResponseException(400, "Form field '{{baseName}}' is required")); return; } {{#vendorExtensions.requiresMapper}} @@ -85,7 +86,7 @@ public interface {{classname}}ServerRequestMappers { .handle((state, sink) -> { {{#formParams}}{{#required}} if (state.{{paramName}} == null) { - sink.error(ru.tinkoff.kora.http.server.common.HttpServerResponseException.of(400, "Form field '{{baseName}}' is required")); + sink.error(new HttpServerResponseException(400, "Form field '{{baseName}}' is required")); return; } {{/required}}{{/formParams}} diff --git a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerResponseMappers.mustache b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerResponseMappers.mustache index b4ceb1dc2..d4c2818cc 100644 --- a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerResponseMappers.mustache +++ b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerResponseMappers.mustache @@ -3,7 +3,6 @@ package {{package}}; import ru.tinkoff.kora.http.server.common.handler.HttpServerResponseMapper; import ru.tinkoff.kora.http.server.common.HttpServerResponse; import ru.tinkoff.kora.http.server.common.HttpServerResponseEntity; -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse; import ru.tinkoff.kora.http.common.HttpHeaders; import reactor.core.publisher.Mono; import {{package}}.{{classname}}Responses.*; @@ -49,7 +48,7 @@ public interface {{classname}}ServerResponseMappers { {{/headers}} ); {{^dataType}} - return Mono.just(new SimpleHttpServerResponse({{#isDefault}}rs.statusCode(){{/isDefault}}{{^isDefault}}{{code}}{{/isDefault}}, "application/octet-stream", headers, null)); + return Mono.just(HttpServerResponse.of({{#isDefault}}rs.statusCode(){{/isDefault}}{{^isDefault}}{{code}}{{/isDefault}}, "application/octet-stream", headers)); {{/dataType}} {{#dataType}} var entity = new HttpServerResponseEntity<>({{#isDefault}}rs.statusCode(){{/isDefault}}{{^isDefault}}{{code}}{{/isDefault}}, rs.content(), headers); diff --git a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerSecuritySchema.mustache b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerSecuritySchema.mustache index 8001ad991..33572a961 100644 --- a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerSecuritySchema.mustache +++ b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/javaServerSecuritySchema.mustache @@ -67,13 +67,13 @@ public interface ApiSecurity { var {{#lambda.camelcase}}{{name}}{{/lambda.camelcase}} = this.{{#lambda.camelcase}}{{name}}{{/lambda.camelcase}}.extract(request, {{#lambda.camelcase}}{{name}}{{/lambda.camelcase}}_token){{^isOAuth}};{{/isOAuth}}{{#isOAuth}}{{#vendorExtensions.hasScopes}} .handle((principal, sink) -> { {{#scopes}} - if (!principal.scopes().contains("{{scope}}")) throw HttpServerResponseException.of(403, "");{{/scopes}} + if (!principal.scopes().contains("{{scope}}")) throw new HttpServerResponseException(403, "");{{/scopes}} sink.next(principal); }){{/vendorExtensions.hasScopes}};{{/isOAuth}}{{/methods}}{{#methods}}{{#vendorExtensions.isFirst}} return {{#lambda.camelcase}}{{name}}{{/lambda.camelcase}}{{/vendorExtensions.isFirst}}{{/methods}}{{#methods}}{{^vendorExtensions.isFirst}} .switchIfEmpty(Mono.defer(() -> {{#lambda.camelcase}}{{name}}{{/lambda.camelcase}})){{/vendorExtensions.isFirst}}{{/methods}} - .switchIfEmpty(Mono.error(() -> HttpServerResponseException.of(403, ""))) + .switchIfEmpty(Mono.error(() -> new HttpServerResponseException(403, ""))) .doOnNext(principal -> Principal.set(context, principal)) .then(Mono.defer(() -> chain.apply(request))); }); diff --git a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinClientRequestMappers.mustache b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinClientRequestMappers.mustache index ac53ac945..f845033fb 100644 --- a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinClientRequestMappers.mustache +++ b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinClientRequestMappers.mustache @@ -3,7 +3,7 @@ package {{package}} import ru.tinkoff.kora.http.client.common.form.UrlEncodedWriter import ru.tinkoff.kora.http.client.common.form.MultipartWriter import ru.tinkoff.kora.http.client.common.request.HttpClientRequestMapper -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder +import ru.tinkoff.kora.http.client.common.request.HttpClientRequest import reactor.core.publisher.Mono @ru.tinkoff.kora.common.annotation.Generated("openapi generator kora client"){{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}} @@ -15,7 +15,7 @@ interface {{classname}}ClientRequestMappers { class {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}FormParamRequestMapper{{#vendorExtensions.requiresFormParamMappers}}({{#vendorExtensions.formParamMappers}} private val {{paramName}}Converter: ru.tinkoff.kora.http.client.common.writer.StringParameterConverter<{{paramType}}>, {{/vendorExtensions.formParamMappers}} ){{/vendorExtensions.requiresFormParamMappers}}: HttpClientRequestMapper<{{classname}}.{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}FormParam> { - override fun apply(request: HttpClientRequestMapper.Request<{{classname}}.{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}FormParam>): HttpClientRequestBuilder { + override fun apply(request: HttpClientRequestMapper.Request<{{classname}}.{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}FormParam>): HttpClientRequest.Builder { {{#vendorExtensions.urlEncodedForm}} val b = UrlEncodedWriter(){{#formParams}} request.parameter().{{paramName}}?.let { {{#vendorExtensions.requiresMapper}} diff --git a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerRequestMappers.mustache b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerRequestMappers.mustache index f7d60cef2..827384b7f 100644 --- a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerRequestMappers.mustache +++ b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerRequestMappers.mustache @@ -3,6 +3,7 @@ package {{package}} import ru.tinkoff.kora.http.server.common.form.MultipartReader import ru.tinkoff.kora.http.server.common.handler.HttpServerRequestMapper import ru.tinkoff.kora.http.server.common.HttpServerRequest +import ru.tinkoff.kora.http.server.common.HttpServerResponseException import reactor.core.publisher.Mono @ru.tinkoff.kora.common.annotation.Generated("openapi generator kora client"){{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}} @@ -28,7 +29,7 @@ interface {{classname}}ServerRequestMappers { val {{paramName}} = if ({{paramName}}Part == null || {{paramName}}Part.values().isEmpty()) null else {{paramName}}Part.values().first() {{/vendorExtensions.requiresMapper}}{{#required}} if ({{paramName}} == null) { - sink.error(ru.tinkoff.kora.http.server.common.HttpServerResponseException.of(400, "Form field '{{baseName}}' is required")) + sink.error(HttpServerResponseException(400, "Form field '{{baseName}}' is required")) return@handle } {{/required}}{{/isArray}}{{/formParams}} @@ -59,7 +60,7 @@ interface {{classname}}ServerRequestMappers { .handle { state, sink -> {{#formParams}}{{#required}} if (state.{{paramName}} == null) { - sink.error(ru.tinkoff.kora.http.server.common.HttpServerResponseException.of(400, "Form field '{{baseName}}' is required")) + sink.error(HttpServerResponseException(400, "Form field '{{baseName}}' is required")) return@handle } {{/required}}{{/formParams}} diff --git a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerResponseMappers.mustache b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerResponseMappers.mustache index 6957d88b6..982214055 100644 --- a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerResponseMappers.mustache +++ b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerResponseMappers.mustache @@ -4,7 +4,6 @@ import ru.tinkoff.kora.http.server.common.handler.HttpServerResponseMapper import ru.tinkoff.kora.http.server.common.handler.HttpServerResponseEntityMapper import ru.tinkoff.kora.http.server.common.HttpServerResponse import ru.tinkoff.kora.http.server.common.HttpServerResponseEntity -import ru.tinkoff.kora.http.server.common.SimpleHttpServerResponse import ru.tinkoff.kora.http.common.HttpHeaders import reactor.core.publisher.Mono import {{package}}.{{classname}}Responses.* @@ -43,7 +42,7 @@ interface {{classname}}ServerResponseMappers { {{/headers}} ) {{^dataType}} - return Mono.just(SimpleHttpServerResponse({{#isDefault}}rs.statusCode{{/isDefault}}{{^isDefault}}{{code}}{{/isDefault}}, "application/octet-stream", headers, null)) + return Mono.just(HttpServerResponse.of({{#isDefault}}rs.statusCode{{/isDefault}}{{^isDefault}}{{code}}{{/isDefault}}, "application/octet-stream", headers)) {{/dataType}} {{#dataType}} val entity = HttpServerResponseEntity({{#isDefault}}rs.statusCode{{/isDefault}}{{^isDefault}}{{code}}{{/isDefault}}, rs.content, headers) diff --git a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerSecuritySchema.mustache b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerSecuritySchema.mustache index db2e404d8..27ce1eabf 100644 --- a/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerSecuritySchema.mustache +++ b/openapi/openapi-generator/src/main/resources/openapi/templates/kora/kotlinServerSecuritySchema.mustache @@ -60,13 +60,13 @@ public interface ApiSecurity { val {{#lambda.camelcase}}{{name}}{{/lambda.camelcase}} = this.{{#lambda.camelcase}}{{name}}{{/lambda.camelcase}}.extract(request, {{#lambda.camelcase}}{{name}}{{/lambda.camelcase}}_token){{^isOAuth}}{{/isOAuth}}{{#isOAuth}}{{#vendorExtensions.hasScopes}} .handle { principal, sink -> {{#scopes}} - if (!principal.scopes().contains("{{scope}}")) throw HttpServerResponseException.of(403, ""){{/scopes}} + if (!principal.scopes().contains("{{scope}}")) throw HttpServerResponseException(403, ""){{/scopes}} sink.next(principal) }{{/vendorExtensions.hasScopes}}{{/isOAuth}}{{/methods}}{{#methods}}{{#vendorExtensions.isFirst}} {{#lambda.camelcase}}{{name}}{{/lambda.camelcase}}{{/vendorExtensions.isFirst}}{{/methods}}{{#methods}}{{^vendorExtensions.isFirst}} .switchIfEmpty(Mono.defer { {{#lambda.camelcase}}{{name}}{{/lambda.camelcase}} }){{/vendorExtensions.isFirst}}{{/methods}} - .switchIfEmpty(Mono.error { HttpServerResponseException.of(403, "") }) + .switchIfEmpty(Mono.error { HttpServerResponseException(403, "") }) .doOnNext { principal -> Principal.set(context, principal) } .then(Mono.defer { chain.apply(request) }); } diff --git a/opentelemetry/opentelemetry-module/src/main/java/ru/tinkoff/kora/opentelemetry/module/http/client/OpentelemetryHttpClientTracer.java b/opentelemetry/opentelemetry-module/src/main/java/ru/tinkoff/kora/opentelemetry/module/http/client/OpentelemetryHttpClientTracer.java index 2c73a0c27..525c88937 100644 --- a/opentelemetry/opentelemetry-module/src/main/java/ru/tinkoff/kora/opentelemetry/module/http/client/OpentelemetryHttpClientTracer.java +++ b/opentelemetry/opentelemetry-module/src/main/java/ru/tinkoff/kora/opentelemetry/module/http/client/OpentelemetryHttpClientTracer.java @@ -8,7 +8,6 @@ import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; import ru.tinkoff.kora.common.Context; import ru.tinkoff.kora.http.client.common.request.HttpClientRequest; -import ru.tinkoff.kora.http.client.common.request.HttpClientRequestBuilder; import ru.tinkoff.kora.http.client.common.telemetry.HttpClientTracer; import ru.tinkoff.kora.opentelemetry.common.OpentelemetryContext; @@ -30,7 +29,7 @@ public CreateSpanResult createSpan(Context ctx, HttpClientRequest request) { .setSpanKind(SpanKind.CLIENT) .setParent(otctx.getContext()); builder.setAttribute(SemanticAttributes.HTTP_METHOD, request.method()); - builder.setAttribute(SemanticAttributes.HTTP_URL, request.resolvedUri()); + builder.setAttribute(SemanticAttributes.HTTP_URL, request.uriResolved()); var span = builder.startSpan(); OpentelemetryContext.set(ctx, otctx.add(span)); var processedRequest = inject(request.toBuilder(), span).build(); @@ -44,11 +43,12 @@ public CreateSpanResult createSpan(Context ctx, HttpClientRequest request) { } - public static HttpClientRequestBuilder inject(HttpClientRequestBuilder builder, @Nullable Span span) { + public static HttpClientRequest.Builder inject(HttpClientRequest.Builder builder, @Nullable Span span) { if (span == null) { return builder; } - W3CTraceContextPropagator.getInstance().inject(span.storeInContext(root()), builder, HttpClientRequestBuilder::header); + + W3CTraceContextPropagator.getInstance().inject(span.storeInContext(root()), builder, HttpClientRequest.Builder::header); return builder; } } diff --git a/validation/validation-module/src/main/java/ru/tinkoff/kora/validation/module/http/server/ValidationHttpServerInterceptor.java b/validation/validation-module/src/main/java/ru/tinkoff/kora/validation/module/http/server/ValidationHttpServerInterceptor.java index 986d2ba80..f04cacd26 100644 --- a/validation/validation-module/src/main/java/ru/tinkoff/kora/validation/module/http/server/ValidationHttpServerInterceptor.java +++ b/validation/validation-module/src/main/java/ru/tinkoff/kora/validation/module/http/server/ValidationHttpServerInterceptor.java @@ -37,6 +37,6 @@ private HttpServerResponse toResponse(HttpServerRequest request, ViolationExcept } } var message = exception.getMessage(); - return HttpServerResponseException.of(400, message); + return new HttpServerResponseException(400, message); } }