11package ru .tinkoff .kora .http .server .common ;
22
3+ import static java .time .Instant .now ;
4+ import static org .assertj .core .api .Assertions .assertThat ;
5+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
6+ import static org .junit .jupiter .api .Assertions .fail ;
7+ import static org .mockito .Mockito .never ;
8+ import static org .mockito .Mockito .timeout ;
9+ import static org .mockito .Mockito .verify ;
10+ import static org .mockito .Mockito .when ;
11+ import static ru .tinkoff .kora .http .common .HttpMethod .GET ;
12+ import static ru .tinkoff .kora .http .common .HttpMethod .POST ;
13+
314import io .opentelemetry .api .trace .Span ;
15+ import java .io .IOException ;
16+ import java .io .OutputStream ;
17+ import java .nio .ByteBuffer ;
18+ import java .nio .charset .StandardCharsets ;
19+ import java .time .Duration ;
20+ import java .util .ArrayList ;
21+ import java .util .List ;
22+ import java .util .Optional ;
23+ import java .util .concurrent .CompletableFuture ;
24+ import java .util .concurrent .ConcurrentLinkedDeque ;
25+ import java .util .concurrent .ExecutionException ;
26+ import java .util .concurrent .Executors ;
27+ import java .util .concurrent .ForkJoinPool ;
28+ import java .util .concurrent .ThreadLocalRandom ;
29+ import java .util .concurrent .TimeUnit ;
30+ import java .util .function .Supplier ;
431import okhttp3 .ConnectionPool ;
532import okhttp3 .OkHttpClient ;
633import okhttp3 .Request ;
734import okhttp3 .RequestBody ;
835import okio .BufferedSink ;
936import org .jetbrains .annotations .NotNull ;
1037import org .jspecify .annotations .Nullable ;
11- import org .junit .jupiter .api .*;
38+ import org .junit .jupiter .api .AfterEach ;
39+ import org .junit .jupiter .api .Assertions ;
40+ import org .junit .jupiter .api .Nested ;
41+ import org .junit .jupiter .api .Test ;
42+ import org .junit .jupiter .api .TestInstance ;
1243import org .mockito .AdditionalAnswers ;
1344import org .mockito .ArgumentMatchers ;
1445import org .mockito .Mockito ;
3263import ru .tinkoff .kora .http .server .common .privateapi .MetricsHandler ;
3364import ru .tinkoff .kora .http .server .common .privateapi .ReadinessHandler ;
3465import ru .tinkoff .kora .http .server .common .router .HttpServerHandler ;
35- import ru .tinkoff .kora .http .server .common .telemetry .*;
66+ import ru .tinkoff .kora .http .server .common .telemetry .$HttpServerTelemetryConfig_ConfigValueExtractor ;
67+ import ru .tinkoff .kora .http .server .common .telemetry .$HttpServerTelemetryConfig_HttpServerLoggingConfig_ConfigValueExtractor ;
68+ import ru .tinkoff .kora .http .server .common .telemetry .$HttpServerTelemetryConfig_HttpServerMetricsConfig_ConfigValueExtractor ;
69+ import ru .tinkoff .kora .http .server .common .telemetry .$HttpServerTelemetryConfig_HttpServerTracingConfig_ConfigValueExtractor ;
70+ import ru .tinkoff .kora .http .server .common .telemetry .HttpServerObservation ;
71+ import ru .tinkoff .kora .http .server .common .telemetry .HttpServerTelemetry ;
72+ import ru .tinkoff .kora .http .server .common .telemetry .NoopHttpServerTelemetry ;
3673import ru .tinkoff .kora .telemetry .common .MetricsScraper ;
3774
38- import java .io .IOException ;
39- import java .io .OutputStream ;
40- import java .nio .ByteBuffer ;
41- import java .nio .charset .StandardCharsets ;
42- import java .time .Duration ;
43- import java .util .ArrayList ;
44- import java .util .List ;
45- import java .util .Optional ;
46- import java .util .concurrent .*;
47- import java .util .function .Supplier ;
48-
49- import static java .time .Instant .now ;
50- import static org .assertj .core .api .Assertions .assertThat ;
51- import static org .assertj .core .api .Assertions .assertThatThrownBy ;
52- import static org .junit .jupiter .api .Assertions .fail ;
53- import static org .mockito .Mockito .*;
54- import static ru .tinkoff .kora .http .common .HttpMethod .GET ;
55- import static ru .tinkoff .kora .http .common .HttpMethod .POST ;
56-
5775@ TestInstance (TestInstance .Lifecycle .PER_METHOD )
5876public abstract class HttpServerTestKit {
5977 protected static MetricsScraper registry = Mockito .mock (MetricsScraper .class );
@@ -74,6 +92,7 @@ public abstract class HttpServerTestKit {
7492
7593 private volatile HttpServer httpServer = null ;
7694 private volatile HttpServer privateHttpServer = null ;
95+ private volatile HttpServer internalHttpServer = null ;
7796
7897 protected final OkHttpClient client = new OkHttpClient .Builder ()
7998 .connectionPool (new ConnectionPool (0 , 1 , TimeUnit .MICROSECONDS ))
@@ -190,6 +209,76 @@ void testReadinessFailureOnUninitializedProbe() throws IOException {
190209 }
191210
192211
212+ @ Nested
213+ public class InternalApiTest {
214+ @ Test
215+ void testInternalApiHelloWorld () throws IOException {
216+ var httpResponse = HttpServerResponse .of (200 , HttpBody .plaintext ("internal hello" ));
217+ var handler = handler (GET , "/internal" , (_ ) -> httpResponse );
218+ startInternalHttpServer (handler );
219+
220+ var request = internalApiRequest ("/internal" )
221+ .get ()
222+ .build ();
223+
224+ try (var response = client .newCall (request ).execute ()) {
225+ assertThat (response .code ()).isEqualTo (200 );
226+ assertThat (response .body ().string ()).isEqualTo ("internal hello" );
227+ }
228+ }
229+
230+ @ Test
231+ void testInternalApiUnknownPath () throws IOException {
232+ var handler = handler (GET , "/internal" , (_ ) -> HttpServerResponse .of (200 ));
233+ startInternalHttpServer (handler );
234+
235+ var request = internalApiRequest ("/unknown" )
236+ .get ()
237+ .build ();
238+
239+ try (var response = client .newCall (request ).execute ()) {
240+ assertThat (response .code ()).isEqualTo (404 );
241+ }
242+ }
243+
244+ @ Test
245+ void testInternalApiWithInterceptor () throws IOException {
246+ var httpResponse = HttpServerResponse .of (200 , HttpBody .plaintext ("internal hello" ));
247+ var handler = handler (GET , "/internal" , (_ ) -> httpResponse );
248+ var interceptor = new HttpServerInterceptor () {
249+ @ Override
250+ public HttpServerResponse intercept (HttpServerRequest request , InterceptChain chain ) throws Exception {
251+ var header = request .headers ().getFirst ("x-internal-block" );
252+ if (header != null ) {
253+ request .body ().close ();
254+ return HttpServerResponse .of (403 , HttpBody .plaintext ("blocked" ));
255+ }
256+ return chain .process (request );
257+ }
258+ };
259+ startInternalHttpServer (List .of (interceptor ), handler );
260+
261+ var request = internalApiRequest ("/internal" )
262+ .get ()
263+ .build ();
264+
265+ try (var response = client .newCall (request ).execute ()) {
266+ assertThat (response .code ()).isEqualTo (200 );
267+ assertThat (response .body ().string ()).isEqualTo ("internal hello" );
268+ }
269+
270+ var blockedRequest = internalApiRequest ("/internal" )
271+ .header ("x-internal-block" , "true" )
272+ .get ()
273+ .build ();
274+
275+ try (var response = client .newCall (blockedRequest ).execute ()) {
276+ assertThat (response .code ()).isEqualTo (403 );
277+ assertThat (response .body ().string ()).isEqualTo ("blocked" );
278+ }
279+ }
280+ }
281+
193282 @ Nested
194283 public class PublicApiTest {
195284 @ Test
@@ -990,6 +1079,34 @@ protected void startPrivateHttpServer() {
9901079 }
9911080 }
9921081
1082+ protected void startInternalHttpServer (HttpServerRequestHandler ... handlers ) {
1083+ startInternalHttpServer (List .of (), handlers );
1084+ }
1085+
1086+ protected void startInternalHttpServer (List <HttpServerInterceptor > interceptors , HttpServerRequestHandler ... handlers ) {
1087+ var config = new HttpServerConfig_Impl (
1088+ 0 ,
1089+ false ,
1090+ Duration .ofSeconds (1 ),
1091+ Duration .ofSeconds (1 ),
1092+ false ,
1093+ Duration .ofMillis (1 ),
1094+ new $HttpServerTelemetryConfig_ConfigValueExtractor .HttpServerTelemetryConfig_Impl (
1095+ new $HttpServerTelemetryConfig_HttpServerLoggingConfig_ConfigValueExtractor .HttpServerLoggingConfig_Defaults (),
1096+ new $HttpServerTelemetryConfig_HttpServerMetricsConfig_ConfigValueExtractor .HttpServerMetricsConfig_Defaults (),
1097+ new $HttpServerTelemetryConfig_HttpServerTracingConfig_ConfigValueExtractor .HttpServerTracingConfig_Defaults ()
1098+ ),
1099+ Size .of (1 , Size .Type .GiB )
1100+ );
1101+ var internalApiHandler = new HttpServerHandler (List .of (handlers ), interceptors , config );
1102+ this .internalHttpServer = this .httpServer (valueOf (config ), internalApiHandler , this .telemetry );
1103+ try {
1104+ this .internalHttpServer .init ();
1105+ } catch (Exception e ) {
1106+ throw new RuntimeException (e );
1107+ }
1108+ }
1109+
9931110 @ AfterEach
9941111 void tearDown () throws Exception {
9951112 if (this .httpServer != null ) {
@@ -1000,6 +1117,10 @@ void tearDown() throws Exception {
10001117 this .privateHttpServer .release ();
10011118 this .privateHttpServer = null ;
10021119 }
1120+ if (this .internalHttpServer != null ) {
1121+ this .internalHttpServer .release ();
1122+ this .internalHttpServer = null ;
1123+ }
10031124 this .readinessProbePromise .setValue (readinessProbe );
10041125 this .livenessProbePromise .setValue (livenessProbe );
10051126 }
@@ -1021,6 +1142,10 @@ protected Request.Builder privateApiRequest(String path) {
10211142 return request (this .privateHttpServer .port (), path );
10221143 }
10231144
1145+ protected Request .Builder internalApiRequest (String path ) {
1146+ return request (this .internalHttpServer .port (), path );
1147+ }
1148+
10241149 protected Request .Builder request (String path ) {
10251150 return request (this .httpServer .port (), path );
10261151 }
0 commit comments