同一URLの直接アクセスによるA/Bテスト
クッキーに基づいて提供されるレスポンスを制御することでA/Bテストを設定します。このバージョンは、リクエストをオリジンでテストおよび制御に渡すことをサポートし、ランダム割り当てをバイパスします。
const NAME = "myExampleWorkersABTest";
export default { async fetch(req) { const url = new URL(req.url);
// コントロールおよびテストルートへの直接アクセスを許可するためにパススルーを有効にします。 if (url.pathname.startsWith("/control") || url.pathname.startsWith("/test")) return fetch(req);
// このリクエスターがどのグループに属しているかを判断します。 const cookie = req.headers.get("cookie");
if (cookie && cookie.includes(`${NAME}=control`)) { url.pathname = "/control" + url.pathname; } else if (cookie && cookie.includes(`${NAME}=test`)) { url.pathname = "/test" + url.pathname; } else { // クッキーがない場合、これは新しいクライアントです。グループを選択し、クッキーを設定します。 const group = Math.random() < 0.5 ? "test" : "control"; // 50/50の分割 if (group === "control") { url.pathname = "/control" + url.pathname; } else { url.pathname = "/test" + url.pathname; } // 不変性を避けるためにレスポンスを再構築します let res = await fetch(url); res = new Response(res.body, res); // 永続的なA/Bセッションを有効にするためにクッキーを設定します。 res.headers.append("Set-Cookie", `${NAME}=${group}; path=/`); return res; } return fetch(url); },};const NAME = "myExampleWorkersABTest";
export default { async fetch(req): Promise<Response> { const url = new URL(req.url); // コントロールおよびテストルートへの直接アクセスを許可するためにパススルーを有効にします。 if (url.pathname.startsWith("/control") || url.pathname.startsWith("/test")) return fetch(req); // このリクエスターがどのグループに属しているかを判断します。 const cookie = req.headers.get("cookie"); if (cookie && cookie.includes(`${NAME}=control`)) { url.pathname = "/control" + url.pathname; } else if (cookie && cookie.includes(`${NAME}=test`)) { url.pathname = "/test" + url.pathname; } else { // クッキーがない場合、これは新しいクライアントです。グループを選択し、クッキーを設定します。 const group = Math.random() < 0.5 ? "test" : "control"; // 50/50の分割 if (group === "control") { url.pathname = "/control" + url.pathname; } else { url.pathname = "/test" + url.pathname; } // 不変性を避けるためにレスポンスを再構築します let res = await fetch(url); res = new Response(res.body, res); // 永続的なA/Bセッションを有効にするためにクッキーを設定します。 res.headers.append("Set-Cookie", `${NAME}=${group}; path=/`); return res; } return fetch(url); },} satisfies ExportedHandler;import randomfrom urllib.parse import urlparse, urlunparsefrom js import Response, Headers, fetch
NAME = "myExampleWorkersABTest"
async def on_fetch(request): url = urlparse(request.url) # ローカルでテストする際は以下のコメントを外してください # url = url._replace(netloc="example.com") if "localhost" in url.netloc else url
# コントロールおよびテストルートへの直接アクセスを許可するためにパススルーを有効にします。 if url.path.startswith("/control") or url.path.startswith("/test"): return fetch(urlunparse(url))
# このリクエスターがどのグループに属しているかを判断します。 cookie = request.headers.get("cookie")
if cookie and f'{NAME}=control' in cookie: url = url._replace(path="/control" + url.path) elif cookie and f'{NAME}=test' in cookie: url = url._replace(path="/test" + url.path) else: # クッキーがない場合、これは新しいクライアントです。グループを選択し、クッキーを設定します。 group = "test" if random.random() < 0.5 else "control" if group == "control": url = url._replace(path="/control" + url.path) else: url = url._replace(path="/test" + url.path)
# 不変性を避けるためにレスポンスを再構築します res = await fetch(urlunparse(url)) headers = dict(res.headers) headers["Set-Cookie"] = f'{NAME}={group}; path=/' headers = Headers.new(headers.items()) return Response.new(res.body, headers=headers)
return fetch(urlunparse(url))