Skip to content
··閱讀時間5分鐘

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

繼續閱讀

我嘅旅程
聯繫
語言
偏好設定