# 프로파일이 선언하는 세 상한 * @param maxDepth deepest accepted nesting * @param maxArrayElements most elements accepted in one array * @param maxStringBytes longest accepted string boolean rejectScalarCoercion, int maxDepth, int maxArrayElements, int maxStringBytes) { public static WebJsonProfile strict() { return new WebJsonProfile(true, true, true, true, true, 64, 100_000, 1_048_576); } maxArrayElements() 를 부르는 자리 : (0) # 같은 이름의 필드가 예산 타입에도 있다 22: * @param maxArrayElements most elements accepted in one JSON array 33: int maxArrayElements, 51: private static final int ABSOLUTE_ARRAY_ELEMENTS_MAX = 100_000; 59: requirePositive(maxArrayElements, "maxArrayElements"); 85: requireAtMost(maxArrayElements, ABSOLUTE_ARRAY_ELEMENTS_MAX, "maxArrayElements"); 110: ABSOLUTE_ARRAY_ELEMENTS_MAX, 123: && maxArrayElements <= other.maxArrayElements 프로덕션이 등록하는 값과 그 필드 순서 : * @param maxExecutionTime longest this operation may run before its deadline expires * @param maxResponseBytes largest response this operation may produce */ public record WebRequestBudget( int maxUriBytes, int maxHeaderBytes, int maxQueryParameters, long maxBodyBytes, int maxJsonDepth, int maxArrayElements, int maxMultipartParts, public static WebRequestBudget standard() { return new WebRequestBudget( 2048, 8192, 64, 256L * 1024, 32, 1_000, 16, Duration.ofSeconds(10), 4L * 1024 * 1024); } 절대 상한을 쓰는 술어를 프로덕션에서 부르는 자리 : test · WebRequestBudgetTest.java:43 assertThat(WebRequestBudget.standard().withinPlatformMaximum()).isTrue(); test · WebRequestBudgetTest.java:58 () -> catalog.registerOverride(new WebBudgetProfileName("orders.bulk"), base, tighter)) test · WebRequestBudgetTest.java:66 catalog.registerOverride( 그 예산 목록은 프로덕션 자동설정이 만들고, 등록하는 예산은 하나다 : WebMvcPlatformAutoConfiguration.java:67 WebBudgetCatalog catalog = new WebBudgetCatalog(); WebMvcPlatformAutoConfiguration.java:68 catalog.register(WebBudgetProfileName.standard(), WebRequestBudget.standard()); WebFluxPlatformAutoConfiguration.java:85 WebBudgetCatalog catalog = new WebBudgetCatalog(); WebFluxPlatformAutoConfiguration.java:86 catalog.register(WebBudgetProfileName.standard(), WebRequestBudget.standard()); WebRequestBudget 의 공개 팩토리 : 1 # 그 예산을 강제하는 필터가 실제로 읽는 필드 budget.maxBodyBytes() budget.maxHeaderBytes() budget.maxQueryParameters() budget.maxResponseBytes() budget.maxUriBytes() 반응형 필터가 자기 파일에서 읽는 필드 : budget.maxBodyBytes() budget.maxHeaderBytes() budget.maxQueryParameters() budget.maxUriBytes() 나머지 둘은 이 감싼 교환에 넘겨 잰다 : 64: .filter(new BoundedServerWebExchange(exchange, budget)) budget.maxBodyBytes() budget.maxResponseBytes() 두 필터를 등록하는 자리 : webfluxContractTest · ReactiveBudgetFixtureApplication.java testkit · BudgetFixtureApplication.java # 유계 팩토리가 파서에 거는 것과 그 이유 /** * Builds the reader whose limits are enforced before a document is materialised. * *

The constraints go on the {@code JsonFactory} rather than being checked after parsing, and * that placement is the whole point. A depth limit applied to a parsed tree has already paid for * the tree; a nesting bomb is cheap to send and expensive to hold, so the only limit that helps is * one the streaming parser refuses to exceed. JsonFactoryBuilder builder = JsonFactory.builder() .streamReadConstraints( StreamReadConstraints.builder() .maxNestingDepth(profile.maxDepth()) .maxStringLength(profile.maxStringBytes()) .build()); if (profile.rejectDuplicateKeys()) { builder.enable(StreamReadFeature.STRICT_DUPLICATE_DETECTION); } return builder.build(); # 파서가 실제로 제공하는 상한 전부 jackson-core-3.1.5.jar maxNestingDepth(int) maxDocumentLength(long) maxTokenCount(long) maxNumberLength(int) maxStringLength(int) maxNameLength(int) 유계 팩토리를 부르는 자리와 그것을 부르는 자동설정 : WebMvcPlatformAutoConfiguration.java:135 return WebObjectMapperFactory.jsonMapper( WebFluxPlatformAutoConfiguration.java:129 return WebObjectMapperFactory.jsonMapper(WebJsonProfile.strict()); WebObjectMapperFactory.java:59 JsonMapper.builder(BoundedJsonFactory.create(profile)) 그중 이 저장소가 이미 쓰는 것 : JacksonMessageCodec.java:213 .maxDocumentLength(maxBytes) StrictWebSocketJsonCodec.java:64 .maxDocumentLength(budget.maxMessageBytes()) WebSocketCborCodec.java:76 .maxDocumentLength(binary.maxMessageBytes()) WebCborMapperFactory.java:55 .maxDocumentLength(budget.maxBodyBytes()) WebXmlMapperFactory.java:74 .maxDocumentLength(budget.maxBodyBytes()) LocalJsonSchemaRegistry.java:623 .maxDocumentLength(limits.maximumEnvelopeBytes()) 같은 어댑터의 두 자리가 받는 예산 타입과 그 출하값 : WebCborMapperFactory.java:41 public static ObjectMapper create(CodecBudget budget) { WebXmlMapperFactory.java:39 public static ObjectMapper create(CodecBudget budget) { WebXmlMapperFactory.java:56 public static ObjectMapper create(CodecBudget budget, XMLInputFactory input) { 21: int maxBodyBytes, 43: public static CodecBudget conventional(WebRepresentation representation) { 여섯 자리를 실제로 만드는 곳 : main · JacksonMessageCodec.java:66 public static JacksonMessageCodec of(Map> registry) { main · JacksonMessageCodec.java:77 public static JacksonMessageCodec of(Map> registry, int maxBytes) { main · MessagingCoreAutoConfiguration.java:364 dev.caskeleton.messaging.schema.json.JacksonMessageCodec.of( test · BinaryCodecRoundTripTest.java:118 new WebSocketCborCodec( test · BinaryCodecRoundTripTest.java:64 return new WebSocketCborCodec( test · JsonContractRegistryTest.java:108 JacksonMessageCodec.of(Map.of(new MessageContractKey(text, V1), String.class), exact); test · JsonContractRegistryTest.java:37 JacksonMessageCodec.of( test · JsonContractRegistryTest.java:87 JacksonMessageCodec.of(Map.of(new MessageContractKey(largeList, V1), List.class), 1_024); test · JsonSchemaIntegrationEventEncoderTest.java:229 new LocalJsonSchemaRegistry( test · JsonSchemaIntegrationEventEncoderTest.java:242 return new LocalJsonSchemaRegistry.SchemaSource(path, bytes, sha256(bytes)); test · LocalJsonSchemaRegistryTest.java:119 new LocalJsonSchemaRegistry( test · LocalJsonSchemaRegistryTest.java:122 new LocalJsonSchemaRegistry.SchemaSource( test · LocalJsonSchemaRegistryTest.java:134 new LocalJsonSchemaRegistry.SchemaSource( test · LocalJsonSchemaRegistryTest.java:136 assertThatThrownBy(() -> new LocalJsonSchemaRegistry(duplicate, LIMITS)) test · LocalJsonSchemaRegistryTest.java:346 return new LocalJsonSchemaRegistry( test · LocalJsonSchemaRegistryTest.java:355 return new LocalJsonSchemaRegistry( test · LocalJsonSchemaRegistryTest.java:356 Map.of(path, new LocalJsonSchemaRegistry.SchemaSource(path, bytes, sha256(bytes))), LIMITS); test · LocalJsonSchemaRegistryTest.java:367 return new LocalJsonSchemaRegistry.SchemaSource(path, bytes, sha256(bytes)); test · MessagingEvidenceManifestSchemaValidator.java:48 new LocalJsonSchemaRegistry( test · MessagingEvidenceManifestSchemaValidator.java:51 new LocalJsonSchemaRegistry.SchemaSource( test · WebCodecMapperTest.java:109 WebXmlMapperFactory.create( test · WebCodecMapperTest.java:163 ObjectMapper mapper = WebCborMapperFactory.create(shallow); test · WebCodecMapperTest.java:38 return WebCborMapperFactory.create(CodecBudget.conventional(WebRepresentation.CBOR)); test · WebCodecMapperTest.java:42 return WebXmlMapperFactory.create(CodecBudget.conventional(WebRepresentation.XML)); test · WebCodecMapperTest.java:86 () -> WebCborMapperFactory.create(CodecBudget.conventional(WebRepresentation.XML))) test · WebSocketJsonWireManifestTest.java:49 new StrictWebSocketJsonCodec( 그 백엔드 잠금 항목이 실린 구성 : tools.jackson.dataformat:jackson-dataformat-cbor:3.1.5=compileClasspath,jettyCompatTestCompileClasspath,jettyCompatTestRuntimeClasspath,nginxProxyTestCompileClasspath,nginxProxyTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath,testkitCompileClasspath,testkitRuntimeClasspath tools.jackson.dataformat:jackson-dataformat-xml:3.1.5=compileClasspath,jettyCompatTestCompileClasspath,jettyCompatTestRuntimeClasspath,nginxProxyTestCompileClasspath,nginxProxyTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath,testkitCompileClasspath,testkitRuntimeClasspath # 표본 애플리케이션은 컬렉션 본문에 크기 제약을 건다 206- public record BatchCreateRequest( 207- @Valid 208: @Size(max = MAX_BATCH_SIZE, message = "batch may not exceed " + MAX_BATCH_SIZE + " items")