Panduan Node.js, Bagian 8: Protokol HTTP dan WebSocket

Node.js adalah platform server. Tugas utama server adalah untuk memproses permintaan dari klien, khususnya, dari browser, secepat dan seefisien mungkin. Terjemahan kedelapan dari tutorial Node.js yang kami terbitkan hari ini adalah tentang HTTP dan WebSocket.




Apa yang terjadi ketika membuat permintaan HTTP?


Mari kita bicara tentang bagaimana browser membuat permintaan ke server menggunakan protokol HTTP / 1.1.

Jika Anda pernah memiliki wawancara di bidang TI, maka Anda mungkin akan ditanya apa yang terjadi ketika Anda mengetik sesuatu di bilah alamat browser Anda dan tekan Enter. Mungkin ini adalah salah satu pertanyaan paling populer yang terjadi pada wawancara semacam itu. Siapa pun yang mengajukan pertanyaan seperti itu ingin tahu apakah Anda dapat menjelaskan beberapa konsep yang cukup sederhana dan mencari tahu apakah Anda memahami prinsip-prinsip Internet.

Pertanyaan ini menyentuh banyak teknologi, untuk memahami prinsip-prinsip umum yang berarti memahami bagaimana salah satu sistem paling rumit yang pernah dibangun oleh umat manusia dibangun, yang mencakup seluruh dunia.

▍ Protokol HTTP


Browser modern dapat membedakan URL asli yang dimasukkan ke dalam bilah alamat mereka dari permintaan pencarian, untuk pemrosesan yang biasanya digunakan oleh mesin pencari standar. Kami akan berbicara tentang URL. Jika Anda memasukkan alamat situs web, seperti flaviocopes.com , ke dalam baris peramban, peramban mengonversi alamat ini ke formulir http://flaviocopes.com , berdasarkan asumsi bahwa protokol HTTP akan digunakan untuk bertukar data dengan sumber daya yang ditentukan. Harap dicatat bahwa pada Windows, apa yang akan kita bicarakan di sini mungkin terlihat sedikit berbeda dari pada macOS dan Linux.

▍ Fase pencarian DNS


Jadi, browser, mulai bekerja mengunduh data dari alamat yang diminta oleh pengguna, melakukan operasi Pencarian DNS (Pencarian DNS) untuk mengetahui alamat IP dari server terkait. Nama simbolis dari sumber daya yang dimasukkan di bilah alamat nyaman untuk orang, tetapi perangkat Internet menyiratkan kemungkinan pertukaran data antara komputer menggunakan alamat IP, yang merupakan kumpulan angka seperti 222.324.3.1 (untuk IPv4).

Pertama, mencari tahu alamat IP server, browser melihat ke cache DNS lokal untuk melihat apakah prosedur serupa telah dilakukan baru-baru ini. Di browser Chrome, misalnya, ada cara mudah untuk melihat cache DNS dengan memasukkan alamat berikut di bilah alamat: chrome://net-internals/#dns .

Jika tidak ada yang dapat ditemukan di cache, browser menggunakan panggilan sistem gethostbyname POSIX untuk mengetahui alamat IP server.

▍ fungsi gethostbyname


Fungsi gethostbyname pertama-tama memeriksa hosts , yang, pada macOS atau Linux, dapat ditemukan di /etc/hosts untuk mencari tahu apakah informasi lokal dapat ditemukan dengan mencari tahu alamat server.

Jika lokal berarti menyelesaikan permintaan untuk mengetahui alamat IP server gagal, sistem melakukan permintaan ke server DNS. Alamat server tersebut disimpan dalam pengaturan sistem.

Berikut adalah beberapa server DNS populer:

  • 8.8.8.8: Server Google DNS.
  • 1.1.1.1: Server CloudFlare DNS.

Kebanyakan orang menggunakan server DNS yang disediakan oleh penyedia mereka. Browser melakukan permintaan DNS menggunakan protokol UDP.

TCP dan UDP adalah dua protokol dasar yang digunakan dalam jaringan komputer. Mereka berada pada level konseptual yang sama, tetapi TCP adalah protokol berorientasi koneksi, dan untuk pertukaran pesan UDP, pemrosesan yang menciptakan beban tambahan kecil pada sistem, prosedur pembentukan koneksi tidak diperlukan. Kami tidak akan berbicara tentang bagaimana pertukaran data dengan UDP.

Alamat IP yang sesuai dengan nama domain yang menarik bagi kami mungkin ada dalam cache server DNS. Jika ini bukan masalahnya, ia akan menghubungi server DNS root. Sistem DNS root server terdiri dari 13 server, di mana pengoperasian seluruh Internet tergantung.

Perlu dicatat bahwa root DNS server tidak mengetahui korespondensi antara semua nama domain dan alamat IP yang ada di dunia. Tetapi server yang sama mengetahui alamat server DNS tingkat atas untuk domain seperti .com, .it, .pizza, dan sebagainya.

Setelah menerima permintaan, root DNS server mengarahkan ulang ke server DNS dari domain tingkat atas, ke server TLD (dari Top-Level Domain).

Misalkan browser sedang mencari alamat IP untuk server flaviocopes.com . Beralih ke root DNS server, browser akan menerima alamat server TLD untuk zona .com darinya. Sekarang alamat ini akan disimpan dalam cache, sebagai hasilnya, jika Anda perlu mengetahui alamat IP dari URL lain dari zona .com, Anda tidak perlu menghubungi server DNS root lagi.

Server TLD memiliki alamat IP server nama (Name Server, NS), dengan bantuan yang Anda dapat mengetahui alamat IP dari URL yang kami miliki. Di mana server NS mendapatkan informasi ini? Faktanya adalah bahwa jika Anda membeli domain, pendaftar domain mengirimkan data tentangnya ke server nama. Prosedur serupa dilakukan, misalnya, ketika mengubah hosting.

Server yang dimaksud biasanya dimiliki oleh penyedia hosting. Sebagai aturan, untuk melindungi dari kegagalan, beberapa server dibuat. Misalnya, mereka mungkin memiliki alamat ini:

  • ns1.dreamhost.com
  • ns2.dreamhost.com
  • ns3.dreamhost.com

Untuk mengetahui alamat IP dengan URL, pada akhirnya, mereka beralih ke server tersebut. Mereka menyimpan data aktual tentang alamat IP.

Sekarang, setelah kami berhasil menemukan alamat IP di belakang URL yang dimasukkan di bilah alamat browser, kami beralih ke langkah selanjutnya dari pekerjaan kami.

▍ Membuat koneksi TCP


Setelah mempelajari alamat IP server, klien dapat memulai koneksi TCP ke sana. Dalam proses membangun koneksi TCP, klien dan server mengirimkan satu sama lain beberapa data layanan, setelah itu mereka dapat bertukar informasi. Ini berarti bahwa setelah koneksi dibuat, klien akan dapat mengirim permintaan ke server.

▍Mengirim permintaan


Permintaan adalah fragmen teks yang disusun sesuai dengan aturan protokol yang digunakan. Ini terdiri dari tiga bagian:

  • String kueri
  • Minta tajuk.
  • Meminta badan.

String kueri


String kueri adalah string teks tunggal yang berisi informasi berikut:

  • Metode HTTP.
  • Alamat Sumber Daya
  • Versi protokol.

Mungkin terlihat, misalnya, seperti ini:

 GET / HTTP/1.1 

Minta tajuk


Header permintaan diwakili oleh seperangkat : . Ada 2 bidang header yang diperlukan, salah satunya adalah Host dan yang kedua adalah Connection . Kolom yang tersisa adalah opsional.

Judulnya mungkin terlihat seperti ini:

 Host: flaviocopes.com Connection: close 

Bidang Host menunjukkan nama domain yang diminati browser. Bidang Connection , diatur ke close , berarti koneksi antara klien dan server tidak perlu tetap terbuka.

Header permintaan yang umum digunakan meliputi:

  • Origin
  • Accept
  • Accept-Encoding
  • Cookie
  • Cache-Control
  • Dnt

Padahal, masih banyak lagi.

Header permintaan berakhir dengan string kosong.

Meminta badan


Badan permintaan bersifat opsional, tidak digunakan dalam permintaan GET. Badan permintaan digunakan dalam permintaan POST, serta dalam permintaan lainnya. Ini mungkin berisi, misalnya, data dalam format JSON.

Karena sekarang kita berbicara tentang permintaan GET, badan permintaan akan kosong, kami tidak akan bekerja dengannya.

▍ Jawab


Setelah server menerima permintaan yang dikirim oleh klien, ia memprosesnya dan mengirimkan respons kepada klien.

Respons dimulai dengan kode status dan pesan yang sesuai. Jika permintaan berhasil, awal respons akan terlihat seperti ini:

 200 OK 

Jika ada kesalahan, mungkin ada kode lain. Misalnya, berikut ini:

  • 404 Not Found
  • 403 Forbidden
  • 301 Moved Permanently
  • 500 Internal Server Error
  • 304 Not Modified
  • 401 Unauthorized

Selanjutnya, respons berisi daftar tajuk HTTP dan isi respons (yang, karena permintaan dieksekusi oleh browser, akan berupa kode HTML).

Penguraian HTML


Setelah browser menerima respons dari server, yang bodinya berisi kode HTML, ia mulai menguraikannya, mengulangi proses di atas untuk setiap sumber daya yang diperlukan untuk membentuk halaman. Sumber daya tersebut meliputi, misalnya, yang berikut:

  • File CSS.
  • Gambar
  • Ikon halaman web (favicon).
  • File JavaScript.

Bagaimana tepatnya browser menampilkan halaman tidak berlaku untuk percakapan kami. Hal utama yang menarik bagi kami di sini adalah bahwa proses meminta dan menerima data di atas digunakan tidak hanya untuk kode HTML, tetapi juga untuk objek lain yang ditransfer dari server ke browser menggunakan protokol HTTP.

Tentang membuat server sederhana menggunakan Node.js


Sekarang, setelah kami memeriksa proses interaksi antara browser dan server, Anda dapat melihat segar di bagian aplikasi First Node.js dari bagian pertama dari rangkaian materi ini, di mana kami menggambarkan kode untuk server sederhana.

Membuat permintaan HTTP dengan Node.js


Untuk melakukan permintaan HTTP menggunakan Node.js, modul yang sesuai digunakan . Contoh di bawah ini menggunakan modul https . Faktanya adalah bahwa dalam kondisi modern, bila memungkinkan, perlu untuk menggunakan protokol HTTPS.

▍ Mengeksekusi permintaan GET


Berikut adalah contoh menjalankan permintaan GET menggunakan Node.js:

 const https = require('https') const options = { hostname: 'flaviocopes.com', port: 443, path: '/todos', method: 'GET' } const req = https.request(options, (res) => { console.log(`statusCode: ${res.statusCode}`) res.on('data', (d) => {   process.stdout.write(d) }) }) req.on('error', (error) => { console.error(error) }) req.end() 

▍POST eksekusi permintaan


Berikut cara membuat permintaan POST dari Node.js:

 const https = require('https') const data = JSON.stringify({ todo: 'Buy the milk' }) const options = { hostname: 'flaviocopes.com', port: 443, path: '/todos', method: 'POST', headers: {   'Content-Type': 'application/json',   'Content-Length': data.length } } const req = https.request(options, (res) => { console.log(`statusCode: ${res.statusCode}`) res.on('data', (d) => {   process.stdout.write(d) }) }) req.on('error', (error) => { console.error(error) }) req.write(data) req.end() 

▍PUT dan HAPUS pertanyaan


Eksekusi permintaan seperti itu terlihat sama dengan eksekusi permintaan POST. Perbedaan utama, selain konten semantik dari operasi tersebut, adalah nilai properti method dari objek options .

▍ Melakukan permintaan HTTP di Node.js menggunakan perpustakaan Axios


Axios adalah pustaka JavaScript yang sangat populer yang berfungsi baik di browser (ini mencakup semua browser modern dan IE, dimulai dengan IE8), dan di lingkungan Node.js, yang dapat digunakan untuk melakukan permintaan HTTP.

Perpustakaan ini didasarkan pada janji-janji, ia memiliki beberapa keunggulan dibandingkan mekanisme standar, khususnya, lebih dari API Fetch. Di antara kelebihannya adalah sebagai berikut:

  • Dukungan untuk browser lama (Anda perlu polyfill untuk menggunakan Ambil).
  • Kemampuan untuk menginterupsi permintaan.
  • Dukungan untuk mengatur batas waktu permintaan.
  • Perlindungan bawaan terhadap serangan CSRF.
  • Dukungan untuk mengunggah data dengan ketentuan informasi tentang kemajuan proses ini.
  • Dukungan untuk konversi data JSON.
  • Pekerjaan di Node.js

Instalasi


Anda dapat menggunakan npm untuk menginstal Axios:

 npm install axios 

Efek yang sama dapat dicapai dengan benang:

 yarn add axios 

Anda dapat menghubungkan perpustakaan ke halaman menggunakan unpkg.com :

 <script src="https://unpkg.com/axios/dist/axios.min.js"></script> 

API Axios


Anda dapat membuat permintaan HTTP menggunakan objek axios :

 axios({ url: 'https://dog.ceo/api/breeds/list/all', method: 'get', data: {   foo: 'bar' } }) 

Tetapi biasanya lebih nyaman menggunakan metode khusus:

  • axios.get()
  • axios.post()

Ini mirip dengan bagaimana jQuery menggunakan $.get() dan $.post() alih-alih $.ajax() $.post() .

Axios menawarkan metode terpisah untuk mengeksekusi jenis permintaan HTTP lain, yang tidak sepopuler GET dan POST, tetapi masih digunakan:

  • axios.delete()
  • axios.put()
  • axios.patch()
  • axios.options()

Perpustakaan memiliki metode untuk mengeksekusi permintaan yang dirancang untuk hanya menerima tajuk HTTP, tanpa badan respons:

  • axios.head()

DAPATKAN permintaan


Axios nyaman digunakan menggunakan sintaksis async / await modern. Contoh kode berikut, yang dirancang untuk Node.js, menggunakan perpustakaan untuk memuat daftar trah anjing dari Dog API . Di sini metode axios.get() diterapkan dan batuan dihitung:

 const axios = require('axios') const getBreeds = async () => { try {   return await axios.get('https://dog.ceo/api/breeds/list/all') } catch (error) {   console.error(error) } } const countBreeds = async () => { const breeds = await getBreeds() if (breeds.data.message) {   console.log(`Got ${Object.entries(breeds.data.message).length} breeds`) } } countBreeds() 

Hal yang sama dapat ditulis ulang tanpa menggunakan async / menunggu, menerapkan janji:

 const axios = require('axios') const getBreeds = () => { try {   return axios.get('https://dog.ceo/api/breeds/list/all') } catch (error) {   console.error(error) } } const countBreeds = async () => { const breeds = getBreeds()   .then(response => {     if (response.data.message) {       console.log(         `Got ${Object.entries(response.data.message).length} breeds`       )     }   })   .catch(error => {     console.log(error)   }) } countBreeds() 

Menggunakan parameter dalam permintaan GET


Permintaan GET dapat berisi parameter yang terlihat seperti ini di URL:

 https://site.com/?foo=bar 

Saat menggunakan Axios, permintaan semacam ini dapat dilakukan seperti ini:

 axios.get('https://site.com/?foo=bar') 

Efek yang sama dapat dicapai dengan mengatur properti params di objek dengan parameter:

 axios.get('https://site.com/', { params: {   foo: 'bar' } }) 

Permintaan POST


Mengeksekusi permintaan POST sangat mirip dengan mengeksekusi permintaan GET, tetapi di sini, alih-alih metode axios.get() , metode axios.post() digunakan:

 axios.post('https://site.com/') 

Sebagai argumen kedua, metode post menerima objek dengan parameter permintaan:

 axios.post('https://site.com/', { foo: 'bar' }) 

Menggunakan Protokol WebSocket di Node.js


WebSocket adalah alternatif untuk HTTP, dapat digunakan untuk mengatur pertukaran data dalam aplikasi web. Protokol ini memungkinkan Anda untuk membuat saluran komunikasi dua arah yang berumur panjang antara klien dan server. Setelah koneksi dibuat, saluran komunikasi tetap terbuka, yang menempatkan aplikasi pada pembuangan koneksi yang sangat cepat, ditandai dengan latensi rendah dan beban tambahan kecil pada sistem.

Protokol WebSocket didukung oleh semua browser modern.

▍ Perbedaan HTTP


HTTP dan WebSocket adalah protokol yang sangat berbeda yang menggunakan pendekatan berbeda untuk bertukar data. HTTP didasarkan pada model "permintaan-respons": server mengirim beberapa data ke klien setelah diminta. Dalam kasus WebSocket, semuanya diatur secara berbeda. Yaitu:

  • Server dapat mengirim pesan ke klien atas inisiatifnya sendiri, tanpa menunggu permintaan dari klien.
  • Klien dan server dapat bertukar data secara bersamaan.
  • Saat mengirimkan pesan, sejumlah kecil data layanan digunakan. Ini, khususnya, menyebabkan latensi rendah dalam pengiriman data.

Protokol WebSocket sangat cocok untuk komunikasi real-time melalui saluran yang tetap terbuka untuk waktu yang lama. HTTP, pada gilirannya, sangat baik untuk mengatur sesi komunikasi sesekali yang diprakarsai oleh klien. Pada saat yang sama, harus dicatat bahwa, dari sudut pandang pemrograman, jauh lebih mudah untuk mengimplementasikan pertukaran data menggunakan protokol HTTP daripada menggunakan protokol WebSocket.

▍ Versi protokol WebSocket yang dilindungi


Ada versi yang tidak aman dari protokol WebSocket ( ws:// skema URI), yang menyerupai, dalam hal keamanan, protokol http:// . Penggunaan ws:// harus dihindari, lebih memilih versi protokol yang aman - wss:// .

▍Membuat Koneksi WebSocket


Untuk membuat koneksi WebSocket, Anda perlu menggunakan konstruktor yang sesuai:

 const url = 'wss://myserver.com/something' const connection = new WebSocket(url) 

Setelah koneksi berhasil dibuat, acara open dinaikkan. Anda dapat mengatur acara ini dengan menetapkan fungsi panggilan balik ke properti onopen dari objek connection :

 connection.onopen = () => { //... } 

Untuk menangani kesalahan, pengendali event onerror digunakan:

 connection.onerror = error => { console.log(`WebSocket error: ${error}`) } 

▍Mengirim data ke server


Setelah membuka koneksi WebSocket ke server, Anda dapat mengirim data ke sana. Ini dapat dilakukan, misalnya, dalam onopen :

 connection.onopen = () => { connection.send('hey') } 

▍Mendapatkan data dari server


Untuk menerima data yang dikirim menggunakan protokol WebSocket dari server, Anda dapat menetapkan onmessage onmessage, yang akan dipanggil ketika acara message diterima:

 connection.onmessage = e => { console.log(e.data) } 

▍ Implementasi server WebSocket di lingkungan Node.js


Untuk menerapkan server WebSocket di lingkungan Node.js, Anda dapat menggunakan pustaka ws yang populer. Kami akan menggunakannya untuk pengembangan server, tetapi cocok untuk membuat klien, serta untuk mengatur interaksi antara dua server.

Instal pustaka ini dengan pertama-tama menginisialisasi proyek:

 yarn init yarn add ws 

Kode untuk server WebSocket yang perlu kita tulis cukup ringkas:

 constWebSocket = require('ws') const wss = newWebSocket.Server({ port: 8080 }) wss.on('connection', ws => { ws.on('message', message => {   console.log(`Received message => ${message}`) }) ws.send('ho!') }) 

Di sini kita membuat server baru yang mendengarkan pada port standar 8080 untuk protokol WebSocket dan menjelaskan panggilan balik, yang, ketika koneksi dibuat, mengirim pesan ke klien ho! dan mencetak ke konsol pesan yang diterima dari klien.

Ini adalah contoh kerja server WebSocket, dan berikut adalah klien yang dapat berinteraksi dengannya.

Ringkasan


Hari ini kita berbicara tentang mekanisme jaringan yang didukung oleh platform Node.js, menggambar paralel dengan mekanisme serupa yang digunakan di browser. Topik kita berikutnya adalah menangani file.

Pembaca yang budiman! Apakah Anda menggunakan protokol WebSocket di aplikasi web Anda, sisi server yang dibuat menggunakan Node.js?

Source: https://habr.com/ru/post/id424557/


All Articles