Panduan lengkap tentang menyiapkan proxy di Angular untuk panggilan API di belakang proxy perusahaan atau dengan otentikasi windows

Pengembang Angular menggunakan Angular CLI untuk pengembangan lokal. Salah satu kebutuhan paling umum adalah menyiapkan proxy di lingkungan pengembang lokal untuk menghindari kesalahan CORS saat aplikasi Angular mengirimkan permintaan HTTP ke API yang berada di domain berbeda. CLI Angular membuat prosesnya relatif mudah, tetapi bisa jadi rumit dalam beberapa kasus edge.

Pada artikel ini, saya akan membahas cara mengatur proxy server dev

Siapkan proxy untuk terhubung ke API di localhost

Dengan Angular CLI, kita dapat memulai server dev lokal menggunakan perintah di bawah ini.

ng serve

Perintah ini memanggil server dev internal berdasarkan server dev webpack. Secara default, server pengembang berjalan pada http://localhost:4200.

Saat aplikasi Angular perlu memanggil API backendnya, yang juga dihosting secara lokal di http://localhost:3000, maka kita akan menemui kesalahan CORS karena panggilan HTTP menggunakan asal yang berbeda (localhost:3000).

this.http.get('http://locahost:3000/api/')
    .subscribe(res => {...});

Masalah CORS dapat diatasi dengan mengonfigurasi proxy server dev Angular. Contoh konfigurasi proxy dapat dibuat di bawah

// proxy.conf.json
{
  "/api": {
    "target": "http://localhost:3000",
    "secure": false,
  }
}
// we change the angular http call to remove the domain prefix
this.http.get('/api/')
    .subscribe(res => {...});

Seperti yang diilustrasikan oleh diagram berikut, proxy berada di antara aplikasi Angular dan API backend dan menerjemahkan panggilan “api/v1” ke API backend. Kesalahan CORS tidak terjadi karena panggilan ke API berasal dari asal yang sama (localhost:4200/api) sekarang.

Agar konfigurasi proxy berlaku, konfigurasi tersebut harus diteruskan ke perintah ng serve.

ng serve --proxy-config proxy.conf.json

Atau kita bisa menambahkannya ke konfigurasi angular.json

"serve": {
  ...
  "options": {
    ...
    "proxyConfig": "proxy.conf.json"
  }
}

Hubungkan ke API eksternal di belakang Proksi perusahaan

Seringkali kami bekerja dalam jaringan perusahaan, dan aplikasi Angular di lingkungan pengembang lokal juga perlu terhubung ke API eksternal. Menggunakan contoh sebelumnya, kita mungkin perlu memanggil http://abc.company.com/api di aplikasi Angular alih-alih memanggil http://localhost:3000/api.

Mengakses API eksternal di belakang proksi perusahaan memerlukan variabel lingkungan HTTP_PROXY dan HTTPS_PROXY untuk dikonfigurasi. Jika proksi menggunakan sertifikat SSL, tanda secure perlu disetel ke false, untuk melewati verifikasi sertifikat.

Untuk menangani proxy perusahaan, kita perlu membuat proxy.conf.js seperti di bawah ini.

const HttpsProxyAgent = require('https-proxy-agent');

const proxyConfig = [
  {
    context: '/api',
    pathRewrite: { '^/api': '' },
    target: 'https://api.abc.com',
    changeOrigin: true,
    secure: false
  }
];

function setupForCorporateProxy(proxyConfig) {
  const proxyServer = process.env.http_proxy || process.env.HTTP_PROXY;

  if (proxyServer) {
    const agent = new HttpsProxyAgent(proxyServer);
    proxyConfig.forEach(c => {
      c.agent = agent;
    });
  }
  return proxyConfig;
}

module.exports = setupForCorporateProxy(proxyConfig);

Dalam contoh di atas, kami memproksi permintaan seperti api/v1/client ke server eksternal https://api.abc.com/v1/client. Ketika proxy perusahaan diperlukan, kami menyiapkan objek agen HTTPS di proxy berdasarkan variabel lingkungan HTTP_PROXY dan HTTPS_PROXY. Opsi secure:false ditambahkan untuk menangani sertifikat SSL khusus di proxy perusahaan.

Untuk menggunakan konfigurasi js baru untuk aplikasi Angular, jalankan perintah berikut

ng serve --proxy-config proxy.conf.js

Perlu dicatat bahwa ada dua jenis agen: HttpsProxyAgent dan HttpProxyAgent, perlu memilih yang sesuai berdasarkan pengaturan lingkungan.

Proxy ke API menggunakan otentikasi windows (IIS)

Otentikasi Windows banyak digunakan oleh banyak perusahaan yang mengandalkan Ekosistem Microsoft. Situasinya bisa menjadi rumit jika Aplikasi Angular terhubung ke layanan API yang dihosting dengan IIS yang dilindungi oleh otentikasi windows.

Masalah umumnya adalah panggilan dari aplikasi Angular ke API akan mengembalikan 401 saat menggunakan pengaturan proxy di lingkungan pengembang lokal.

Misalnya, /api/v1/../login adalah Titik Akhir yang dilindungi oleh Otentikasi Windows, permintaan ke API dari Aplikasi Angular yang berjalan secara lokal menerima 401 tanggapan tidak sah. Di bawah ini adalah tangkapan layar tab jaringan di alat pengembang Chrome.

Akar penyebab masalah ini adalah otentikasi windows berbasis koneksi, tetapi Proxy memutus koneksi tetap aktif.

Di bawah tenda otentikasi windows, ia menggunakan Kerberos atau NTLM, salah satu protokol akan memerlukan koneksi tetap hidup untuk menjaga status otentikasi.

Ketika /api/v1/../login dipanggil, browser mencoba membuat koneksi dengan server IIS melalui jabat tangan negosiasi NTLM yang mencakup 3 bagian. Yaitu pesan Tipe-1, Pesan Tipe-2, dan Pesan Tipe-3. Anda dapat menemukan rincian lebih lanjut tentang jabat tangan NTLM di sini. Anda mungkin sudah memperhatikan bahwa ada dua panggilan HTTP yang ditampilkan untuk permintaan yang sama pada gambar di atas. Itu adalah dua bagian pertama dari jabat tangan.

Karena permintaan tersebut diproksi secara lokal, 3 pesan jabat tangan dikirim dalam 3 permintaan (soket) terpisah melalui proksi, sehingga koneksi tetap aktif tidak dapat dipertahankan dalam prosesnya. Itulah alasan pesan terakhir tidak muncul.

Untuk memperbaiki masalah ini, Kita perlu mengkonfigurasi proxy untuk mempertahankan koneksi tunggal antara browser dan server IIS. Paketagentkeepalive dapat membantu kita mencapai tujuan ini. Konfigurasi proxy yang diperbarui ditunjukkan di bawah ini.

const Agent = require("agentkeepalive");

const keepaliveAgent = new Agent({
    maxSockets: 1,
    keepAlive: true,
    maxFreeSockets: 10,
    keepAliveMsecs: 1000,
    timeout: 60000,
    keepAliveTimeout: 30000 // free socket keepalive for 30 seconds
});

const PROXY_CONFIG = [
    {
        target: "http://localhost:3000",
        context: "/api",
        secure: false,
        changeOrigin: true,
        loglevel: "debug",
        agent: keepaliveAgent
    }
];
module.exports = PROXY_CONFIG;

Konfigurasi proxy yang diperbarui menyetel tanda maxSockets ke 1, keepAlive ke true, dan menyetel batas waktu menjadi 30 detik, yang merupakan waktu yang cukup lama untuk menyelesaikan jabat tangan. Konfigurasi ini bertujuan untuk membuat http.Agent menjaga koneksi tetap hidup antara browser dan server IIS melalui proxy dalam proses otentikasi.

Sekarang, permintaan API /api/v1/../login seharusnya berfungsi.

Di atas adalah log tab jaringan setelah otentikasi berhasil dengan konfigurasi baru. Kita dapat melihat tiga permintaan selama jabat tangan, dan yang terakhir mengembalikan status sukses HTTP 200.

Beberapa skema dalam satu header WWW-Otentikasi

Kemungkinan penyebab kesalahan otentikasi windows lainnya adalah header www-authenticate. Menurut RFC 7235, tidak apa-apa untuk memiliki beberapa skema otentikasi dalam satu bidang header www-authenticate, meskipun hal ini dapat membuat bidang tersebut sulit untuk diurai.

agen harus sangat berhati-hati dalam mengurai nilai bidang header WWW-
Authenticate atau Proxy-Authenticate jika berisi
lebih dari satu tantangan, atau jika lebih dari satu bidang
header WWW-Authenticate disediakan, karena konten tantangan itu sendiri
berisi daftar parameter autentikasi yang dipisahkan koma.

Kenyataannya adalah dukungan browser “dipertanyakan”. Di bawah ini adalah contoh header www-authenticate dengan dua skema.

WWW-Authenticate: Negotiate, NTLM

Beberapa browser mungkin tidak dapat menguraikan hal di atas dengan benar dan ini akan merusak proses jabat tangan NTLM. Untuk mengatasi masalah ini, kita dapat memanfaatkan callback proxyRes di http-proxy-middleware seperti di bawah ini

const onProxyRes = function (proxyRes, req, res) {
     var key = 'www-authenticate';
     proxyRes.headers[key] = proxyRes.headers[key] && proxyRes.headers[key].split(',');
};

// add it into the proxy config option
onProxyRes: onProxyRes

Konfigurasi proxy lengkapnya terlihat seperti di bawah ini.

const Agent = require("agentkeepalive");

const keepaliveAgent = new Agent({
    maxSockets: 1,
    keepAlive: true,
    maxFreeSockets: 10,
    keepAliveMsecs: 1000,
    timeout: 60000,
    keepAliveTimeout: 30000 // free socket keepalive for 30 seconds
});
const onProxyRes = function (proxyRes, req, res) {
     var key = 'www-authenticate';
     proxyRes.headers[key] = proxyRes.headers[key] && proxyRes.headers[key].split(',');
};
const PROXY_CONFIG = [
    {
        target: "http://localhost:3000",
        context: "/api",
        secure: false,
        changeOrigin: true,
        onProxyRes: onProxyRes,
        agent: keepaliveAgent
    }
];
module.exports = PROXY_CONFIG;

Dengan tambahan panggilan balik baru, beberapa skema di header www-authenticate akan dikirim dalam beberapa baris, dan jabat tangan negosiasi NTLM akan dapat dilanjutkan.

// From the original response header
www-authenticate: Negotiate, NTLM

// After the onProxRes callback function
www-authenticate: ['Negotiate', 'NTLM']

// It is equivalent to
< WWW-Authenticate: Negotiate
< WWW-Authenticate: NTLM

Ringkasan

Pada artikel ini, kami membahas cara menghindari masalah CORS dengan menyiapkan proxy menggunakan Angular CLI untuk pengembangan lokal. Saya harap ini berguna bagi Anda jika Anda sedang mengerjakan Angular di belakang proxy perusahaan dan/atau menggunakan IIS dengan otentikasi windows.

Selamat pemrograman!

Konten lainnya di PlainEnglish.io.

Daftar ke buletin mingguan gratis kami. Ikuti kami di "Twitter", "LinkedIn", "YouTube", dan "Discord" .

Tertarik untuk meningkatkan skala startup perangkat lunak Anda? Lihat "Sirkuit".