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.
Tulisan ini akan berlanjut ke Bagian 3
Happy Coding 🔥