HTTP di Node.js - Bagian 2

NODE.JSHTTPREQUESTRESPONSEGETPOST

Tulisan berikut merupakan tulisan yang terbagi dalam beberapa bagian sebagai berikut:

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 🔥

Komentar