HTTP di Node.js - Bagian 1

NODE.JSHTTPREQUESTRESPONSEGETPOST

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

Meskipun saat ini sudah amat banyak framework seperti express, fastify, dll yang memudahkan kita dalam membuat server memakai Node.js tetapi pada dasarnya framework-framework seperti yang Saya sebut sebelumnya tidaklah terlepas dari pemakaian atas salah satu modul inti dari Node.js yang bernama HTTP.

Dalam pengalaman Saya dalam mengembangkan banyak aplikasi web dengan memakai Node.js terkadang kita tidak memerlukan framework-framework yang sebenarnya secara teknis & kebutuhan sudah bisa di tangani hanya dengan memakai modul dasar dari Node.js seperti modul HTTP.

HTTP

Konsep dasar dari aplikasi web sangat sederhana yaitu ada klien, server dan jaringan yang menghubungkan keduanya. Klien dan server perlu berkomunikasi satu sama lain melalui jaringan dan cara berkomunikasi ini harus disepakati bersama dan kesepakatan dalam cara berkomunikasi inilah yang melahirkan protokol seperti HTTP.

Sebagai mana yang anda ketahui, salah satu yang membedakan Node.js dengan bahasa pemrogramn lain seperti PHP yaitu pada PHP anda memerlukan web server tersendiri seperti Apache HTTP dan modul tambahan tersendiri untuk memproses kode-kode PHP tersebut sedangkan pada Node.js anda bisa membuat web server yang berdiri sendiri dan menulis kode pemroses di server dengan memakai satu bahasa pemrograman yaitu JavaScript.

Seperti Saya katakan sebelumnya bahwa mempelajari HTTP API di Node.js sangatlah penting bukan hanya dengan modul ini anda bisa membangun berbagai macam aplikasi web yang berjalan diatas protokol HTTP tanpa harus bergantung pada framework-framework yang sudah ada selain itu anda akan mempunyai skill yang jauh lebih mendalam di Node.js.


HTTP/1.1 muncul untuk meningkatkan performansi dari koneksi antara server dan klien, beberapa peningkatan yang sangat penting adalah:

  • Persistent connections to allow connection reuse artinya penggunaan kembali koneksi yang sudah ada.

  • Chunked transfer encoding to allow response streaming artinya HTTP/1.1 memberikan fitur transfer data pecahan yang memungkinkan response secara streaming.

  • Request pipelining to allow parallel request processing.

  • Byte serving to allow range-based resource requests.

  • Improved and much better-specified caching mechanisms.

HTTP merupakan protokol web yang sudah lebih dari 20 tahun ini kita pakai, protokol ini sebenarnya bernama HTTP/1.1, untuk lebih lanjut Saya sarankan membaca referensi tentang HTTP seperti di https://hpbn.co/http1x.

HTTP Node.js

HTTP di Node.js merupakan parser HTTP yang API-nya cukup sederhana & bersama dengan parser TCP (net) maka dengan mudah bisa dibuat server HTTP yang sangat fleksibel.

http class

Modul HTTP di Node.js (v14.11.0) mempunyai 5 kelas, 7 top function & 4 properti. 5 kelas utama yaitu:

http.Agent http.ClientRequest http.Server http.ServerResponse http.IncomingMessages

dan 2 fungsi utama menurut saya yang sangat penting pada modul HTTP Node.js ini berada yang pada top function yaitu:

http.request()

Fungsi ini menyediakan API untuk request, hampir sama dengan ketika kita mengakses URL melalpui browser.

http.createServer()

Dengan fungsi ini anda bisa membuat web server yang sangat fleksibel dengan memakai JavaScript.

Request

Seperti Saya tulis sebelumnya, selain melalui browser anda juga bisa melakukan request secara programatik yaitu dengan memakai fungsi http.request().

import http from "http";

let keepaliveAgent = new http.Agent({ keepAlive: true });

const options = {
  hostname: "kalenderjawa.dev",
  port: 80,
  path: "/",
  method: 'GET',
  agent: keepaliveAgent
}

const req = http.request(options, (res) => {
  console.log(res instanceof http.IncomingMessage);
  console.log(res.rawHeaders);
  res.setEncoding("utf-8");
  res.on("data", (chunk) => {
    console.log(chunk);
  });
  res.on("end", () => console.log("Data end."));
});

console.log(req instanceof http.ClientRequest);

req.end();

Perhatikan bahwa kita bisa mengatur Agent untuk request dimana Agent ini perannya mirip dengan browser, dalam Node.js Agent ini berada pada kelas http.Agent.

Data headers dari response res pada kode diatas dapat dilihat melalui properti res.rawheaders yang memberikan data headers kasar berbentuk array [key1, value1, key2, value2,...]

[
  'Host', // key 'Host'
  'localhost:3113', // value 'localhost:3113'
  'Connection',
  'keep-alive',
  'User-Agent',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 
  (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36 Edg/85.0.564.51',
  'DNT',
  '1',
  'Accept',
  'image/webp,image/apng,image/*,*/*;q=0.8',
  ...
]

yang perlu diingat disini bahwa modul HTTP di Node.js hanya mem-parsing data menjadi headers & body tetapi tidak mem-parsing data headers itu sendiri, sehingga untuk memilah array headers yg diterima maka anda harus memisahnya secara manual.

res.setEncoding() diperlukan supaya data yang diterima dari request tidak diperlakukan sebagai data kasar yaitu Buffer dan dengan mengatur tipe encoding maka data asli yang diterima bisa kita baca selayaknya.

Satu lagi yang perlu dingat bahwa API HTTP di Node.js selain hanya menangani parsing data menjadi headers & body selain itu juga menangani proses stream. Pada kode diatas data yang diterima dari request adalah berupa potongan-potongan data atau sering di istilahkan dengan chunk.

HTTP Server

Membangun server dasar dari Node.js amatlah mudah dan hanya dengan memakai modul bawaan Node.js anda bisa membuat server yang memberikan klien halaman HTML. Sebagai contoh kode seperti dibawah ini,

import http from "http";

let body = "<strong>20OK</strong>";

const httpServer = http.createServer((req, res) => {
  res.setHeader("Content-Length", body.length);
  res.setHeader("Content-Type", "text/html");
  res.setHeader("Set-Cookie", ["nodejs=http"]);
  res.setHeader("Server", "http node.js");
  res.setHeader("X-Dev", "junwatu");
  res.end(body);
});

httpServer.listen(3113, () => {
  console.log("== node.js http server ==");
  console.log(`ukuran maksimum dari header: ${http.maxHeaderSize / 1024}KB`);
});

Web server diatas hanya mempunyai satu rute yaitu / yang mengembalikan konten HTML ke klien dan konten yang diberikan ke klien memberikan data tambahan berupa cookie, header dan juga custom header seperti X-Dev.

Konten yang diberikan kepada klien pada kode diatas adalah bertipe HTML atau istilahnya mempunyi mime text/html.

res.setHeader("Content-Type", "text/html");

Logikanya kalau anda ingin memberikan klien berbagai macam tipe berkas (gambar, mp3, video, css, javascript) maka kode yang anda tulis harus bisa menangani tipe mime yang berbeda tersebut.

Jika anda menjalankan kode diatas kemudian melakukan akses melalui browser dan melihat response permintaan melalui Chrome Dev Tools (jika anda memakai browser Google Chrome) maka dapat anda lihat data-data yang dikembalikan ke klien oleh web server seperti pada screenshot berikut

Respon HTTP

Selain data-data yang sudah kita set pada header response ada juga beberapa data header default seperti Keep-Alive timeout=5 yang artinya koneksi akan tetap hidup dengan timeout 5 detik sejak response data terakhir.

Secara default browser akan meminta Connection=keep-alive kepada server dan pada Node.js yang mendukung HTTP/1.1 telah mendukung keepalive sejak versi 0.8.0. Fitur ini merupakan salah satu cara dalam meningkatkan performansi dari aplikasi web yaitu dengan cara menggunakan kembali koneksi yang sudah ada.

Kode Status

Respon dari HTTP selalu menyertakan kode status HTTP. Kode-kode ini menandakan status dari respon terhadap request apakah respon dalam status berhasil, error, dialihkan ataukah dalam keadaan yang lain.

Anda bisa melihat kode status apa saja di modul HTTP Node.js melalui metode http.STATUS_CODES.

C:\Users\E Q U A N\Desktop\http>node
Welcome to Node.js v14.11.0.
Type ".help" for more information.
> const http = require('http');
undefined
> http.STATUS_CODES
{
  '100': 'Continue',
  '101': 'Switching Protocols',
  '102': 'Processing',
  '103': 'Early Hints',
  '200': 'OK',
  '201': 'Created',
  '202': 'Accepted',
  '203': 'Non-Authoritative Information',
  '204': 'No Content',
  '205': 'Reset Content',
  '206': 'Partial Content',
  '207': 'Multi-Status',
  '208': 'Already Reported',
  '226': 'IM Used',
  '300': 'Multiple Choices',
  '301': 'Moved Permanently',
  '302': 'Found',
  '303': 'See Other',
  '304': 'Not Modified',
  '305': 'Use Proxy',
  '307': 'Temporary Redirect',
  '308': 'Permanent Redirect',
  '400': 'Bad Request',
  '401': 'Unauthorized',
  '402': 'Payment Required',
  '403': 'Forbidden',
  '404': 'Not Found',
  '405': 'Method Not Allowed',
  '406': 'Not Acceptable',
  '407': 'Proxy Authentication Required',
  '408': 'Request Timeout',
  '409': 'Conflict',
  '410': 'Gone',
  '411': 'Length Required',
  '412': 'Precondition Failed',
  '413': 'Payload Too Large',
  '414': 'URI Too Long',
  '415': 'Unsupported Media Type',
  '416': 'Range Not Satisfiable',
  '417': 'Expectation Failed',
  '418': "I'm a Teapot",
  '421': 'Misdirected Request',
  '422': 'Unprocessable Entity',
  '423': 'Locked',
  '424': 'Failed Dependency',
  '425': 'Too Early',
  '426': 'Upgrade Required',
  '428': 'Precondition Required',
  '429': 'Too Many Requests',
  '431': 'Request Header Fields Too Large',
  '451': 'Unavailable For Legal Reasons',
  '500': 'Internal Server Error',
  '501': 'Not Implemented',
  '502': 'Bad Gateway',
  '503': 'Service Unavailable',
  '504': 'Gateway Timeout',
  '505': 'HTTP Version Not Supported',
  '506': 'Variant Also Negotiates',
  '507': 'Insufficient Storage',
  '508': 'Loop Detected',
  '509': 'Bandwidth Limit Exceeded',
  '510': 'Not Extended',
  '511': 'Network Authentication Required'
}
>

Penggunaan kode status bergantung kepada banyak hal, bisa desain server, kondisi jaringan, berkas dalam sistem operasi dll tetapi yang pasti anda bisa mengatur kode status tersebut melalui kode pemrograman.

response.statusCode = 200

atau bisa melalui fungsi ringkas writeHead() yang mempunyai prioritas lebih tinggi dari fungsi setHeader()

response.writeHead(200, { 'Content-Type': 'text/plain', 'X-Dev': 'Sinau Node.js' })
response.end(body)

Yang perlu diingat adalah bahwa terdapat 5 kategori utama dalam kode status HTTP yaitu:

  • 1xx Informational
  • 2xx Success
  • 3xx Redirection
  • 4xx Client Error
  • 5xx Server Error

Pengkategorian diatas sudah cukup jelas tetapi untuk mengetahui apa arti dari setiap kode status HTTP. Selengkapnya tentang kode status HTTP diatas anda bisa melihatnya pada website seperti httpstatuses.com.

Kode status yang wajib diketahui adalah kode sukses 200 dan kode eror 404.

Stream

Stream adalah salah satu konsep yang fundamental dalam Node.js, paling mudah dalam memahami konsep stream ini adalah seperti saat kita sedang menonton film secara streaming 😊. Dengan metode streaming kita bisa menonton film yang kita sukai tanpa perlu mengunduh film tersebut secara keseluruhan.

Demikian juga dengan konsep stream yang diterapkan pada modul HTTP Node.js, sebagai klien yang mengakses browser dengan metode stream, untuk melihat isi halaman HTML tersebut kita tidak perlu menunggu seluruh halaman HTML selesai di download di browser.

Contoh kode pengiriman halaman HTML ke browser klien adalah seperti berikut,

import http from "http";
import fs from "fs";
import path from "path";
import zlib from "zlib";

const httpServer = http.createServer((req, res) => {
  res.setHeader("Content-Type", "text/html");
  res.setHeader("Set-Cookie", ["nodejs=http"]);
  res.setHeader("Server", "http node.js");
  res.setHeader("X-Dev", "junwatu");

  res.setHeader('Content-Encoding',"br");
  fs.createReadStream(path.dirname(".") + '/index.html')
  .pipe(zlib.createBrotliCompress())
  .pipe(res);
});

httpServer.listen(3113, () => {
  console.log("== node.js http server ==");
  console.log(`ukuran maksimum dari header: ${http.maxHeaderSize / 1024}KB`);
});

Tulisan ini akan berlanjut pada Bagian 2.

Happy Coding!🐱‍🏍

Komentar