@searchos/bot-proxy 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @searchos/bot-proxy might be problematic. Click here for more details.
- package/README.md +96 -33
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
## 워크플로우
|
|
6
6
|
|
|
7
|
+
### 봇 분류
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
봇 요청 (UA 기반 감지)
|
|
11
|
+
│
|
|
12
|
+
├── AI 봇 (isAi: true) + aiRender 활성화
|
|
13
|
+
│ ai 캐시 → desktop 폴백 → origin
|
|
14
|
+
│
|
|
15
|
+
└── 일반 봇 (검색엔진, SNS, SEO 등)
|
|
16
|
+
desktop/mobile 캐시 → origin
|
|
17
|
+
```
|
|
18
|
+
|
|
7
19
|
### Next.js + CloudFront (S3)
|
|
8
20
|
|
|
9
21
|
```
|
|
@@ -14,25 +26,28 @@ Next.js middleware
|
|
|
14
26
|
│
|
|
15
27
|
├── nextjsProxy() 호출
|
|
16
28
|
│ │
|
|
29
|
+
│ ├── 정적 SEO 파일 (robots.txt, sitemap.xml, llms.txt)
|
|
30
|
+
│ │ → 프리렌더 서버에서 프록시
|
|
31
|
+
│ │
|
|
17
32
|
│ ├── UA로 봇 감지 (detectBot)
|
|
18
33
|
│ │ 봇 아님 → null 반환 → 기존 middleware 실행
|
|
19
34
|
│ │
|
|
20
35
|
│ ├── IP 대역 검증 (verifyBotIp) → 로그에 ip_verified 기록
|
|
21
36
|
│ │
|
|
22
|
-
│ ├──
|
|
23
|
-
│ │
|
|
24
|
-
│ │
|
|
25
|
-
│
|
|
26
|
-
│ │ GET https://{cf도메인}/v2/{사이트도메인}/{hash}_{device}.html
|
|
37
|
+
│ ├── [AI 봇 + aiRender + aiPath 매칭]
|
|
38
|
+
│ │ │
|
|
39
|
+
│ │ ├── ai 캐시 조회: {cf}/v2/{도메인}/{hash}_ai.html
|
|
40
|
+
│ │ │ 히트 → HIT-AI 반환 + ai 워밍
|
|
27
41
|
│ │ │
|
|
28
|
-
│ │ ├──
|
|
29
|
-
│ │ │
|
|
42
|
+
│ │ ├── desktop 폴백: {cf}/v2/{도메인}/{hash}_desktop.html
|
|
43
|
+
│ │ │ 히트 → HIT-DESKTOP 반환 + ai 워밍
|
|
30
44
|
│ │ │
|
|
31
|
-
│ │ └── 미스 → null
|
|
32
|
-
│ │ + 백그라운드: 봇 로그 전송 + 캐시 워밍 요청
|
|
45
|
+
│ │ └── 미스 → null (origin) + ai 워밍 + 일반 워밍
|
|
33
46
|
│ │
|
|
34
|
-
│ └──
|
|
35
|
-
│
|
|
47
|
+
│ └── [일반 봇]
|
|
48
|
+
│ 캐시 조회: {cf}/v2/{도메인}/{hash}_{device}.html
|
|
49
|
+
│ 히트 → HIT 반환 + 워밍
|
|
50
|
+
│ 미스 → null (origin) + 워밍
|
|
36
51
|
│
|
|
37
52
|
▼
|
|
38
53
|
기존 middleware 로직 (인증, i18n, 리다이렉트 등)
|
|
@@ -48,25 +63,31 @@ Cloudflare Worker
|
|
|
48
63
|
│
|
|
49
64
|
├── cloudflareProxy() 호출
|
|
50
65
|
│ │
|
|
66
|
+
│ ├── 정적 SEO 파일 (robots.txt, sitemap.xml, llms.txt)
|
|
67
|
+
│ │ → 프리렌더 서버에서 프록시
|
|
68
|
+
│ │
|
|
51
69
|
│ ├── UA로 봇 감지 (detectBot)
|
|
52
70
|
│ │ 봇 아님 → null 반환 → origin fetch
|
|
53
71
|
│ │
|
|
54
|
-
│ ├──
|
|
72
|
+
│ ├── KV 바인딩 확인 (env.V2_CACHE)
|
|
73
|
+
│ │ 없음 → null 반환
|
|
55
74
|
│ │
|
|
56
|
-
│ ├──
|
|
57
|
-
│ │ URL path → 정규화 → MD5 → {hash}_{device}
|
|
75
|
+
│ ├── IP 대역 검증 (verifyBotIp) → 로그에 ip_verified 기록
|
|
58
76
|
│ │
|
|
59
|
-
│ ├──
|
|
60
|
-
│ │
|
|
77
|
+
│ ├── [AI 봇 + aiRender + aiPath 매칭]
|
|
78
|
+
│ │ │
|
|
79
|
+
│ │ ├── ai 캐시 조회: V2_CACHE.get("{hash}_ai")
|
|
80
|
+
│ │ │ 히트 → HIT-AI 반환 + waitUntil(로그 + ai 워밍)
|
|
61
81
|
│ │ │
|
|
62
|
-
│ │ ├──
|
|
63
|
-
│ │ │
|
|
82
|
+
│ │ ├── desktop 폴백: V2_CACHE.get("{hash}_desktop")
|
|
83
|
+
│ │ │ 히트 → HIT-DESKTOP 반환 + waitUntil(로그 + ai 워밍)
|
|
64
84
|
│ │ │
|
|
65
|
-
│ │ └── 미스 → null
|
|
66
|
-
│ │ + waitUntil: 봇 로그 전송 + 캐시 워밍 요청
|
|
85
|
+
│ │ └── 미스 → null (origin) + waitUntil(로그 + ai 워밍 + 일반 워밍)
|
|
67
86
|
│ │
|
|
68
|
-
│ └──
|
|
69
|
-
│
|
|
87
|
+
│ └── [일반 봇]
|
|
88
|
+
│ 캐시 조회: V2_CACHE.get("{hash}_{device}")
|
|
89
|
+
│ 히트 → HIT 반환 + waitUntil(로그 + 워밍)
|
|
90
|
+
│ 미스 → null (origin) + waitUntil(로그 + 워밍)
|
|
70
91
|
│
|
|
71
92
|
▼
|
|
72
93
|
origin (고객 서버)
|
|
@@ -78,6 +99,26 @@ origin (고객 서버)
|
|
|
78
99
|
npm install @searchos/bot-proxy
|
|
79
100
|
```
|
|
80
101
|
|
|
102
|
+
## 옵션
|
|
103
|
+
|
|
104
|
+
### 공통 옵션
|
|
105
|
+
|
|
106
|
+
| 옵션 | 타입 | 필수 | 기본값 | 설명 |
|
|
107
|
+
|------|------|------|--------|------|
|
|
108
|
+
| `projectId` | `string` | O | | SearchOS 프로젝트 ID |
|
|
109
|
+
| `siteDomain` | `string` | O | | 사이트 도메인 (`https://` 자동 제거) |
|
|
110
|
+
| `prerenderDomain` | `string` | O | | 프리렌더 서버 URL |
|
|
111
|
+
| `botLogEndpoint` | `string` | O | | 봇 로그 엔드포인트 |
|
|
112
|
+
| `aiRender` | `boolean` | | `true` | AI 봇에게 ai 캐시 우선 서빙 |
|
|
113
|
+
| `ocr` | `boolean` | | `true` | AI 워밍 요청 시 OCR 포함 여부 |
|
|
114
|
+
| `aiPathPrefixes` | `string[]` | | `[]` | AI 렌더 적용 경로 prefix (빈 배열 = 전체 경로) |
|
|
115
|
+
|
|
116
|
+
### Next.js 전용
|
|
117
|
+
|
|
118
|
+
| 옵션 | 타입 | 필수 | 설명 |
|
|
119
|
+
|------|------|------|------|
|
|
120
|
+
| `cloudfrontDomain` | `string` | O | CloudFront 배포 도메인 (S3 캐시 조회용) |
|
|
121
|
+
|
|
81
122
|
## 사용법
|
|
82
123
|
|
|
83
124
|
### Next.js
|
|
@@ -88,15 +129,18 @@ import { nextjsProxy } from "@searchos/bot-proxy";
|
|
|
88
129
|
|
|
89
130
|
export async function middleware(request) {
|
|
90
131
|
const res = await nextjsProxy(request, {
|
|
91
|
-
projectId: "...",
|
|
92
|
-
siteDomain: "example.com",
|
|
93
|
-
cloudfrontDomain: "
|
|
94
|
-
prerenderDomain: "
|
|
95
|
-
botLogEndpoint: "
|
|
132
|
+
projectId: "...",
|
|
133
|
+
siteDomain: "example.com",
|
|
134
|
+
cloudfrontDomain: "https://d1234.cloudfront.net",
|
|
135
|
+
prerenderDomain: "https://proxy.searchos.kr",
|
|
136
|
+
botLogEndpoint: "https://botlog.searchos.kr/bot-ping",
|
|
137
|
+
// AI 옵션 (모두 선택사항)
|
|
138
|
+
aiRender: true, // AI 봇에게 ai 캐시 우선 서빙
|
|
139
|
+
ocr: true, // AI 워밍 시 OCR 포함
|
|
140
|
+
aiPathPrefixes: ["/blog/"], // /blog/ 하위만 AI 렌더 적용
|
|
96
141
|
});
|
|
97
142
|
if (res) return res;
|
|
98
143
|
|
|
99
|
-
// 기존 middleware 로직
|
|
100
144
|
return NextResponse.next();
|
|
101
145
|
}
|
|
102
146
|
```
|
|
@@ -110,17 +154,28 @@ export default {
|
|
|
110
154
|
async fetch(request, env, ctx) {
|
|
111
155
|
const res = await cloudflareProxy(request, env, ctx, {
|
|
112
156
|
projectId: "...",
|
|
113
|
-
siteDomain: "
|
|
114
|
-
prerenderDomain: "
|
|
115
|
-
botLogEndpoint: "
|
|
157
|
+
siteDomain: "example.com",
|
|
158
|
+
prerenderDomain: "https://proxy.searchos.kr",
|
|
159
|
+
botLogEndpoint: "https://botlog.searchos.kr/bot-ping",
|
|
160
|
+
// AI 옵션 (모두 선택사항)
|
|
161
|
+
aiRender: true,
|
|
162
|
+
ocr: true,
|
|
163
|
+
aiPathPrefixes: [], // 빈 배열 = 전체 경로에 AI 렌더 적용
|
|
116
164
|
});
|
|
117
165
|
if (res) return res;
|
|
118
166
|
|
|
119
|
-
return fetch(request);
|
|
167
|
+
return fetch(request);
|
|
120
168
|
}
|
|
121
169
|
};
|
|
122
170
|
```
|
|
123
171
|
|
|
172
|
+
> **KV 바인딩 필수**: Cloudflare Worker는 `wrangler.toml`에 `V2_CACHE` KV namespace 바인딩이 필요.
|
|
173
|
+
> ```toml
|
|
174
|
+
> [[kv_namespaces]]
|
|
175
|
+
> binding = "V2_CACHE"
|
|
176
|
+
> id = "your-kv-namespace-id"
|
|
177
|
+
> ```
|
|
178
|
+
|
|
124
179
|
## 캐시 키 규칙
|
|
125
180
|
|
|
126
181
|
```
|
|
@@ -178,12 +233,20 @@ UA 기반으로 6개 카테고리의 봇을 감지:
|
|
|
178
233
|
|
|
179
234
|
## 응답 헤더
|
|
180
235
|
|
|
236
|
+
캐시 히트 시에만 응답에 포함 (미스 시 null 반환, 헤더 없음).
|
|
237
|
+
|
|
181
238
|
| 헤더 | 값 | 설명 |
|
|
182
239
|
|------|-----|------|
|
|
183
|
-
| X-Cache | HIT /
|
|
240
|
+
| X-Cache | `HIT-AI` / `HIT-DESKTOP` / `HIT` | 어떤 캐시에서 서빙되었는지 |
|
|
184
241
|
| X-Bot | googlebot, chatgpt-user 등 | 감지된 봇 이름 |
|
|
185
242
|
| X-Bot-Verified | true / false | IP 대역 검증 결과 |
|
|
186
243
|
|
|
244
|
+
| X-Cache 값 | 의미 |
|
|
245
|
+
|-------------|------|
|
|
246
|
+
| `HIT-AI` | AI 전용 캐시에서 서빙 |
|
|
247
|
+
| `HIT-DESKTOP` | AI 봇이지만 ai 캐시 미스, desktop 폴백으로 서빙 |
|
|
248
|
+
| `HIT` | 일반 봇, desktop/mobile 캐시에서 서빙 |
|
|
249
|
+
|
|
187
250
|
## 패키지 구조
|
|
188
251
|
|
|
189
252
|
```
|