Tulisan berikut merupakan tulisan yang terbagi dalam beberapa bagian sebagai berikut:
- HTTP di Node.js - Bagian 1
- HTTP di Node.js - Bagian 2 (tulisan ini)
HTTP Server
Melanjutkan tulisan sebelumnya mengenai API HTTP di Node.js.
Kompresi Response
Header Content-Encoding
menentukan jenis kompresi
dari response HTTP.
Kompresi hanya diperlukan untuk konten-konten atau data yang aslinya memang belum terkompresi sehingga ketika dikirimkan melalui http, kompresi tersebut akan memberikan manfaat yang lebih (silahkan baca lebih lanjut tentang kompresi HTTP di MDN.
res.setHeader('Content-Encoding', 'br')
br
adalah algoritma kompresi yang bernama
Brotli dan kompresi ini sangat cocok untuk
kompresi jenis teks sehingga kalau server HTTP banyak
mengeluarkan data teks seperti JSON atau dokumen HTML maka
gunakan saja kompresi ini.
import zlib from 'zlib'
fs.createReadStream(path.dirname(".") + "/index.html")
.pipe(zlib.createBrotliCompress())
.pipe(res);
Seperti Saya tulis sebelumnya bahwa di Node.js itu kamu bisa
membaca file secara streaming (selain sinkron dan
asinkron) dan pada saat proses stream tersebut bisa disisipkan
fungsi kompresi createBrotliCompress()
melalui
pipe
.
Dukungan browser akan Brotli?
Hampir 95% dari browser sudah mendukung kompresi Brotli kecuali IE dan Opera Mini, jadi bisa dipastikan secara umum sangat aman untuk memakai kompresi ini.
Deteksi MIME
Seperti yang Saya tulis sebelumnya kalau anda ingin memberikan
klien berbagai macam tipe berkas seperti gambar, mp3, video,
css, javascript (selain index.html
) dengan memakai
server HTTP Node.js maka kode yang anda tulis harus bisa
menangani tipe mime yang berbeda tersebut.
mime atau MIME merupakan standarisasi tipe media mengenai format dan aturan isi dari suatu dokumen MDN.
Hal yang perlu diingat bahwa browser itu mendeteksi tipe
mime dari header Content-Type
bukan dari
ekstensi file, sehingga sangatlah penting untuk menulis
dengan tepat tipe mime dari dokumen yang akan dikirimkan
oleh server ke klien browser.
Database mime dengan mudah bisa anda buat memakai JavaScript object seperti berikut
let mime = {
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpg',
'.gif': 'image/gif',
}
Untuk mendeteksi tipe file yang diminta oleh klien, hanya bisa
dilakukan dengan memeriksa ekstensi dari file request tersebut.
Dalam API HTTP Node.js bisa diperiksa pada properti
url
dari request HTTP req
let filename = '.' + req.url
Sebagai batasan, server HTTP ini hanya melayani rute path
/
dan secara default akan menyediakan file
index.html
if(filename === './') {
filename = ./index.html
}
Untuk mengetahui ekstensi dari file request bisa dengan mudah di
cari memakai modul path
import path from 'path'
let extensionName = String(path.extname(filename)).toLowerCase()
dan kemudian tipe mime bisa kita dapatkan dengan memakai
extensionName
sebagai key
let contentType = mime[extensionName] || "application/octet-stream"
Jika tipe mime file tidak ada dalam daftar
mime
maka contentType
akan di set ke
application/octet-stream
atau dalam bahasa awam
kita anggap file tersebut adalah binary (kita tidak
tahu jenis dari file tersebut).
Setelah kita tahu nama file yang diminta oleh klien
filename
dan tipe mime
contentType
maka dengan mudah file bisa kita
berikan ke klien.
import fs from 'fs'
fs.readFile(filename, (error, data) => {
if(error) {
if(error.code === 'ENOENT') {
fs.readFile('./404.html', (error, data) => {
res.writeHead('400', {'Content-Type': contentType})
res.end(data, 'utf-8')
})
} else {
res.writeHead(500)
res.end(`Server error ${error.code}`)
res.end()
}
} else {
res.writeHead(200, { 'Content-Typ': contentType })
res.end(content, 'utf-8')
}
})
Kode lengkap dari server HTTP Node.js sederhana tanpa dependensi luar.
import http from 'http'
import path from 'path'
import fs from 'fs'
const PORT = 5000
const mime = {
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpg',
'.gif': 'image/gif'
}
http
.createServer((req, res) => {
console.log(`request ${req.url}`)
let filename = '.' + req.url
if (filename === './') {
filename = './index.html'
}
let extensionName = String(path.extname(filename)).toLowerCase()
let contentType = mime[extensionName] || 'application/octet-stream'
fs.readFile(filename, (error, data) => {
if (error) {
if (error.code === 'ENOENT') {
fs.readFile('./404.html', (error, data404) => {
res.writeHead('404', { 'Content-Type': contentType })
res.end(data404, 'utf-8')
})
} else {
res.writeHead(500)
res.end(`Server error ${error.code}`)
res.end()
}
} else {
res.writeHead(200, { 'Content-Type': contentType })
res.end(data, 'utf-8')
}
})
})
.listen(PORT, () => console.log(`Server running on port ${PORT}`))
Kode server diatas cukup untuk menyediakan halaman HTML, CSS dan beberapa format gambar dan kalau boleh Saya bilang adalah server yang sifatnya informatif karena hanya bisa menyediakan file-file yang bersifat statis (operasi HTTP dengan GET saja) sehingga sangat cocok jika difungsikan sebagai server untuk website statis.