Sub-scope 04 (httpclient) restclient/** + webclient/** — manifest and probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T05:31:16+00:00

=== OWNED FILES ===
3317df91c6c64d62d0c1b0ac6634f8d2209a5503 main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingAttemptExecutor.java 269
5e5cb1380bdb79df615d583ab3e644fb000e9c57 main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingClientRuntime.java 132
06d394b8d3116511a7407980e57276e067cb87db main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingExecutionSupport.java 86
d4e4d3188f8fb13ee72a849e101303bfbde4a83e main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingOperationContext.java 41
8b0b348f9ff5f5577a913f934d2ced7f163cd6a5 main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingRedirectCoordinator.java 114
f0c6a30368119d4fb939f8850b23603f5d945759 main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingResponseMapper.java 78
9589a9f172c77738aaab1a689e812d3185ccc5bf main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingStreamingGateway.java 169
90e67085b700cfdfe637b2c8643a8b2054035a6e main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BoundedErrorBody.java 54
bad7193da46442324dcc5bc325870c2b3ff3f156 main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/CountingBoundedInputStream.java 50
6c72a175d065e5ae317c6992120a166661bae83b main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/DefaultBlockingStreamingResponse.java 67
17e787852f7b4762ff280b68bc510a5f986be3ee main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/DefaultGenericHttpGateway.java 304
473cf6085dfdd827822e938915f5bf43321f36ef main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/GenericHttpGateway.java 26
35f9f94dff3fdcc2f24cf29f99cfbca04466e352 main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/RemoteProblemDecoder.java 88
e88961bc440727c875270af1e8b6e559db0a53ec main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/ResponseSizeLimiter.java 62
ce9cc87429faccd4effe19ada9b017187485abd8 main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/RestClientBodyWriter.java 76
de93a1bec3b600f203894ff5d9641e041a9db54c main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/RestClientResponseReader.java 206
42518b6727c4dfc884f9bec5eb29752b8272b132 main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/RestClientRuntimeFactory.java 144
e4305dce6f69236a4465bafa9328e53a5f1cf3ce main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/StableBlockingExceptionMapper.java 40
fdd77212d4830a37192a6550834673d31d45579b main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/StatusHandlingPolicy.java 12
f7e354c4783a8d1cfa91589c7c08ad51eb3e245f main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/BoundedDataBufferFlux.java 39
158094336c522fda6ee08642b47b512cdd32536f main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/DefaultReactiveHttpGateway.java 330
5b9588c32fd9099c168b058f7a23e40878b1838c main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/DefaultReactiveSseGateway.java 183
33ff26665dca2064611531748084a305826b13fe main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/FirstByteDeliveryGuard.java 24
f4ca87199cfb463223d496f950d2b2e87a952ed2 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/MultipartReplayability.java 37
36f2d940765828913d1adbf5eee49ecf82d1a927 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveAttemptExecutor.java 184
b193badebdecca660699403d87b7847bb2e802d5 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveBodySource.java 38
ad4f8e67414ef821f8d49822bfb4b7dca138b1c2 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveClientRuntime.java 111
dbadac6d34f55b4b5795988e83448e1cf3732d51 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveHttpGateway.java 18
f250530402a4b0c849e8d7cbbc117faca481c030 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveSseGateway.java 13
134d3c2baa033be52419c164b4792f3501c92a30 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveStreamingGateway.java 107
e5f5779004a000c5bb830f7ed512dcf5f77ca342 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/SseIdleTimeoutException.java 22
f82ef76d8b89077ee50820179ab93d287ef9cae4 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/SseOperation.java 49
90f65c72d6580e715f7bd72e49d6d236b81ac8f8 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/SseReconnectPolicy.java 28
ece8e712de4c2dd97ba98a9a182e972a7d8dc24f main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/WebClientBodyWriter.java 98
225bd9843d62843034dcab53ac51fa2497f5ea45 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/WebClientResponseMapper.java 54
9c2e47f592ae3462e72e7b4a803f1b37bba3df71 main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/WebClientRuntimeFactory.java 123
b1990e1b941ed8157e1ae3964c7c5e3d4323511f test/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingRedirectCoordinatorTest.java 175
8acd49e49ff84f29f2c539b875d7b78c3c97e65b test/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingResponseMapperTest.java 63
0f841cd744743ac058c99ca2c841593d4ecc01fa test/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingStreamingLifecycleTest.java 145
a88e2e1c08e8e037a4124d30db718bdc82c0de57 test/java/dev/caskeleton/adapter/outbound/httpclient/restclient/DefaultGenericHttpGatewayTest.java 200
b308025e96311ce3b8d80359ff3431f9b28bff87 test/java/dev/caskeleton/adapter/outbound/httpclient/restclient/ResponseSizeLimiterTest.java 37
d4241ae02359c7306800a410da417a746593ad8e test/java/dev/caskeleton/adapter/outbound/httpclient/webclient/BlockHoundEventLoopTest.java 110
fa0419d599ca04b74b29762ceefe0724de505074 test/java/dev/caskeleton/adapter/outbound/httpclient/webclient/DefaultReactiveHttpGatewayTest.java 95
fb8fe20deeee336dd793926f2ab3dd8cf7b343ff test/java/dev/caskeleton/adapter/outbound/httpclient/webclient/FirstByteRetryBoundaryTest.java 64
6541bc4bffaa675074e3886c12fa6e1f3b48384d test/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveSseGatewayTest.java 101
eb13dd777f8beedb48057001c2fe7c6ebd4194b4 test/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveStreamingLifecycleTest.java 121

main: 36  test: 10
=== 8.1 BoundedDataBufferFlux의 두 연산자가 실제로 하는 일 ===
$ grep -n 'doOnCancel\|onErrorResume\|doOnDiscard\|doOnNext' adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/BoundedDataBufferFlux.java
25:        .doOnNext(
30:        .doOnDiscard(DataBuffer.class, DataBufferUtils::release)
31:        .doOnCancel(() -> {})
32:        .onErrorResume(
35:              // discarded through doOnDiscard above.
exit=0

$ git grep -rn 'BoundedDataBufferFlux' -- 'adapter/outbound/httpclient/src' | grep -v 'BoundedDataBufferFlux.java'
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveStreamingGateway.java:102:              return BoundedDataBufferFlux.bound(
exit=0

=== 8.2 ResponseSizeLimiter의 UNBOUND 메타데이터 생성자 사용처 ===
$ grep -n 'UNBOUND\|public ResponseSizeLimiter' adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/ResponseSizeLimiter.java
15:  private static final HttpFailureMetadata UNBOUND =
25:  public ResponseSizeLimiter(long maxWireBytes, long maxDecodedBytes) {
26:    this(maxWireBytes, maxDecodedBytes, UNBOUND);
29:  public ResponseSizeLimiter(
exit=0

$ git grep -rn 'new ResponseSizeLimiter(' -- 'adapter/outbound/httpclient/src'
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingAttemptExecutor.java:52:        new ResponseSizeLimiter(
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingStreamingGateway.java:60:          new ResponseSizeLimiter(
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/webclient/ReactiveStreamingGateway.java:69:        new ResponseSizeLimiter(
adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingResponseMapperTest.java:59:    ResponseSizeLimiter limiter = new ResponseSizeLimiter(10, 20);
adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/restclient/ResponseSizeLimiterTest.java:16:    ResponseSizeLimiter limiter = new ResponseSizeLimiter(10, 100);
adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/restclient/ResponseSizeLimiterTest.java:21:    ResponseSizeLimiter decodedLimiter = new ResponseSizeLimiter(100, 10);
adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/restclient/ResponseSizeLimiterTest.java:29:    ResponseSizeLimiter limiter = new ResponseSizeLimiter(4, 1024);
exit=0

=== 8.3 리다이렉트 hop 상한이 실제로 강제되는가 ===
$ grep -n 'for (int hop' -A 3 adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/restclient/BlockingRedirectCoordinator.java
77:    for (int hop = 0; isRedirect(response.status()); hop++) {
78-      Optional<String> location = response.firstHeader("Location");
79-      if (location.isEmpty()) {
80-        return response;
exit=0

$ git grep -n 'maxHops' -- 'adapter/outbound/httpclient/src/main'
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/profile/ClientProfileValidator.java:71:    if (redirect.maxHops() == 0) {
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/profile/RedirectSettings.java:7:public record RedirectSettings(boolean enabled, int maxHops, boolean allowCrossOrigin) {
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/profile/RedirectSettings.java:12:    if (maxHops < 0) {
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/security/RedirectEvaluator.java:16:    if (context.hop() >= context.policy().maxHops()) {
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/security/RedirectPolicy.java:18:    boolean enabled, int maxHops, boolean allowCrossOrigin, boolean callerManaged) {
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/security/RedirectPolicy.java:23:  public RedirectPolicy(boolean enabled, int maxHops, boolean allowCrossOrigin) {
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/security/RedirectPolicy.java:24:    this(enabled, maxHops, allowCrossOrigin, false);
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/security/RedirectPolicy.java:38:        settings.enabled(), settings.maxHops(), settings.allowCrossOrigin(), false);
exit=0

=== 8.4 게이트웨이 test ===
$ git ls-files 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/restclient' 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/webclient' | xargs -n1 basename
BlockingRedirectCoordinatorTest.java
BlockingResponseMapperTest.java
BlockingStreamingLifecycleTest.java
DefaultGenericHttpGatewayTest.java
ResponseSizeLimiterTest.java
BlockHoundEventLoopTest.java
DefaultReactiveHttpGatewayTest.java
FirstByteRetryBoundaryTest.java
ReactiveSseGatewayTest.java
ReactiveStreamingLifecycleTest.java
exit=0

$ git grep -h '  void [a-z]' -- 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/restclient' 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/webclient' | sed 's/^ *//'
void refusesRedirectsWhenTheProfileDisablesThem() throws Exception {
void followsABoundedSameOriginHopWhenEnabled() throws Exception {
void stopsAtTheConfiguredHopLimit() throws Exception {
void aHopIsRejectedWhenTheProfileAllowlistExcludesIt() throws Exception {
void aSeeOtherHopDropsTheRequestBody() throws Exception {
void mapsProblemJsonWithoutTrustingBodyStatus() {
void dropsExtensionsThatAreNotAllowlisted() {
void treatsANonProblemContentTypeAsAnEmptyProblem() {
void survivesAnUnparseableProblemDocument() {
void abortsWhenDecodedBytesExceedLimit() {
void closeReturnsConnectionAfterPartialRead() throws Exception {
void validatesStatusBeforeDeliveringAnyBodyByte() throws Exception {
void enforcesTheWireBudgetWhileStreaming() throws Exception {
void closeIsIdempotent() {
void expandsRelativeTemplateAndReturnsTypedResult() throws Exception {
void worksIdenticallyOnTheJdkTransport() throws Exception {
void rejectsAnAbsoluteUriFromTheCaller() throws Exception {
void mapsProblemResponsesToStableExceptions() throws Exception {
void canReturnANonSuccessStatusAsAResultWhenThePolicySaysSo() throws Exception {
void throwsRemoteErrorWithoutAProblemDocument() throws Exception {
void recordsSeparateLogicalAndAttemptMetrics() throws Exception {
void refusesAnUnregisteredProfile() throws Exception {
void enforcesTheProfileResponseSizeLimit() throws Exception {
void boundsWireAndDecodedBytesIndependently() {
void failsWhileReadingRatherThanAfterBuffering() throws IOException {
void theDetectorItselfCatchesABlockingCallOnANonBlockingScheduler() {
void theReactiveGatewayCompletesWithoutBlockingAnEventLoop() throws Exception {
void theReactiveRetryBackoffDoesNotBlockAnEventLoop() throws Exception {
void returnsTypedResultWithoutBlocking() throws Exception {
void appliesTheSameTargetPolicyAsTheBlockingGateway() throws Exception {
void producesTheSameStableFailureTypeForANonSuccessStatus() throws Exception {
void releasesTheRuntimeLeaseAfterCompletion() throws Exception {
void theGuardLatchesExactlyOnce() {
void doesNotRetryAfterFirstBufferWasDelivered() {
void aPartialResponseNotYetDeliveredMayStillBeRetriedForASafeOperation() {
void multipartReplayabilityFollowsTheWeakestPart() {
void decodesEventsFromTheStream() throws Exception {
void closesSilentStreamAtStreamingIdleTimeout() throws Exception {
void setupAndStreamingBudgetsAreSeparateSettings() {
void lastEventIdIsOptInAndOffByDefault() {
void cancellationReleasesTheConnectionForTheNextCall() throws Exception {
void statusIsValidatedBeforeAnyBufferIsEmitted() throws Exception {
void marksTheFirstByteBoundaryWhileStreaming() throws Exception {
exit=0

