HTTP/HTTPS Debugging噩夢:穿越Mixed Content地獄嘅24小時旅程
我花咗24個鐘debug點解我嘅React app喺HTTPS頁面不斷發HTTP requests——即使我嘅code已經喺convert佢哋。元兇令我震驚。
---
更新(2025年11月): STRAŦUM依家喺Private Alpha live喇!呢篇文提到嘅9-agent marketing platform正接受early testers。喺stratum.chandlernguyen.com申請access或者睇完整launch故事。
---
背景:Marketing Platform Journey繼續
記得9月嗰篇文我話我一邊瞓午覺一邊speed-run一個10-agent marketing platform?四個禮拜入面,3個working agents,target 10月/11月做alpha launch。
好喇,依家係10月尾。係時候progress update。
好消息:
- 個platform終於有名喇:STRAŦUM(Intelligence Over Execution)
- 完整嘅brand guidelines同design system(原來branding比寫code仲耐)
- 9個(10個入面)agents build好同integrated
- Multi-tenant architecture actually working
- Final stage:準備pre-alpha、invitation-only testing
Reality Check:
放假8日之後,我病咗10日(我知life happens。)呢個令所有嘢pause同shift咗我嘅timeline。所以10月launch唔到喇,係唔係?
但係solo development有件嘢好嘅:你控制pace。冇壓力逼你喺未ready嘅時候ship。冇investors喺你頸後面呼氣。只係...build it right。
呢篇blog post係關於其中一個「build it right」嘅時刻,變成咗6個鐘嘅debugging marathon。因為就喺我病好返開始全速嘅時候,我嘅deployment platform決定有其他plans。
當AWS Down咗,Engineers Get Creative(有時後悔)
有啲嘢coding bootcamps唔會教你:有時你嘅deployment platform就咁...消失。唔係因為你做錯咩,而係因為AWS決定有widespread outage影響全球Vercel deployments。
我嗰個Monday就係咁開始嘅。我嘅production site down咗,Vercel show errors,而我腦入面只有一個想法:「我需要backup。Fast。」
Cloudflare Pages登場。我聽過好評。Great CDN、automatic deployments、simple setup。有咩可以出錯?
旁白:所有嘢。所有嘢都可以出錯。
太簡單嘅Switch
Migration到Cloudflare Pages出奇地smooth。Connect咗GitHub repo、set environment variables喺dashboard、push到main。三分鐘後:deployed。
「Wow,」我諗。「呢個幾乎太簡單喇。」
然後我打開production site。
```
Mixed Content: The page at 'https://my-site.com/...' was loaded over HTTPS,
but requested an insecure resource 'http://stratum-api.us-central1.run.app/...'
```
嗰種你意識到celebration太早嘅sinking feeling?係,就係嗰種。
問題:由HTTPS頁面發HTTP Calls
我嘅React app喺page本身loaded over HTTPS嘅情況下發HTTP requests到backend API。Browsers(rightfully)block呢個作為security risk。Mixed Content errors。每個API call都fail。
「But wait,」我同自己講,「我有ensureHttpsInProduction()喺我嘅code入面!佢supposed to自動convert HTTP到HTTPS!」
我check咗deployed bundle。Function喺度。Logic正確。Browser console show conversion喺happening。咁點解HTTP requests仲係getting through?
第一次Debugging嘗試:Environment Variable搜索
可能Cloudflare嘅environment variables冇being picked up?
```bash
# Checked Cloudflare Dashboard
VITE_API_URL=https://stratum-api.us-central1.run.app ✓
VITE_SUPABASE_URL=https://your-project.supabase.co ✓
```
全部HTTPS。全部正確。
我trigger咗rebuild。等。Deployed。打開site。
同一個error。仲係HTTP requests。
第二次嘗試:The Great Reimport
可能files冇用centralized嘅API_BASE_URL?
我花咗下一個鐘update 24個files,import from @/lib/api而唔係直接用import.meta.env.VITE_API_URL。每個make API calls嘅component都get咗treatment。
```typescript
// Before
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/v1/...`);
// After
import { API_BASE_URL } from '@/lib/api';
const response = await fetch(`${API_BASE_URL}/api/v1/...`);
```
Push。Deploy。等。
仲係broken。
到呢個point,我開始question我嘅人生choices。
Plot Twist:Git入面Missing嘅Files
But wait,仲有更差嘅。
當調查點解我嘅HTTPS enforcement唔work嘅時候,我發現咗一啲terrifying嘅嘢。包含ensureHttpsInProduction()嘅api.ts file根本唔喺我嘅Git repo入面。
authService.ts都唔喺。csvSanitizer.ts都唔喺。三個critical frontend files,就咁...唔見咗。
點解?.gitignore file有呢個:
```
# Python stuff
lib/
build/
dist/
```
對Python嚟講好reasonable,係唔係?但我嘅frontend utilities住喺apps/web/src/lib/。嗰個broad lib/ pattern唔小心ignore咗我成個frontend lib directory!
呢個代表:
1. Cloudflare係由repo build嘅(missing呢啲files)
2. 我嘅local development有呢啲files(locally work到冇問題)
3. 我完全唔知佢哋冇being tracked
Fix:
```diff
# .gitignore - Before
-lib/
# .gitignore - After
+apps/api/lib/ # Python-specific
+!apps/web/src/lib/ # Explicitly include frontend lib
```
加返missing files,commit,push。而家Cloudflare有HTTPS enforcement code喇!
但係...HTTP errors繼續。
第三次嘗試:Build-Time Validation
到呢個point,我question緊所有嘢。「You know what?」我諗。「如果呢件事keep happening,我需要PREVENT佢ever reaching production。」
我寫咗一個Vite plugin,如果detect到production入面有HTTP URLs就fail build:
```typescript
function validateProductionUrls(mode: string) {
if (mode !== 'production') return;
const apiUrl = process.env.VITE_API_URL || '';
if (apiUrl && apiUrl.trim().startsWith('http://')) {
if (!apiUrl.includes('localhost') && !apiUrl.includes('127.0.0.1')) {
throw new Error(
`❌ HTTPS ENFORCEMENT FAILED
Environment Variable: VITE_API_URL
Current Value: ${apiUrl}
This will cause Mixed Content errors in production!`
);
}
}
}
```
Genius,係唔係?而家deploy有HTTP URLs係IMPOSSIBLE嘅。
Deploy again。Build passed(environment variables係HTTPS)。Site loaded。
同一個。Damn。Error。
恍然大悟:Local Files被Deploy咗
夜晚(好夜),我有個realization。
我再check deployed JavaScript bundle。真正睇清楚。入面嘅URL係:
```javascript
"http://stratum-api.us-central1.run.app"
```
但我Cloudflare嘅environment variables係HTTPS。咁呢個HTTP URL係邊度嚟嘅?
然後hit到我喇。我嘅local .env.production file。
```bash
# apps/web/.env.production (LOCAL FILE)
VITE_API_URL=http://stratum-api.us-central1.run.app
```
Cloudflare Pages deploy咗我嘅local environment file而唔係用dashboard variables!
我check .cloudflare-pages-ignore:
```
# Environment files
.env
.env.local
.env.development
.env.test
# .env.production ← MISSING!
```
Face. Palm.
Fix:一行
```diff
# apps/web/.cloudflare-pages-ignore
.env
.env.local
.env.development
.env.test
+.env.production
```
Deploy。等。
呢次唔同error喇!Progress!
```
Access to fetch at 'https://stratum-api.us-central1.run.app/...'
from origin 'https://preview-xyz.stratum-marketing-suite.pages.dev'
has been blocked by CORS policy
```
CORS errors!靚到不得了嘅CORS errors!即係HTTPS work緊!
But Wait,仲有:Cache Conspiracy
修好CORS。Deploy again。打開我嘅custom domain。
HTTP errors again。
乜話?!
原來Cloudflare嘅CDN aggressive咁cache緊舊bundle。新deployment(有HTTPS)喺preview URL係live嘅,但我嘅custom domain serve緊cached content有HTTP URLs。
Cloudflare嘅cache purging需要:
1. 搵啱嘅zone settings(唔喺Pages dashboard入面)
2. Navigate through domain settings(唔obvious)
3. Manually purge cache(每次deployment都要)
經過幾個鐘debug HTTP/HTTPS issues之後,我做咗個決定。
返去Vercel:有時Boring係Better
AWS返嚟喇。Vercel又work喇。
我migrate所有嘢返去Vercel。點解?
1. Automatic cache invalidation - 唔使manual purging
2. 更簡單嘅environment variable handling - 你set咩就get咩
3. 更快debugging - 少啲infrastructure要reason about
4. Battle-tested - 我知佢嘅quirks
Vercel deployment用咗3分鐘。冇HTTP errors。冇cache issues。就咁...work。
我學到嘅(Hard Way)
1. 永遠喺Deployment Platforms Ignore .env.production
```
# .vercelignore
# .cloudflare-pages-ignore
# .netlify-ignore
.env
.env.local
.env.development
.env.test
.env.production ← 唔好忘記呢個
```
2. Monorepos入面Broad .gitignore Patterns好危險
```diff
# ❌ Bad - Ignores frontend AND backend lib folders
-lib/
-build/
-dist/
# ✅ Good - Specific to each context
+apps/api/lib/ # Python-specific
+apps/api/build/
+apps/api/dist/
+apps/web/dist/ # Vite output only
```
永遠要問:「呢個pattern會唔會accidentally ignore啲重要嘢?」
喺有多種語言(Python + TypeScript)嘅monorepo入面,為一個ecosystem designed嘅broad patterns可以accidentally ignore另一個嘅critical files。
3. Build-Time Validation仲係值得嘅
即使佢冇catch到local file issue,build-time validation prevent _未來_嘅misconfigurations:
```typescript
// vite.config.ts
export default defineConfig(({ mode }) => {
validateProductionUrls(mode);
return {
// ... config
};
});
```
4. Multi-Layer Defense Work
我哋最終嘅architecture有三層:
- Build-time:如果detect到HTTP URLs就fail build
- Runtime:如果page loaded over HTTPS就convert HTTP → HTTPS
- Deployment:排除local .env files
5. Preview URLs係你嘅朋友
永遠先test preview URL。如果嗰個work但你嘅custom domain唔work,通常係caching。
6. 了解你Platform嘅Quirks
- Vercel:Simple、auto-invalidate cache、environment variables「just work」
- Cloudflare Pages:Great CDN,但manual cache purging同更複雜嘅setup
救咗我嘅Code
以下係最終ensureHttpsInProduction() function:
```typescript
function ensureHttpsInProduction(url: string): string {
// Only convert in browser context when site is loaded over HTTPS
if (typeof window !== 'undefined' && window.location.protocol === 'https:') {
// Don't convert localhost/127.0.0.1 URLs (local development)
if (url.startsWith('http://') &&
!url.includes('localhost') &&
!url.includes('127.0.0.1')) {
console.warn('[API] Converting HTTP to HTTPS:', url);
return url.replace('http://', 'https://');
}
}
return url;
}
```
同vite.config.ts入面嘅build-time validation:
```typescript
function validateProductionUrls(mode: string) {
if (mode !== 'production') return;
const apiUrl = process.env.VITE_API_URL || '';
// Check for HTTP (should be HTTPS)
if (apiUrl && apiUrl.trim().startsWith('http://')) {
if (!apiUrl.includes('localhost') && !apiUrl.includes('127.0.0.1')) {
throw new Error(`
❌ HTTPS ENFORCEMENT FAILED
Environment Variable: VITE_API_URL
Current Value: ${apiUrl}
Mixed Content Error Prevention:
Browsers block HTTP requests from HTTPS pages.
Fix: Update environment variables to use HTTPS URLs.
`);
}
}
}
```
真正嘅Lesson:Debugging係偵探工作
呢個唔係coding problem。呢個係configuration考古expedition。
真正嘅bugs係:
1. ✅ Broad .gitignore patterns ignore critical frontend files
2. ✅ .cloudflare-pages-ignore入面missing .env.production
3. ✅ Aggressive CDN caching masking fix
4. ✅ Assume environment variable precedence
技術solution係一個.ignore file入面嘅一行。
Debugging?用咗6個鐘、14次deployments、同太多咖啡。
值唔值得?
Absolutely。以下係我gain到嘅:
1. 深入理解 Mixed Content security policies
2. Build-time validation prevent未來issues
3. Multi-layer HTTPS enforcement platform-agnostic
4. 真正appreciate Vercel嘅simplicity
同最重要嘅:一個好正嘅debugging故事可以share。:P
Git Log講晒成個故事
```bash
2033b9a fix: add .env.production to .vercelignore
3555390 docs: migrate deployment documentation from Cloudflare Pages to Vercel
a4edb09 chore: force clean Cloudflare Pages rebuild
590c271 fix: enhance ensureHttpsInProduction logging
15d69c6 chore: force rebuild of UserProfile bundle
a1c345f fix: add .env.production to cloudflare-pages-ignore ← THE .ENV FIX
635d80d docs: update documentation for Cloudflare Pages migration
edfa611 feat: add build-time HTTPS enforcement
802c1e9 fix: enforce HTTPS for all API calls across frontend
26f6b87 refactor: comprehensive .gitignore audit and cleanup
3758a9c fix: unignore frontend lib directory and add missing files ← THE GITIGNORE FIX
```
每個commit代表舊世界入面一個鐘嘅debugging,但有Claude Code,感恩,我嘅速度快咗。一個hypothesis tested。一個lesson learned。
俾其他喺Fight Mixed Content Errors嘅Engineers
如果你讀緊呢個因為你debug緊同一個issue,呢度係你嘅checklist:
1. Check你嘅Environment Variables:
```bash
# Print actual values being used
console.log('API URL:', import.meta.env.VITE_API_URL);
```
2. Check你Deployed嘅Bundle:
```bash
# Download and search the JavaScript bundle
curl https://your-site.com/assets/index-ABC123.js | grep "http://"
```
3. Check你嘅Ignore Files:
```bash
# Make sure .env.production is excluded
cat .vercelignore
cat .cloudflare-pages-ignore
cat .netlify-ignore
```
4. Check你嘅.gitignore(Monorepos):
```bash
# Make sure critical files aren't being ignored
git ls-files apps/web/src/lib/ # Should show api.ts, etc.
# If empty, check for broad patterns
grep "^lib/" .gitignore # ❌ Too broad
grep "^apps/api/lib/" .gitignore # ✅ Specific
```
5. Check你嘅Cache:
```bash
# Test on preview URL first
# If preview works but production doesn't = cache issue
```
6. 加Build-Time Validation:
```typescript
// Prevent it from ever happening again
if (mode === 'production' && url.startsWith('http://')) {
throw new Error('HTTPS required in production!');
}
```
我希望我當時有嘅Migration Checklist
Switch deployment platforms嘅時候:
- [ ] List舊platform嘅ALL environment variables
- [ ] 先喺新platform SET environment variables
- [ ] 加ALL .env files入.ignore(including .env.production)
- [ ] Verify .gitignore冇ignore critical files(run git ls-files嚟check)
- [ ] 喺custom domain之前先test preview URL
- [ ] Check deployed bundle有冇HTTP URLs
- [ ] Verify CORS settings如果backend係separate嘅
- [ ] Document platform-specific quirks
仲喺寫Code、仲喺學、仲(有時)喺Break嘢
一行fix用咗六個鐘嘅debugging。呢個就係software engineering嘅essence。
我哋ship嘅code重要,冇錯。但我哋develop嘅debugging skills?嗰啲先係令我哋成為更好engineers嘅嘢。
下次我嘅deployment platform down(而且一定會有下次),我會ready。我有:
- ✅ Platform-agnostic HTTPS enforcement
- ✅ Build-time validation
- ✅ 更好理解environment variable precedence
- ✅ Backup deployment strategy
而hopefully,呢篇blog post會幫其他人慳返嗰6個鐘嘅幾個。:)
你有冇試過一個「一行fix」用咗你embarrassingly長嘅時間先搵到?我好想聽吓你嘅debugging偵探故事——misery loves company!
祝好,
Chandler





