From ef5f9ae000b1fbc10036f35900529d6c1650b5a1 Mon Sep 17 00:00:00 2001 From: Sin-Kang Date: Sat, 23 May 2026 22:59:07 +0900 Subject: [PATCH] docs(readmes): badge-ify root tables now that easy-paging renumber landed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deferred from the earlier badge PR (#56, closed) — that one used the pre-renumber prefixes (versionPrefix=0.4 / 0.5). After #57 landed the renumber (easy-paging 0.4.0→3.0.0, 0.5.0→4.0.0), this PR finishes the badge conversion with the correct post-renumber prefixes. Changes per language (2 files, 40 lines each): Section headers — align with the renumber: "Spring Boot 4 (`0.5.x` line)" → "(`4.x` line)" "Spring Boot 3 maintenance (`0.4.x` line)" → "(`3.x` line)" Korean equivalents. Maintenance branch link — the branch was renamed too: [`0.4.x` branch](.../tree/0.4.x) → [`3.x` branch](.../tree/3.x) Column header — slight tightening since the cell content is now a badge instead of a coordinate string: "Maven Central coordinates" → "Maven Central" 14 rows — each "Maven Central coordinates" cell: [`kr.devslab::`](sonatype-link) → [![Maven Central](shields.io/maven-central/v/...?...&versionPrefix=N)](sonatype-link) Where N = 4 for SB4 rows, N = 3 for SB3 rows. ssrf-guard rows use no prefix (single-line library; whatever's latest on Maven Central is what readers should pull). The versionPrefix filter keeps the two easy-paging lines visually independent — without it, the SB3 row's badge would jump to the latest 4.x patch the moment one ships. Per-demo README "Files of interest" tables intentionally left as prose (copy-paste-friendly Gradle snippets; #55 already aligned them with the build files). A CI mismatch check is a follow-up if those drift again. Sibling PRs in the same badge sweep, already merged: - devslab-kr/.github#6 (org profile) - devslab-kr/api-log#3 (api-log doc surface for 3.0.0 renumber) Maven Central propagation note: api-log v3.0.0 published 13:44Z, profile badge picked it up within minutes — same auto-update behavior will apply to these demos on the next easy-paging patch release. --- README.ko.md | 40 ++++++++++++++++++++-------------------- README.md | 40 ++++++++++++++++++++-------------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/README.ko.md b/README.ko.md index 19894c0..08c6a77 100644 --- a/README.ko.md +++ b/README.ko.md @@ -10,38 +10,38 @@ ## 예제 -### easy-paging — Spring Boot 4 (`0.5.x` 라인) +### easy-paging — Spring Boot 4 (`4.x` 라인) 최신 active 라인. Spring Boot 4 이상 사용 중이면 여기. -| 데모 | 보여주는 것 | Maven Central 좌표 | +| 데모 | 보여주는 것 | Maven Central | | --- | --- | --- | -| [`easy-paging-sb4-demo`](easy-paging-sb4-demo/) | `@AutoPaginate` 어노테이션 기반 offset 페이지네이션 (Spring Boot 4 + MyBatis + H2) | [`kr.devslab:easy-paging-spring-boot-starter:4.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-sb4-keyset-demo`](easy-paging-sb4-keyset-demo/) | `@KeysetPaginate` 커서(keyset) 페이지네이션 — composite `(time, id)` 키, 쓰기 중에도 안정, `OFFSET`/`COUNT(*)` 없음 | [`kr.devslab:easy-paging-spring-boot-starter:4.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-sb4-postgres-demo`](easy-paging-sb4-postgres-demo/) | 동일 스타터를 **실제 PostgreSQL**과 — `bootRun`은 Docker Compose, 테스트는 Testcontainers + `@ServiceConnection`, 로컬 DB 설치 불필요 | [`kr.devslab:easy-paging-spring-boot-starter:4.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-sb4-reactive-demo`](easy-paging-sb4-reactive-demo/) | Reactive 스택 — **WebFlux + R2DBC**, `R2dbcOffsetPagingSupport` 사용. MVC 데모와 동일한 JSON 봉투를 `Mono>`로 서빙 | [`kr.devslab:easy-paging-spring-boot-starter-reactive:4.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter-reactive) | +| [`easy-paging-sb4-demo`](easy-paging-sb4-demo/) | `@AutoPaginate` 어노테이션 기반 offset 페이지네이션 (Spring Boot 4 + MyBatis + H2) | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=4)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-sb4-keyset-demo`](easy-paging-sb4-keyset-demo/) | `@KeysetPaginate` 커서(keyset) 페이지네이션 — composite `(time, id)` 키, 쓰기 중에도 안정, `OFFSET`/`COUNT(*)` 없음 | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=4)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-sb4-postgres-demo`](easy-paging-sb4-postgres-demo/) | 동일 스타터를 **실제 PostgreSQL**과 — `bootRun`은 Docker Compose, 테스트는 Testcontainers + `@ServiceConnection`, 로컬 DB 설치 불필요 | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=4)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-sb4-reactive-demo`](easy-paging-sb4-reactive-demo/) | Reactive 스택 — **WebFlux + R2DBC**, `R2dbcOffsetPagingSupport` 사용. MVC 데모와 동일한 JSON 봉투를 `Mono>`로 서빙 | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter-reactive?label=kr.devslab%3Aeasy-paging-spring-boot-starter-reactive&versionPrefix=4)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter-reactive) | -### easy-paging — Spring Boot 3 maintenance (`0.4.x` 라인) +### easy-paging — Spring Boot 3 maintenance (`3.x` 라인) -Spring Boot 3.3–3.5 사용 중인 앱용. 스타터의 [`0.4.x` 브랜치](https://github.com/devslab-kr/easy-paging-spring-boot-starter/tree/0.4.x)가 SB3 보안 패치를 계속 받고, 이 데모들은 그 라인에 pin 됨. +Spring Boot 3.3–3.5 사용 중인 앱용. 스타터의 [`3.x` 브랜치](https://github.com/devslab-kr/easy-paging-spring-boot-starter/tree/3.x)가 SB3 보안 패치를 계속 받고, 이 데모들은 그 라인에 pin 됨. -| 데모 | 보여주는 것 | Maven Central 좌표 | +| 데모 | 보여주는 것 | Maven Central | | --- | --- | --- | -| [`easy-paging-demo`](easy-paging-demo/) | `@AutoPaginate` 어노테이션 기반 offset 페이지네이션 (Spring Boot 3 + MyBatis + H2) | [`kr.devslab:easy-paging-spring-boot-starter:3.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-keyset-demo`](easy-paging-keyset-demo/) | `@KeysetPaginate` 커서 페이지네이션 | [`kr.devslab:easy-paging-spring-boot-starter:3.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-postgres-demo`](easy-paging-postgres-demo/) | 실제 PostgreSQL 사용 | [`kr.devslab:easy-paging-spring-boot-starter:3.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-reactive-demo`](easy-paging-reactive-demo/) | Reactive 스택 — WebFlux + R2DBC | [`kr.devslab:easy-paging-spring-boot-starter-reactive:3.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter-reactive) | +| [`easy-paging-demo`](easy-paging-demo/) | `@AutoPaginate` 어노테이션 기반 offset 페이지네이션 (Spring Boot 3 + MyBatis + H2) | [![Maven Central 3.x](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=3)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-keyset-demo`](easy-paging-keyset-demo/) | `@KeysetPaginate` 커서 페이지네이션 | [![Maven Central 3.x](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=3)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-postgres-demo`](easy-paging-postgres-demo/) | 실제 PostgreSQL 사용 | [![Maven Central 3.x](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=3)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-reactive-demo`](easy-paging-reactive-demo/) | Reactive 스택 — WebFlux + R2DBC | [![Maven Central 3.x](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter-reactive?label=kr.devslab%3Aeasy-paging-spring-boot-starter-reactive&versionPrefix=3)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter-reactive) | ### ssrf-guard -| 데모 | 보여주는 것 | Maven Central 좌표 | +| 데모 | 보여주는 것 | Maven Central | | --- | --- | --- | -| [`ssrf-guard-demo`](ssrf-guard-demo/) | SSRF(Server-Side Request Forgery) 방어를 3종 Spring HTTP 클라이언트(RestClient, RestTemplate, WebClient)에 동시 적용 — 모두 같은 `UrlPolicy`. 15가지 공격 매트릭스 엔드포인트, Micrometer 메트릭 포함 | [`kr.devslab:ssrf-guard:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard) | -| [`ssrf-guard-springai-demo`](ssrf-guard-springai-demo/) | ⭐ **LLM 에이전트 SSRF 방어 (Spring AI).** 모든 Spring AI `ToolCallback`을 자동으로 wrap해서 LLM이 `fetch_url`을 호출하기 전에 URL 인자를 검증. 가짜 LLM 드라이버로 API 키 없이 오프라인 실행 가능 | [`kr.devslab:ssrf-guard-springai:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-springai) | -| [`ssrf-guard-langchain4j-demo`](ssrf-guard-langchain4j-demo/) | ⭐ **LLM 에이전트 SSRF 방어 (LangChain4j).** 자바의 또 다른 메이저 LLM 프레임워크용 — 모든 `ToolExecutor` 빈을 wrap, executor 실행 전에 `ToolExecutionRequest.arguments()` JSON을 검증 | [`kr.devslab:ssrf-guard-langchain4j:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-langchain4j) | -| [`ssrf-guard-feign-demo`](ssrf-guard-feign-demo/) | Spring Cloud OpenFeign `RequestInterceptor` — `@FeignClient` 호출에 동일 `UrlPolicy` 적용. 화이트리스트 / 비화이트리스트 `@FeignClient` 2개로 차단 경로 시연 | [`kr.devslab:ssrf-guard-feign:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-feign) | -| [`ssrf-guard-jdkhttp-demo`](ssrf-guard-jdkhttp-demo/) | `java.net.http.HttpClient`(Java 11+) 래퍼 — 라이브러리 자체엔 Spring 의존성 없음. `main()`에서 3줄 wiring | [`kr.devslab:ssrf-guard-jdkhttp:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-jdkhttp) | -| [`ssrf-guard-okhttp-demo`](ssrf-guard-okhttp-demo/) | OkHttp `Interceptor` + `Dns` — Spring 필요 없음. `OkHttpClient.Builder`에 3줄 wiring | [`kr.devslab:ssrf-guard-okhttp:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-okhttp) | +| [`ssrf-guard-demo`](ssrf-guard-demo/) | SSRF(Server-Side Request Forgery) 방어를 3종 Spring HTTP 클라이언트(RestClient, RestTemplate, WebClient)에 동시 적용 — 모두 같은 `UrlPolicy`. 15가지 공격 매트릭스 엔드포인트, Micrometer 메트릭 포함 | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard?label=kr.devslab%3Assrf-guard)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard) | +| [`ssrf-guard-springai-demo`](ssrf-guard-springai-demo/) | ⭐ **LLM 에이전트 SSRF 방어 (Spring AI).** 모든 Spring AI `ToolCallback`을 자동으로 wrap해서 LLM이 `fetch_url`을 호출하기 전에 URL 인자를 검증. 가짜 LLM 드라이버로 API 키 없이 오프라인 실행 가능 | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-springai?label=kr.devslab%3Assrf-guard-springai)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-springai) | +| [`ssrf-guard-langchain4j-demo`](ssrf-guard-langchain4j-demo/) | ⭐ **LLM 에이전트 SSRF 방어 (LangChain4j).** 자바의 또 다른 메이저 LLM 프레임워크용 — 모든 `ToolExecutor` 빈을 wrap, executor 실행 전에 `ToolExecutionRequest.arguments()` JSON을 검증 | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-langchain4j?label=kr.devslab%3Assrf-guard-langchain4j)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-langchain4j) | +| [`ssrf-guard-feign-demo`](ssrf-guard-feign-demo/) | Spring Cloud OpenFeign `RequestInterceptor` — `@FeignClient` 호출에 동일 `UrlPolicy` 적용. 화이트리스트 / 비화이트리스트 `@FeignClient` 2개로 차단 경로 시연 | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-feign?label=kr.devslab%3Assrf-guard-feign)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-feign) | +| [`ssrf-guard-jdkhttp-demo`](ssrf-guard-jdkhttp-demo/) | `java.net.http.HttpClient`(Java 11+) 래퍼 — 라이브러리 자체엔 Spring 의존성 없음. `main()`에서 3줄 wiring | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-jdkhttp?label=kr.devslab%3Assrf-guard-jdkhttp)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-jdkhttp) | +| [`ssrf-guard-okhttp-demo`](ssrf-guard-okhttp-demo/) | OkHttp `Interceptor` + `Dns` — Spring 필요 없음. `OkHttpClient.Builder`에 3줄 wiring | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-okhttp?label=kr.devslab%3Assrf-guard-okhttp)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-okhttp) | ## 컨벤션 diff --git a/README.md b/README.md index 36ca142..c6077fc 100644 --- a/README.md +++ b/README.md @@ -10,38 +10,38 @@ Each subdirectory is an **independent** Spring Boot application with its own Gra ## Examples -### easy-paging — Spring Boot 4 (`0.5.x` line) +### easy-paging — Spring Boot 4 (`4.x` line) Latest active line. Use these if your app is on Spring Boot 4+. -| Demo | Showcases | Maven Central coordinates | +| Demo | Showcases | Maven Central | | --- | --- | --- | -| [`easy-paging-sb4-demo`](easy-paging-sb4-demo/) | Annotation-driven offset pagination with `@AutoPaginate` (Spring Boot 4 + MyBatis + H2) | [`kr.devslab:easy-paging-spring-boot-starter:4.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-sb4-keyset-demo`](easy-paging-sb4-keyset-demo/) | Cursor (keyset) pagination with `@KeysetPaginate` — composite `(time, id)` key, stable under writes, no `OFFSET`/`COUNT(*)` | [`kr.devslab:easy-paging-spring-boot-starter:4.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-sb4-postgres-demo`](easy-paging-sb4-postgres-demo/) | Same starter against **real PostgreSQL** — Docker Compose for `bootRun`, Testcontainers + `@ServiceConnection` for tests, no local DB install | [`kr.devslab:easy-paging-spring-boot-starter:4.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-sb4-reactive-demo`](easy-paging-sb4-reactive-demo/) | Reactive stack — **WebFlux + R2DBC** via `R2dbcOffsetPagingSupport`. Same JSON envelope as the MVC demos, served as `Mono>` | [`kr.devslab:easy-paging-spring-boot-starter-reactive:4.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter-reactive) | +| [`easy-paging-sb4-demo`](easy-paging-sb4-demo/) | Annotation-driven offset pagination with `@AutoPaginate` (Spring Boot 4 + MyBatis + H2) | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=4)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-sb4-keyset-demo`](easy-paging-sb4-keyset-demo/) | Cursor (keyset) pagination with `@KeysetPaginate` — composite `(time, id)` key, stable under writes, no `OFFSET`/`COUNT(*)` | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=4)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-sb4-postgres-demo`](easy-paging-sb4-postgres-demo/) | Same starter against **real PostgreSQL** — Docker Compose for `bootRun`, Testcontainers + `@ServiceConnection` for tests, no local DB install | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=4)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-sb4-reactive-demo`](easy-paging-sb4-reactive-demo/) | Reactive stack — **WebFlux + R2DBC** via `R2dbcOffsetPagingSupport`. Same JSON envelope as the MVC demos, served as `Mono>` | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter-reactive?label=kr.devslab%3Aeasy-paging-spring-boot-starter-reactive&versionPrefix=4)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter-reactive) | -### easy-paging — Spring Boot 3 maintenance (`0.4.x` line) +### easy-paging — Spring Boot 3 maintenance (`3.x` line) -For apps still on Spring Boot 3.3–3.5. The starter's [`0.4.x` branch](https://github.com/devslab-kr/easy-paging-spring-boot-starter/tree/0.4.x) continues to receive SB3 security patches; these demos pin against that line. +For apps still on Spring Boot 3.3–3.5. The starter's [`3.x` branch](https://github.com/devslab-kr/easy-paging-spring-boot-starter/tree/3.x) continues to receive SB3 security patches; these demos pin against that line. -| Demo | Showcases | Maven Central coordinates | +| Demo | Showcases | Maven Central | | --- | --- | --- | -| [`easy-paging-demo`](easy-paging-demo/) | Annotation-driven offset pagination with `@AutoPaginate` (Spring Boot 3 + MyBatis + H2) | [`kr.devslab:easy-paging-spring-boot-starter:3.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-keyset-demo`](easy-paging-keyset-demo/) | Cursor (keyset) pagination with `@KeysetPaginate` | [`kr.devslab:easy-paging-spring-boot-starter:3.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-postgres-demo`](easy-paging-postgres-demo/) | Same starter against real PostgreSQL | [`kr.devslab:easy-paging-spring-boot-starter:3.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | -| [`easy-paging-reactive-demo`](easy-paging-reactive-demo/) | Reactive stack — WebFlux + R2DBC | [`kr.devslab:easy-paging-spring-boot-starter-reactive:3.0.0`](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter-reactive) | +| [`easy-paging-demo`](easy-paging-demo/) | Annotation-driven offset pagination with `@AutoPaginate` (Spring Boot 3 + MyBatis + H2) | [![Maven Central 3.x](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=3)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-keyset-demo`](easy-paging-keyset-demo/) | Cursor (keyset) pagination with `@KeysetPaginate` | [![Maven Central 3.x](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=3)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-postgres-demo`](easy-paging-postgres-demo/) | Same starter against real PostgreSQL | [![Maven Central 3.x](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter?label=kr.devslab%3Aeasy-paging-spring-boot-starter&versionPrefix=3)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter) | +| [`easy-paging-reactive-demo`](easy-paging-reactive-demo/) | Reactive stack — WebFlux + R2DBC | [![Maven Central 3.x](https://img.shields.io/maven-central/v/kr.devslab/easy-paging-spring-boot-starter-reactive?label=kr.devslab%3Aeasy-paging-spring-boot-starter-reactive&versionPrefix=3)](https://central.sonatype.com/artifact/kr.devslab/easy-paging-spring-boot-starter-reactive) | ### ssrf-guard -| Demo | Showcases | Maven Central coordinates | +| Demo | Showcases | Maven Central | | --- | --- | --- | -| [`ssrf-guard-demo`](ssrf-guard-demo/) | SSRF (Server-Side Request Forgery) protection across three Spring HTTP clients (RestClient, RestTemplate, WebClient) — same `UrlPolicy` for all. 15-pattern attack matrix endpoint, Micrometer metrics. | [`kr.devslab:ssrf-guard:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard) | -| [`ssrf-guard-springai-demo`](ssrf-guard-springai-demo/) | ⭐ **LLM agent SSRF defense (Spring AI).** Wraps every Spring AI `ToolCallback` so URL-shaped tool arguments are validated before the LLM-driven `fetch_url` runs. Fake-LLM driver makes the demo runnable offline (no API key). | [`kr.devslab:ssrf-guard-springai:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-springai) | -| [`ssrf-guard-langchain4j-demo`](ssrf-guard-langchain4j-demo/) | ⭐ **LLM agent SSRF defense (LangChain4j).** Same story for the other major Java LLM framework — wraps every `ToolExecutor` bean and validates `ToolExecutionRequest.arguments()` JSON before the executor runs. | [`kr.devslab:ssrf-guard-langchain4j:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-langchain4j) | -| [`ssrf-guard-feign-demo`](ssrf-guard-feign-demo/) | Spring Cloud OpenFeign `RequestInterceptor` — same `UrlPolicy` applied to `@FeignClient` calls. Two `@FeignClient` interfaces (one whitelisted, one not) to show the block path. | [`kr.devslab:ssrf-guard-feign:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-feign) | -| [`ssrf-guard-jdkhttp-demo`](ssrf-guard-jdkhttp-demo/) | `java.net.http.HttpClient` (Java 11+) wrapper — no Spring required by the library. Three-line wiring in `main()`. | [`kr.devslab:ssrf-guard-jdkhttp:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-jdkhttp) | -| [`ssrf-guard-okhttp-demo`](ssrf-guard-okhttp-demo/) | OkHttp `Interceptor` + `Dns` integration — also no Spring needed. Three-line wiring on `OkHttpClient.Builder`. | [`kr.devslab:ssrf-guard-okhttp:3.1.0`](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-okhttp) | +| [`ssrf-guard-demo`](ssrf-guard-demo/) | SSRF (Server-Side Request Forgery) protection across three Spring HTTP clients (RestClient, RestTemplate, WebClient) — same `UrlPolicy` for all. 15-pattern attack matrix endpoint, Micrometer metrics. | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard?label=kr.devslab%3Assrf-guard)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard) | +| [`ssrf-guard-springai-demo`](ssrf-guard-springai-demo/) | ⭐ **LLM agent SSRF defense (Spring AI).** Wraps every Spring AI `ToolCallback` so URL-shaped tool arguments are validated before the LLM-driven `fetch_url` runs. Fake-LLM driver makes the demo runnable offline (no API key). | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-springai?label=kr.devslab%3Assrf-guard-springai)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-springai) | +| [`ssrf-guard-langchain4j-demo`](ssrf-guard-langchain4j-demo/) | ⭐ **LLM agent SSRF defense (LangChain4j).** Same story for the other major Java LLM framework — wraps every `ToolExecutor` bean and validates `ToolExecutionRequest.arguments()` JSON before the executor runs. | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-langchain4j?label=kr.devslab%3Assrf-guard-langchain4j)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-langchain4j) | +| [`ssrf-guard-feign-demo`](ssrf-guard-feign-demo/) | Spring Cloud OpenFeign `RequestInterceptor` — same `UrlPolicy` applied to `@FeignClient` calls. Two `@FeignClient` interfaces (one whitelisted, one not) to show the block path. | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-feign?label=kr.devslab%3Assrf-guard-feign)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-feign) | +| [`ssrf-guard-jdkhttp-demo`](ssrf-guard-jdkhttp-demo/) | `java.net.http.HttpClient` (Java 11+) wrapper — no Spring required by the library. Three-line wiring in `main()`. | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-jdkhttp?label=kr.devslab%3Assrf-guard-jdkhttp)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-jdkhttp) | +| [`ssrf-guard-okhttp-demo`](ssrf-guard-okhttp-demo/) | OkHttp `Interceptor` + `Dns` integration — also no Spring needed. Three-line wiring on `OkHttpClient.Builder`. | [![Maven Central](https://img.shields.io/maven-central/v/kr.devslab/ssrf-guard-okhttp?label=kr.devslab%3Assrf-guard-okhttp)](https://central.sonatype.com/artifact/kr.devslab/ssrf-guard-okhttp) | ## Conventions