#!/usr/bin/env bash
# 测试 Envoy Lua 双 Cookie XSRF + 登录接口 + 限流头
# 用法:
#   ./test-login-xsrf-rl.sh [BASE_URL] [WARM_PATH] [LOGIN_PATH] [COUNT] [INTERVAL]
# 环境变量:
#   INSECURE=1                  # https 自签时跳过校验
#   TOKEN_HEADER=xsrf-token
#   USERNAME=testUser
#   PASSWORD=string
#   PHONE=string
#   REMEMBER=true               # true/false
#   DATA='{"username":"..."}'   # 直接提供完整 JSON，将覆盖上面四项
#
# 例子:
#   ./test-login-xsrf-rl.sh http://127.0.0.1:8080 /healthz /api/v1/auth/login 25 0.1

set -euo pipefail

BASE_URL="${1:-http://127.0.0.1:8080}"
WARM_PATH="${2:-/healthz}"
LOGIN_PATH="${3:-/api/v1/auth/login}"
COUNT="${4:-20}"
INTERVAL="${5:-0.05}"

METHOD="POST"
CONTENT_TYPE="application/json"

TOKEN_HEADER="${TOKEN_HEADER:-xsrf-token}"
TOKEN_COOKIE="__Host-XSRF-TOKEN"
GUARD_COOKIE="__Host-XSRF-GUARD"

USERNAME="${USERNAME:-testUser}"
PASSWORD="${PASSWORD:-string}"
PHONE="${PHONE:-string}"
REMEMBER="${REMEMBER:-true}"

INSECURE="${INSECURE:-}"

CURL_COMMON=(-sS -L)
[[ -n "${INSECURE}" ]] && CURL_COMMON+=(-k)

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
hdr="$tmpdir/hdr"

echo "# Base=${BASE_URL} Warm=${WARM_PATH} Login=${LOGIN_PATH} Count=${COUNT} Interval=${INTERVAL}s"

# 构造请求体（优先使用 DATA；否则用变量拼装）
build_data() {
  if [[ -n "${DATA:-}" ]]; then
    DATA_PAYLOAD="${DATA}"
    return
  fi

  # 规范化 REMEMBER 为 true/false
  case "${REMEMBER,,}" in
    true) REMEMBER=true ;;
    false) REMEMBER=false ;;
    *) REMEMBER=true ;;
  esac

  if command -v jq >/dev/null 2>&1; then
    DATA_PAYLOAD="$(
      jq -n \
        --arg username "$USERNAME" \
        --arg password "$PASSWORD" \
        --arg phone "$PHONE" \
        --argjson remember "$REMEMBER" \
        '{username:$username,password:$password,phone:$phone,remember:$remember}'
    )"
  else
    # 无 jq 的简易拼装（注意变量里如含双引号会破坏 JSON，生产建议安装 jq）
    DATA_PAYLOAD=$(cat <<JSON
{"username":"$USERNAME","password":"$PASSWORD","phone":"$PHONE","remember":$REMEMBER}
JSON
)
  fi
}

warm_set_cookies() {
  local url="${BASE_URL}${WARM_PATH}"
  echo "# 预热: GET ${url} 以获得 CSRF 双 Cookie"
  curl "${CURL_COMMON[@]}" -X GET -D "$hdr" -o /dev/null "$url" || true

  # 解析 Set-Cookie
  local out
  out=$(awk '
    {
      line=$0; gsub("\r","",line);
      low=tolower(line);
      if (index(low,"set-cookie:")==1) {
        sub(/^[Ss]et-[Cc]ookie:[ ]*/, "", line);
        split(line, p, /;/); split(p[1], kv, /=/);
        name=tolower(kv[1]); val=kv[2];
        if (name=="__host-xsrf-token") token=val;
        if (name=="__host-xsrf-guard") guard=val;
      }
    }
    END{
      if (token) printf("TOKEN=%s\n", token);
      if (guard) printf("GUARD=%s\n", guard);
    }' "$hdr" || true)

  eval "$out" || true
  if [[ -z "${TOKEN:-}" || -z "${GUARD:-}" ]]; then
    echo "!! 未从响应中解析到 CSRF Cookie，检查 Lua 过滤器是否生效或是否命中过滤链。"
    echo "响应头预览："; head -n 50 "$hdr"
    exit 1
  fi

  COOKIE_HEADER="${TOKEN_COOKIE}=${TOKEN}; ${GUARD_COOKIE}=${GUARD}"
  echo "# 已获取 Cookie: ${COOKIE_HEADER}"
}

extract_rl_headers() {
  local LIMIT REMAIN RESET RLED
  LIMIT=$(grep -i '^x-ratelimit-limit:' "$hdr" 2>/dev/null | head -n1 | awk '{print $2}' | tr -d '\r' || true)
  REMAIN=$(grep -i '^x-ratelimit-remaining:' "$hdr" 2>/dev/null | head -n1 | awk '{print $2}' | tr -d '\r' || true)
  RESET=$(grep -i '^x-ratelimit-reset:' "$hdr" 2>/dev/null | head -n1 | awk '{print $2}' | tr -d '\r' || true)
  RLED=$(grep -i '^x-envoy-ratelimited:' "$hdr" 2>/dev/null | head -n1 | awk '{print $2}' | tr -d '\r' || true)
  printf "limit=%s remaining=%s reset=%s ratelimited=%s" "${LIMIT:--}" "${REMAIN:--}" "${RESET:--}" "${RLED:-no}"
}

do_request() {
  local with_header="$1"  # yes/no
  local url="${BASE_URL}${LOGIN_PATH}"
  rm -f "$hdr"

  if [[ "$with_header" == "yes" ]]; then
    CODE=$(curl "${CURL_COMMON[@]}" -X "$METHOD" \
      -H "Content-Type: ${CONTENT_TYPE}" \
      -H "Cookie: ${COOKIE_HEADER}" \
      -H "${TOKEN_HEADER}: ${TOKEN}" \
      --data "$DATA_PAYLOAD" \
      -D "$hdr" -o /dev/null -w "%{http_code}" \
      "$url")
  else
    CODE=$(curl "${CURL_COMMON[@]}" -X "$METHOD" \
      -H "Content-Type: ${CONTENT_TYPE}" \
      -H "Cookie: ${COOKIE_HEADER}" \
      --data "$DATA_PAYLOAD" \
      -D "$hdr" -o /dev/null -w "%{http_code}" \
      "$url")
  fi

  printf "%s code=%s " "$(date '+%H:%M:%S')" "${CODE}"
  extract_rl_headers
  printf "\n"
}

# 1) 构造登录请求体
build_data
echo "# 登录请求体: ${DATA_PAYLOAD}"

# 2) 预热拿 Cookie
warm_set_cookies

# 3) 负例：不带 xsrf-token 头（应 403）
echo "# 负例：不带 XSRF 头，预期 403"
do_request "no"

# 4) 正例：带齐 Cookie + xsrf-token，循环观察限流头
echo "# 正例：带齐 Cookie 与 XSRF 头，开始压测以观测限流头"
for i in $(seq 1 "${COUNT}"); do
  printf "#%02d " "$i"
  do_request "yes"
  sleep "${INTERVAL}"
done
