# 【Laravel】部署在 SLB 或 Nginx 後面，要根據實際使用者請求是 HTTP 或 HTTPS

> 在 Laravel 中，當應用被部署在 **SLB 或 Nginx 後面**，要根據實際使用者請求是 HTTP 或 HTTPS，讓 Laravel 正確產生資源（asset/url）的協定 (`http://` 或 `https://`)，**同時支援兩種不同呼叫來源**（SLB 代理或 client 直連）。

---

## ✅ 關鍵目標：

Laravel 要根據 **實際瀏覽器請求的協定**（**而不是內部或 SLB 連線的協定**）來產生正確的資源連結。

---

## 🧠 為什麼 Laravel 判斷會錯？

當你部署在 **SLB 或 Nginx 反向代理**後面時，Laravel 實際收到的請求是從 SLB 傳來的，Laravel 預設只看：

```php
$_SERVER['HTTPS'] // on or off

```

這時它會誤以為是 HTTP，而不是使用者原本的 HTTPS。

---

## ✅ 正確作法：三步驟搞定 HTTP/HTTPS 自動判斷

---

### ✅ 步驟 1：設定 Laravel 的 TrustProxies

#### `app/Http/Middleware/TrustProxies.php`

```php
use Illuminate\Http\Request;
use Illuminate\Http\Middleware\TrustProxies as Middleware;

class TrustProxies extends Middleware
{
   protected $proxies = '*'; // 或指定你的 proxy IP

   // protected $headers = Request::HEADER_X_FORWARDED_ALL; // 此為舊方法已廢棄感用以下預設
  
   protected $headers =
        Request::HEADER_X_FORWARDED_FOR |
        Request::HEADER_X_FORWARDED_HOST |
        Request::HEADER_X_FORWARDED_PORT |
        Request::HEADER_X_FORWARDED_PROTO |
        Request::HEADER_X_FORWARDED_AWS_ELB;
}

```

---

### ✅ 步驟 2：讓 SLB 或 Nginx 傳遞 `X-Forwarded-Proto`

#### 📌 Nginx 範例（很關鍵）：

```nginx
location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;  # ⭐ 告訴 Laravel 真正協定是 http or https
}

```

#### 📌 AWS ALB / 阿里雲 SLB 也會自動加上 `X-Forwarded-Proto`，你只需要 Laravel 信任它即可（Step 1）

---

### ✅ 步驟 3：確認 `.env` 有設 APP\_URL（給 CLI 用）

```env
APP_URL=https://your-domain.com

```

Laravel CLI 執行時（如：`php artisan queue:work`）沒有 request context，會 fallback 使用 `APP_URL`。

---

## 🔍 驗證

在你的 Laravel 控制器或 middleware 中加這段：

```php
dd([
    'secure' => request()->isSecure(),
    'scheme' => request()->getScheme(),
    'url' => request()->fullUrl(),
]);

```

你應該會看到：

```php
[
  'secure' => true,
  'scheme' => 'https',
  'url' => 'https://your-domain.com/some/path'
]

```

或是在頁面上加上

```
 {{ request()->isSecure() ? 'HTTPS ✅' : 'HTTP ❌' }}
 <br>
 {{ url()->current() }}
 <br>
```

可以看到

[![image-1753348696262.png](https://bookstack.treemanou.com/uploads/images/gallery/2025-07/scaled-1680-/Pnl4rW1ATQlkG0UN-image-1753348696262.png)](https://bookstack.treemanou.com/uploads/images/gallery/2025-07/Pnl4rW1ATQlkG0UN-image-1753348696262.png)

如果前方沒有正確帶入(nginx 前面還有SLB)，可以手動寫死

```Nginx
proxy_set_header X-Forwarded-Proto https;
```

---

## ✅ 小結：Laravel 正確產生 HTTP 或 HTTPS 協定連結的條件

<table id="bkmrk-%E9%A0%85%E7%9B%AE-%E8%AA%AA%E6%98%8E-trustproxies-%E8%A8%AD"><thead><tr><th>項目</th><th>說明</th></tr></thead><tbody><tr><td>`TrustProxies` 設定</td><td>必須設為 `*` + `HEADER_X_FORWARDED_ALL`</td></tr><tr><td>Proxy 傳 `X-Forwarded-Proto`</td><td>Nginx / SLB 必須傳遞使用者實際協定</td></tr><tr><td>`.env` 的 `APP_URL`</td><td>CLI 模式需 fallback 使用，請設為 `https://...`</td></tr><tr><td>使用 Laravel 的 `asset()`, `url()`, `route()`</td><td>Laravel 會根據協定正確產生 URL</td></tr></tbody></table>

---