Files
wanghu 6d7d1c9d90
build / build-push (push) Failing after 11s
修改
2026-09-14 08:48:10 +08:00

126 lines
8.1 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# CampusNotice 接口 curl 测试脚本 v2
# 用法: ./api-curl-test.sh [BASE] [PLATFORM]
# BASE 默认 http://localhost:8101
# PLATFORM 默认 manage(CAS 仅拦 /api/* 与 /mobiapi/*,manage 为匿名通道;生产环境应封死,见安全提醒)
# 注意:中文 JSON 体必须走 UTF-8 文件(--data-binary @file),
# 直接 -d '中文' 会被 Git Bash→curl.exe 的 argv 转换变成 GBK,服务端报
# Invalid UTF-8 start byte(HttpMessageNotReadable → code=6),属测试工具问题。
BASE="${1:-http://localhost:8101}"
PF="${2:-manage}"
U="$BASE/$PF"
TMPB="$(dirname "$0")/.curl-body.json"
PASS=0; BIZ=0; FAIL=0
CREATED_IDS=()
req() { # req 名称 方法 路径 [json体]
local name="$1" method="$2" path="$3" body="$4"
local args=(-s --max-time 15 -w "\n%{http_code}" -H "Accept: application/json")
if [ -n "$body" ]; then
printf '%s' "$body" > "$TMPB" # UTF-8 原样字节落盘
args+=(-X POST -H "Content-Type: application/json; charset=utf-8" --data-binary "@$(cygpath -w "$TMPB" 2>/dev/null || echo "$TMPB")")
elif [ "$method" = "POST" ]; then
args+=(-X POST)
fi
local out; out=$(curl "${args[@]}" "$U$path" 2>/dev/null)
local http="${out##*$'\n'}"; local json="${out%$'\n'*}"
local parsed; parsed=$(node -e "
try{const j=JSON.parse(process.argv[1]);
const d=j.data;
const ds=d===null||d===undefined?'null':Array.isArray(d)?'array['+d.length+']':typeof d==='object'?'{'+Object.keys(d).slice(0,4).join(',')+'}':String(d).slice(0,30);
console.log([j.code,(j.msg||'').slice(0,46),ds].join('\u0001'));
}catch(e){console.log(['-','-','-'].join('\u0001'))}" "$json" 2>/dev/null)
local code msg data
code=$(echo "$parsed" | cut -d$'\001' -f1)
msg=$(echo "$parsed" | cut -d$'\001' -f2)
data=$(echo "$parsed" | cut -d$'\001' -f3)
local st
if [ "$code" = "0" ]; then PASS=$((PASS+1)); st="✅PASS";
elif [ "$code" = "-" ] || [ "$http" != "200" ]; then FAIL=$((FAIL+1)); st="❌FAIL";
else BIZ=$((BIZ+1)); st="🟡BIZ"; fi
printf "%-26s | HTTP %s | code=%-3s | msg=%-46s | data=%s\n" "$name" "$http" "$code" "$msg" "$data"
}
extract_id() { # 从最近一次输出无法跨函数取值,改为调用方直接用 node 从 curl 结果提取
node -e "try{console.log(JSON.parse(require('fs').readFileSync(process.argv[1],'utf8')).data ?? '')}catch(e){console.log('')}" "$1" 2>/dev/null
}
echo "================ CampusNotice curl 矩阵 (BASE=$BASE PF=$PF) ================"
echo "---- A. 静态(直连 BASE,不经 platform 前缀) ----"
for p in "/" "/api-test.html"; do
http=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "$BASE$p")
if [ "$http" = "200" ]; then PASS=$((PASS+1)); printf "%-26s | HTTP %s\n" "静态 $p" "$http"; else FAIL=$((FAIL+1)); printf "%-26s | HTTP %s ❌\n" "静态 $p" "$http"; fi
done
http=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "$BASE/api/notice/Statis")
if [ "$http" = "302" ]; then PASS=$((PASS+1)); printf "%-26s | HTTP 302 → CAS 登录墙(符合预期)\n" "/api 登录墙对照"; else FAIL=$((FAIL+1)); printf "%-26s | HTTP $http ❌(预期302)\n" "/api 登录墙对照"; fi
echo "---- B. 平台/基础(匿名语义) ----"
req "GetUserInfo" GET "/base/GetUserInfo"
req "GetUserMod(匿名预期拒)" GET "/base/GetUserMod"
req "GetSchoolAll" GET "/base/GetSchoolAll"
req "GetGroupUser(未接入桩)" GET "/base/GetGroupUser?gid=1&role=2"
echo "---- C. 通知查询 ----"
req "notice/List" GET "/notice/List?pageIndex=1&pageSize=3"
req "notice/SendList" GET "/notice/SendList?pageIndex=1&pageSize=3&status=1&scope=user"
req "notice/Statis" GET "/notice/Statis"
req "notice/GetNextPrev" GET "/notice/GetNextPrev?serid=1&type=0"
req "notice/DraftList" GET "/notice/DraftList?pageIndex=1&pageSize=3"
req "notice/ApproverSuggest" GET "/notice/ApproverSuggest"
req "ApprovalList(pending)" GET "/notice/ApprovalList?auditState=pending&pageIndex=1&pageSize=3"
req "ApprovalList(reviewed)" GET "/notice/ApprovalList?auditState=reviewed&pageIndex=1&pageSize=3"
echo "---- D. 推送范围(匿名预期拒) ----"
req "notice/ScopeTree" GET "/notice/ScopeTree"
req "notice/ScopePreview" GET "/notice/ScopePreview?scopes=%5B%7B%22scopeType%22%3A1%2C%22scopeId%22%3A0%2C%22scopeName%22%3A%22%E5%85%A8%E6%A0%A1%22%7D%5D"
echo "---- E. 写链路(UTF-8 文件体,测后自清理) ----"
printf '%s' '{"title":"【测试】curl直发","content":"<p>curl</p>","type":1,"deptId":"1","deptName":"校长室","topmost":0,"receiveList":"ALL","fileIds":"","timingSendTime":null,"smsFlag":0,"receiptFlag":1,"publishType":"direct"}' > "$TMPB"
resp=$(curl -s --max-time 15 -X POST -H "Content-Type: application/json; charset=utf-8" --data-binary "@$(cygpath -w "$TMPB" 2>/dev/null || echo "$TMPB")" "$U/notice/Create")
echo "$resp" > "$TMPB.out"
ID_DIRECT=$(extract_id "$TMPB.out")
if [ -n "$ID_DIRECT" ]; then PASS=$((PASS+1)); printf "%-26s | code=0 | id=%s ✅\n" "Create(direct)" "$ID_DIRECT"; else FAIL=$((FAIL+1)); printf "%-26s | ❌ 未返回id\n" "Create(direct)"; fi
CREATED_IDS+=("$ID_DIRECT")
printf '%s' '{"title":"【测试】curl草稿","content":"<p>curl</p>","type":1,"deptId":"1","deptName":"校长室","topmost":0,"receiveList":"ALL","fileIds":"","timingSendTime":null,"smsFlag":0,"receiptFlag":1}' > "$TMPB"
resp=$(curl -s --max-time 15 -X POST -H "Content-Type: application/json; charset=utf-8" --data-binary "@$(cygpath -w "$TMPB" 2>/dev/null || echo "$TMPB")" "$U/notice/SaveDraft")
echo "$resp" > "$TMPB.out"
ID_DRAFT=$(extract_id "$TMPB.out")
if [ -n "$ID_DRAFT" ]; then PASS=$((PASS+1)); printf "%-26s | code=0 | id=%s ✅\n" "SaveDraft" "$ID_DRAFT"; else FAIL=$((FAIL+1)); printf "%-26s | ❌ 未返回id\n" "SaveDraft"; fi
CREATED_IDS+=("$ID_DRAFT")
if [ -n "$ID_DRAFT" ]; then
# Submit 新契约(多步):steps 优先;匿名/无学校身份时预期 code=2(需登录态经 /api 或 manage+学校身份)
printf '%s' "{\"serid\":$ID_DRAFT,\"steps\":[{\"name\":\"校级审核\",\"vote\":\"any\",\"approvers\":[\"lijing\"]}],\"opinion\":\"请审批\"}" > "$TMPB"
resp=$(curl -s --max-time 15 -X POST -H "Content-Type: application/json; charset=utf-8" --data-binary "@$(cygpath -w "$TMPB" 2>/dev/null || echo "$TMPB")" "$U/notice/Submit")
code=$(node -e "try{console.log(JSON.parse(process.argv[1]).code)}catch(e){console.log('-')}" "$resp")
if [ "$code" = "0" ]; then PASS=$((PASS+1)); printf "%-26s | code=0 | 草稿→待审批(第1步激活) ✅\n" "Submit(steps)"; else BIZ=$((BIZ+1)); printf "%-26s | code=%s 🟡 (匿名无学校身份为预期)\n" "Submit(steps)" "$code"; fi
fi
req "Approve(匿名预期拒)" POST "/notice/Approve?serid=${ID_DRAFT:-0}&opinion=x"
req "Reject(匿名预期拒)" POST "/notice/Reject?serid=${ID_DRAFT:-0}&opinion=x"
echo "---- F. 其他模块 ----"
req "dict/ManageList" GET "/dict/ManageList"
req "template/Typelist" GET "/template/Typelist"
req "contacts/GetGroup" GET "/contacts/GetGroup"
req "sms/GetSchool" GET "/sms/GetSchool"
echo "---- G. 附件 ----"
f="$(dirname "$0")/.curl-upload-sample.txt"; echo "curl upload sample $(date +%s)" > "$f"
req "base/FileUpload" POST "/base/FileUpload" "" "file=@$(cygpath -w "$f" 2>/dev/null || echo "$f")"
rm -f "$f"
echo "---- H. 清理测试数据 ----"
if [ "${#CREATED_IDS[@]}" -gt 0 ]; then
ids=$(IFS=,; echo "${CREATED_IDS[*]}")
printf '%s' "[$ids]" > "$TMPB"
resp=$(curl -s --max-time 15 -X POST -H "Content-Type: application/json; charset=utf-8" --data-binary "@$(cygpath -w "$TMPB" 2>/dev/null || echo "$TMPB")" "$U/notice/Delete")
code=$(node -e "try{console.log(JSON.parse(process.argv[1]).code)}catch(e){console.log('-')}" "$resp")
if [ "$code" = "0" ]; then PASS=$((PASS+1)); printf "%-26s | code=0 | ids=[$ids] 已清理 ✅\n" "Delete清理"; else FAIL=$((FAIL+1)); printf "%-26s | code=%s ❌\n" "Delete清理" "$code"; fi
fi
rm -f "$TMPB" "$TMPB.out"
echo "================ 统计: PASS=$PASS BIZ(业务拒绝/环境预期)=$BIZ FAIL=$FAIL ================"
echo "提醒: /manage 匿名可访问全部业务接口——CAS 仅拦 /api/* 与 /mobiapi/*,生产环境务必封死(安全项)。"