Belajar Menggunakan HTTP Request Dan Response Pada Node JS - CRUDPRO

Belajar Menggunakan HTTP Request Dan Response Pada Node JS

Belajar Menggunakan HTTP Request Dan Response Pada Node JS

Sebuah program situs berkomunikasi dengan perangkat lunak klien lewat HTTP. HTTP, sebagai prosedur yang bicara memakai request dan response jadikan program situs tergantung ke transisi ini untuk hasilkan document yang ingin diakses oleh pengguna. Pada umumnya, program situs yang hendak kita bangun harus mempunyai satu langkah untuk membaca HTTP Request dan kembalikan HTTP Response ke pengguna.

Pada peningkatan situs tradisional, kita biasanya memakai sebuah situs server seperti Apache HTTPD atau nginx sebagai penyalur content statis seperti HTML, CSS, Javascript, atau gambar. Untuk menambah program situs kita selanjutnya memakai penyambung antara situs server dengan program yang dikenal bernama CGI (Common Gateway Interface).

CGI diterapkan pada situs server sebagai antar-muka penyambung di antara situs server dengan program yang hendak hasilkan content secara aktif. Beberapa program CGI umumnya diperkembangkan berbentuk script, walau barangkali diperkembangkan dengan bahasa apa saja. Contoh dari bahasa pemrograman dan program yang hidup dalam CGI ialah PHP.

Untuk melihat lebih jelas langkah kerja CGI, lihat gambar berikut ini:

Belajar Menggunakan HTTP Request Dan Response Pada Node JS

Yang bisa kita ambil dari gambar di atas:

  1. Situs Server yang bertemu langsung dengan pengguna, terima HTTP Request dan mengembalikan HTTP Response.
  2. Untuk content statis seperti CSS, Javascript, gambar, atau HTML situs server dapat segera menyuguhkannya sebagai HTTP Response ke pengguna.
  3. Content aktif seperti program PHP atau Perl dihidangkan lewat CGI.
  4. CGI Script selanjutnya hasilkan HTML atau content statis yang lain yang hendak dihidangkan sebagai HTTP Response ke pengguna.

Walau ada beberapa peningkatan seterusnya dari CGI, contoh simpel di atas sebagai ide pokok saat awalnya peningkatan CGI. Biasanya program situs dengan CGI mempunyai kekurangan di mana jalankan script CGI mewajibkan situs server untuk membuat suatu proses baru. Pembuatan proses baru umumnya akan memakai beberapa waktu dan memory dibanding dengan eksekusi script, dan karena tiap pengguna yang tersambung akan menyebabkan ini pada server perform program bisa menjadi buruk.

CGI sendiri sediakan jalan keluar untuk hal itu, misalkan FastCGI yang jalankan program sebagai sisi dari situs server. Bahasa lain sediakan alternative dari CGI, misalkan Java yang mempunyai Servlet. Servlet pada Java sebuah program yang menambah feature dari server langsung . Maka pada pemrograman dengan Servlet, kita akan mempunyai satu situs server dalam program kita, dan pada situs server itu akan ditambahkan sejumlah fitur detail program situs kita.

Pada peningkatan program situs dalam NodeJS, pendekatan yang kita pakai lebih dekat (walau berbeda tepat) dengan pendekatan Servlet yang dipakai Java. Untuk meningkatkan program situs pada NodeJS kita akan:

  1. Memanggil situs server yang sudah disiapkan NodeJS.
  2. Membaca URL yang ingin dijangkau pengguna, dan panggil peranan untuk mengolah URL itu.
  3. Mengolah HTTP Request dari klien.
  4. Menghasilkan HTTP Response untuk klien.

Perbedaan khusus di antara NodeJS dengan Servlet ialah jika NodeJS mempunyai pendekatan yang lebih low tingkat, di mana kita harus aktifkan situs server kita, dan lakukan pengatasan URL, Request, dan Response lewat cara manual. Begitu juga, ada beberapa frame-work yang sudah diperkembangkan di atas NodeJS yang membantu kita dalam tangani hal itu, misalkan ExpressJS.

Catatan: Perlu ditekankan juga bahwa model pengembangan NodeJS tidak unik terhadpa NodeJS. Banyak bahasa lain yang juga mengadopsi cara yang sama, meskipun umumnya framework pengembangan web telah menutupi detil implementasinya. Contoh bahasa lain yang menggunakan model yang serupa yaitu Java dan Scala (Play Framework), Go (Revel), dan masih banyak lainnya.

Di bagian ini, kita akan mengulas pemanggilan situs server standard NodeJS, dan bagaimana mengolah HTTP Request dan membuat HTTP Response. Pengurusan URL dan pemetaan URL ke peranan akan kita ulas pada bab selanjutnya.

HTTP Server dengan NodeJS

Pembuatan sebuah server HTTP dengan NodeJS benar-benar simpel. Buat sebuah file bernama server.js di bagian khusus directory program, dan pakai code berikut ini:

var http = require("http");
var port = process.env.port || 1337;

var server = http.createServer(function(request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
});

server.listen(port, 'localhost');

Kita dapat menjalankan kode di atas dengan menggunakan perintah:

$ node server.js

dan ketika berkunjung ke halaman http://localhost:1337 pada browser kita akan melihat sebuah teks Hello World, seperti berikut:

Belajar Menggunakan HTTP Request Dan Response Pada Node JS

Cukup simpel bukan? Apa yang sudah kita lakukan?

Pada dua baris pertama:

var http = require("http");
var port = process.env.port || 1337;

kita lakukan persiapan awalnya. Faktor http akan memuat object dari modul HTTP standard yang disiapkan oleh NodeJS. Peranan require sebagai implementasi module sistem dari NodeJS. Simpelnya, require pada NodeJS sebagai import pada Java atau C dan C++.

Code process.env.port ambil environment variable PORT dari sistem operasi. Bila nilai tidak ditetapkan, kita masukkan 1337 sebagai nilai standard. Nilai dari port ini nanti akan kita pakai sebagai nilai port yang diawasi oleh situs server.

Di bagian selanjutnya:

var server = http.createServer(function(request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
});

Kita memanggil fungsi http.createServer yang hendak memberi kita object http.Server (dokumentasi http.Server). Object ini, sama dengan namanya, sebagai http server yang sudah disiapkan oleh NodeJS. Peranan http.createServer menerima sebuah fungsi sebagai parameter, yakni fungsi yang hendak dijalankan setiap sebuah request dari klien diterima. Fungsi ini mempunyai 2 buah parameter, yakni:

  1. request, yang disebut instant dari http.IncomingMessage, sebagai wakil HTTP Request yang dikirim pemakai. Sebuah jaringan bisa jadi hasilkan beberapa HTTP Request. Kita akan mengulas sisi ini lebih jauh nanti.
  2. response, instant dari http.ServerResponse, sebagai wakil HTTP Response yang hendak dikasih ke pengguna.

Tiga baris yang berada di dalam fungsi yang kita tulis pada dasarnya membuat HTTP Response secara aktif. Ulasan berkenaan pembuatan HTTP Response akan kita ulas di bagian selanjutnya.

Paling akhir, kita selanjutnya jalankan server dan dengarkan port yang disimpan pada variabel port:

server.listen(port, 'localhost');

http.Server.listen sebagai fungsi yang mulai mendengarkan dan menunggu jaringan dari klien. Dengan jalankan code ini kita pastikan server bisa diakses oleh klien pada mesin kita.

Untuk peningkatan seterusnya, kita bisa membuat modul tertentu untuk server, hingga nantinya kita bisa menyatukan server dengan elemen yang lain pada akhirannya akan hasilkan sebuah frame-work lengkap. Bagaimana kita bisa tingkatkan modularitas dari code server ini?

Pada bagian ini, kita lebih dulu akan fokus ke bagaimana membuat server bisa diundang oleh modul lain lewat require. Pada beberapa bagian seterusnya, kita baru akan balik ke modul server untuk menambah fungsionalitas dan modularitas pada modul server kita.

Kita bisa mengawali dengan pisahkan fungsi anonim yang dikirim ke http.createServer ke sebuah fungsi tertentu, supaya fungsi ini bisa digantikan oleh modul lain:

var onRequest = function (request, response) {
    response.writeHead(200, { "Content-Type": "text/plain" });
    response.write("Hello, World!");
    response.end();
};

var server = http.createServer(onRequest);

Kita kemudian dapat membuat sebuah fungsi baru yang betugas menghidupkan server kita:

var start = function () {
    server.listen(port, 'localhost');
    console.log("Server started at port " + port + ".");
}

exports.start = start;

Memasukkan fungsi start ke dalam property dari objek export di atas akan menyebabkan kita dapat memanggil kode untuk mulai menjalankan server ini dari luar modul. Mari kita coba. Pertama, buat sebuah file index.js dengan isi:

var server = require('./server.js');
server.start();

Kemudian jalankan index.js langsung dengan perintah:

$ node index.js

Lalu masuk ke http://localhost:1337. Hasil yang hendak kita peroleh akan sama dengan awalnya. Di bagian ini kita melihat bagaimana:

  1. Code yang berada di dalam server.js dilakukan saat kita memanggil require('./serverjs').
  2. Saat kita mengimpor sebuah modul, modul itu akan diberi berbentuk object, yang bisa kita taruh ke sebuah variabel.

Dengan pengetahuan ini, kita bisa memakai beberapa tehnik perancangan code biasanya untuk mengembangkan server kita lebih jauh kembali. Tapi saat sebelum masuk ke peningkatan lebih dalam, kita akan menyaksikan bagaimana kita bisa mengolah request dan response lebih dulu.

HTTP Request

Di bagian awalnya kita sudah melihat bagaimana sebuah HTTP Request dibuat dari http.Server, dan sebagai object http.IncomingMessage. Object http.IncomingMessage sebagai object yang unik, karena object ini bisa dibuat oleh 2 buah fungsi, dan masing-masing fungsi akan memberi properti yang lain ke object. Kita akan melihat lebih jauh sisi dari object ini saat mengulas pembuatan HTTP Request nanti. Untuk saat ini, sebagai keluaran hasil dari http.Server, object http.IncomingMessage mempunyai beberapa properti yang penting dicermati, yakni:

IncomingMessage.method Mengambil method (GET, POST, dst) sebagai string.
IncomingMessage.url URL Request sebagai string (contoh: /user/jwz )
IncomingMessage.headers Sebuah objek yang read only (tidak dapat diubah). Lihat penjelasan di bawah.

Ketiga properti ini mempunyai manfaat masing-masing yang paling bisa membantu kita dalam peningkatan program situs. Akses dari tiap-tiap properti dapat segera dilaksanakan dari object yang diberi oleh http.server.createServer, sebagai berikut:

var http = require('http');
var port = process.env.port || 1337;

var onRequest = function (request, response) {
    console.log(request.headers);
};

var server = http.createServer(onRequest);
server.listen(port, 'localhost');

Bila kita jalankan code di atas dan berkunjung halaman pada http://localhost:1337/karena itu kita akan melihat cetakan JSON pada console sebagai berikut:

{
    host: 'localhost:1337',
    connection: 'keep-alive',
    accept: '*/*',
    'user-agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/41.0.2272.89 Safari/537.36',
    'accept-encoding': 'gzip, deflate, sdch',
    'accept-language': 'id,en;q=0.8,en-US;q=0.6',
    cookie: 'thelia_cart=546c25890d8bc7.53190152',
}

Sama seperti yang kita lihat dari isi IncomingMessage.headers di atas, HTTP Header yang diberi berbentuk object, dengan nama header sebagai properti dan nilai (isi) header sebagai nilai properti. Dengan akses ketiga nilai ini, kita segera dapat secara mudah meningkatkan code dasar untuk program, misalkan untuk panggil fungsi yang berbeda untuk tiap metode:

var onRequest = function (request, response) {
    var method = request.method;

    switch(method) {
        case "GET":
            // lakukan sesuatu
        case "POST":
            // lakukan sesuatu
        case "PUT":
            // lakukan sesuatu
    }
};

Sebelum kita masuk lebih jauh, kita akan melihat terlebih dahulu tentang pertukaran data dalam HTTP secara lebih detail bagaimana data dikirimkan dalam HTTP.

Pembacaan Data dari HTTP Request

Data dikirim dalam HTTP Request dalam dua langkah, bergantung dari metode yang dikirim:

  1. Melalui URL, dengan patokan yang diberi. Dipakai oleh GET.
  2. Melalui entity bodi dalam HTTP Request. Dipakai untuk POST dan PUT.

Pada praktiknya ada satu langkah kembali untuk mengirimkan data, yakni lewat cookie, tapi pemakaian cookie tidak sangat efisien karena cookie direncanakan untuk simpan data status pengguna. Saat ini silahkan kita saksikan bagaimanakah cara untuk membaca data pada URL atau entity bodi.

Pembacaan Data pada URL

Pembacaan data yang dikirim lewat URL umumnya dilaksanakan untuk request dengan metode GET. Untuk melihat bagaimana GET mengirim data, kita ditambah dahlu harus mengerti mengenai sintaks penulisan URL. Pada umumnya, sebuah URL mempunyai sintaks sebagai berikut (detail ada di RFC 1738):

<scheme>://<user>:<password>@<host>:<port>/<path>?<query>#<fragment>

Apa makna dari setiap bagian dari URL di atas? Mari lihat dari tabel di bawah.

Nama Deskripsi Harus ada?
scheme Protokol yang digunakan. Ya
user Nama pengguna. Tidak
password Password untuk nama pengguna. Tidak
host Hostname atau IP. Ya
port Port yang akan diakses. Beberapa protokol memiliki port standar (misal: HTTP = 80). Tergantung Protokol
path Lokasi data pada server Tergantung Protokol
query Digunakan untuk mengirimkan parameter kepada apliikasi. Tidak
fragment Nama dari bagian tertentu pada data (mis: judul pada buku). Tidak

Misalnya jika diterapkan pada browser:

https://bert:[email protected]:8080/data/rahasia?id=scp-0682&access=O5#desc

Bagian khusus yang hendak kita pakai untuk membaca data pada metode GET yakni sisi dari query. Sintaks pembuatan query sendiri lumayan gampang, yakni:

?nama-parameter:nilai&nama-parameter:nilai&...

Misalkan pada URL contoh di atas, terdapat dua buah data yang dikirimkan melalui URL, yaitu:

Param. Nilai
id scp-0682
access O5

Untuk pembacaan nilai query kita bisa memakai modul url yang sudah diberi oleh NodeJS. Modul ini mempunyai tiga fungsi khusus:

  1. url.parse, membaca sebuah string URL jadi object.
  2. url.format, kebalikan dari url.parse, mengganti object URL jadi string.
  3. url.format, kebalikan dari url.parse, mengganti object URL jadi string.
  4. url.resolve, melengkapi URL sesuai langkah browser pada tag a.

Fungsi yang hendak kita gunakan untuk membaca nilai query yakni url.parse, sebagai berikut:

var url     = require('url');
var url_obj = url.parse('http://user:[email protected]:8080/pa/th?query=sample&data=123#desc', true);

console.log(url_obj);
/*
{
    protocol: 'http:',
    slashes: true,
    auth: 'user:pass',
    host: 'contoh.com:8080',
    port: '8080',
    hostname: 'contoh.com',
    hash: '#desc',
    search: '?query=sample&data=123',
    query: { query: 'sample', data: '123' },
    pathname: '/pa/th',
    path: '/pa/th?query=sample&data=123',
    href: 'http://user:[email protected]:8080/pa/th?query=sample&data=123#desc'
}
*/

Seperti yang bisa dilihat pada keluaran object di atas, properti yang ingin kita akses ialah url_obj.query. Fungsi url.parse sendiri bisa menerima 3 buah argument, yakni:

  1. Argument pertama, urlStr, diisikan string URL yang ingin diganti jadi object.
  2. Argument kedua, parseQueryString, sebuah boolean yang dipakai untuk tentukan apa query string akan diganti jadi object atau mungkin tidak. Bila tidak diisikan akan dianggap berharga false.
  3. Argument ketiga, slashesDenoteHost, bila diisikan dengan true akan membaca //foo/bar jadi { host: 'foo', pathname: '/bar' } bukan nilai standard { pathname: '//foo/bar' }. Bila tidak diisi dianggap false.

Hingga bila kita ingin meneruskan code di atas dengan coba mengambil langsung query kita bisa lakukan panggilan pada parameternya langsung:

console.log(url_obj.query);
// { query: 'sample', data: '123' }

Dengan memakai fungsi url.parse, pembacaan nilai patokan pada GET bisa menjadi benar-benar gampang dan simpel. Kita dapat memakai properti lain untuk beragam kepentingan. Tiga properti yang sangat menarik dan kerap dipakai yakni pathname (area untuk menyimpan data dalam server), query (query string), dan hash (sisi detail dari document).

Pembacaan Data dalam Entity Body

Beberapa metode lain di luar GET mengirim data lewat entity bodi dari sebuah HTTP Request. Untuk mengakses data yang dikirim dengan langkah ini, kita bisa lakukan buffering data ke sebuah string. Pada NodeJS, data ini bisa dibaca lewat moment data dalam object http.IncomingMessage. Saat semua data sudah usai dibaca, karena itu moment end akan dilakukan. Berikut contoh code untuk pembacaan data:

var data = '';
request.on('data', function (chunck) {
    data = data + chucnk;
});

request.on('end', function () {
    // lakukan sesuatu terhadap variabel data
    // yang sudah lengkap
});

Dari kode di atas kita dapat melihat bagaimana mengambil data dari entity body cukup mudah. Untuk request seperti PUT yang biasanya dikirimkan dalam bentuk data langsung, misalnya:

PUT /data/1234 HTTP/1.1
[berbagai header]

<appointmentRequest>
    <patient id = "jsmith"/>
</appointmentRequest>

yang bila kita mengambil datanya memakai sistem di atas karena itu variabel data akan berisi string XML sesuai yang dikirim. Kita selanjutnya bisa memakai fungsi atau object khusus untuk mengolah string XML itu sama sesuai keperluan. Langkah pemrosesan ini berlaku untuk request POST yang dikirim oleh klien HTTP, baik dari program desktop atau smartphone.

Untuk request POST yang dikirim lewat form HTML, pemrosesan harus dilaksanakan secara sedikit berlainan. Pengiriman data pada form HTML dikirim dengan memakai dua pola encoding, yakni:

  1. application/x-www-form-urlencoded, untuk pengiriman data ukuran kecil yang tidak mengikutsertakan file. Pola encoding memakai langkah yang serupa dengan query pada metode GET.
  2. multipart/form-data, untuk pengiriman data jumlah besar atau yang mengikutsertakan file. Memakai pola encoding khusus yang diterangkan dengan detail dalam RFC 2045 dan RFC 1867. Pembacaan pola bisa dilaksanakan sama sesuai detail pada RFC 2388.

Kedua pola code di atas bisa diolah dengan memakai beberapa modul yang telah ada. Pembaca lebih dianjurkan memakai modul yang sudah ada karena pembacaan pola data sesuai detail RFC sebagai hal yang lumayan panjang untuk dilaksanakan dan diulas pada tulisan ini. (Perlu dicatat jika kesulitan ulasan muncul karena panjangnya detail, bukan susah atau kompleks).

Untuk application/x-www-form-urlencoded, pola data persis sama sama yang ada pada GET. Kita bisa memakai modul querystring untuk memudahkan ktia dalam mengolah data yang tiba dengan pola ini. Modul querystring mempunyai 2 buah fungsi khusus, yakni:

  1. querystring.parse, yang ambil sebuah string query GET dan kembalikan object. Misalkan, querystring.parse('a=1&b=2') akan mengembalikan {a: 1, b: 2}.
  2. querystring.stringify, kontradiksi dari parse. Ambil object dan menjadikan string. Misalkan, querystring.stringify({a: 1}) akan mengembalikan a=1.

Mari kita lihat bagaimana kita bisa memakai querystring untuk membaca data pada entity body. Misalkan sebuah request:

POST /data/mahasiswa HTTP/1.1
[berbagai header]

nama=Budi+Hartono&semester=6&jurusan=Teknik+Informatika

dapat kita proses dengan kode berikut:

var data = "";
request.on('data', function (chunck) {
    data += chunck;
});

request.on('end', function () {
    var mhs = qs.parse(data);
    console.log(mhs);
});

akan memberikan kita keluaran sebuah objek javascript seperti berikut:

{
    nama: 'Budi Hartono',
    semester: '6',
    jurusan: 'Teknik Informatika'
}

Content yang dikirimkan dengan pola multipart/form-data sendiri mempunyai langkah penyimpanan yang sedikit sulit. Misalkan untuk data yang serupa dengan request awalnya, tapi memakai pola ini, request bisa menjadi:

POST /data/mahasiswa HTTP/1.1
[berbagai header]
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="nama"

Budi Hartono
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="semester"

6
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="jurusan"

Teknik Informatika
----WebKitFormBoundary7MA4YWxkTrZu0gW

Karena format ini menggunakan penyimpanan yang cukup panjang (terutama jika melibatkan file), maka kita tidak dapat membaca data ini secara langsung. Kita dapat menggunakan berbagai pustaka yang sudah ada untuk melakukan pembacaan data ini, misalnya node-multiparty. Untuk menggunakan node-multiparty, kita dapat terlebih dahulu menambahkan pustaka dengan perintah:

$ npm install multiparty

dan kemudian dapat menggunakannya seperti berikut:

var multiparty = require('multiparty');
var form       = new multiparty.Form();

form.parse(request, function (err, fields, files)) {
    console.log({'fields': fields, 'files': files});
});

yang jika dijalankan akan menghasilkan:

{
    fields:
    {
        nama:     [ 'Budi Hartono' ],
        semester: [ '6' ],
        jurusan:  [ 'Teknik Informatika' ]
    },
    files: {}
}

Ulasan mendalam mengenai pemakaian node-multiparty bisa dibaca pada dokumentasi pustaka itu. Harus diingat jika walau pola application/x-www-form-urlencoded dan multipart/form-data cuma dipakai untuk HTML Form pada standard, banyak klien yang mengirim request POST, PUT, serta DELETE dengan memakai kedua pola ini tanpa lewat form. Bila program server yang diperkembangkan memang memberikan dukungan pemakaian request ini, langkah pemrosesan yang dipakai masih sama (dengan pustaka seperti node-multiparty). Begitu juga, sudah pasti pemakaian semacam ini tidak dianjurkan, karena berlawanan dengan standard.

Sampai di sini kita sudah melihat bagaimana HTTP Request diletakkan oleh NodeJS, dan bagaimana membaca data yang dikirim oleh HTTP Request. Saat sebelum melihat bagaimana membuat HTTP Request secara aktif, kita akan pelajari mengenai HTTP Response lebih dulu di bagian selanjutnya.

HTTP Response

Pada bagian awalnya kita sudah melihat bagaimana membaca dan menangani HTTP Request dari server NodeJS. Saat ini kita akan melihat bagaimana membuat HTTP Response yang diberi oleh server NodeJS. HTTP Response yang diberi oleh server NodeJS sebagai object bertipe http.ServerResponse, yang menerapkan antar-muka stream.Writable (dokumentasi stream.Writable). Karena itu, penulisan HTTP Response akan memakai ide penulisan stream yang serupa dalam bahasa pemrograman secara umum.

Secara simpel, untuk tuliskan data dengan stream.Writable, kita akan lakukan dua hal berurut:

  1. Menulis stream dengan memanggil fungsi stream.Writable.write.Fungsi menerima dua parameter, yakni string yang hendak dicatat dan encoding dari string yang dipakai
  2. Menutup stream dengan memanggil fungsi stream.Writable.end. Fungsi tidak terima parameter.
.

Pada suatu code server simpel, penulisan tanggapan akan dilakukan sebagai berikut:

var http = require("http");
var port = process.env.port || 1337;

var server = http.createServer(function(request, response) {
    response.write("Hello World");
    response.end();
});

server.listen(port, 'localhost');

Sebagai tambahan untuk HTTP, http.ServerResponse memiliki beberapa fungsi-fungsi tambahan, yaitu (semua fungsi di bawah adalah untuk objek http.ServerResponse):

  1. writeContinue, memberi pesan HTTP/1.1 100 Continue ke klien.
  2. writeHead, tuliskan header dari HTTP Response ke klien. Terima tiga buah argument, yakni sebuah angka code status, string deskripsi status, dan object header. Contoh pemakaian bisa dilihat pada code di bawah (sesudah daftar fungsi).
  3. setHeader, mengisikan nilai sebuah header. Bila header sudah dibuat dengan writeHead atau setHeader awalnya karena itu nilai akan ditimpakan. Terima dua buah argument, yakni string nama header dan string nilai header.
  4. getHeader, ambil isi pada header (case insensitive) saat sebelum dikirim ke pengguna. Terima satu patokan, yakni string nama header.
  5. removeHeader, hapus header yang sudah dibuat awalnya.
  6. addTrailers, menambah HTTP Trailing Header (header yang ada di belakang message) ke HTTP Response. Fungsi ini mempunyai dua persyaratan: cuma untuk pesan HTTP 1.1 dan pesan harus mempunyai header Trailer. Bila kedua persyaratan tidak tercukupi, fungsi akan diabaikan. Terima parameter berbentuk object dengan pola sama dalam fungsi writeHead.

Penggunaan semua beberapa fungsi yang dijelaskan di atas cukup jelas. Misalkan, untuk writeHead:

response.writeHead(200, 'OK', {
    'Content-Length': content.length,
    'Content-Type': 'text/plain'
});

Daftar dari HTTP Header sendiri bisa diketemukan pada beragam sumber, misalkan: RFC 2616, Wikipedia, dan Tambahan C (masih juga dalam pengembangan).

Harus diingat jika HTTP Header selalu harus dicatat saat sebelum entity body ditulis, karena http.ServerResponse sebagai stream yang perlu ditulis secara berurut. Ini memiliki arti konstruksi header HTTP bisa dilakukan dengan lumayan gampang, cukup dengan ikuti posisi penulisan pesan, yakni:

  1. Panggil writeHeader untuk tuliskan HTTP Response Starting Line dan Header.
  2. Panggil write untuk tuliskan entity bodi, bila dibutuhkan kita dapat mengirim content file disini.
  3. Panggil end untk mengirim ke pengguna.

Misalkan, kita bisa memakai modul fs untuk membaca file dan tuliskan isinya sebagai berikut:

var fs = require('fs');
var file = fs.createReadStream('./index.html');
var content = '';

file.on('data', function (data) {
    content += data;
});

file.on('end', function () {
    result = content;

    response.writeHead(200, 'OK', {
        'Content-Type': 'text/html',
        'Content-Length': result.length
    });

    response.write(result);
    response.end();
});

Seperti yang bisa dilihat pada code di atas, penulisan HTTP Response cukup jelas dan simpel. Seterusnya, kita akan melihat pembuatan sebuah HTTP Klien dengan NodeJS, yang hendak membutuhkan kebalikan dari server NodeJS, yakni pembuatan HTTP Request secara aktif dan pembacaan HTTP Response.

HTTP Klien

Selainnya menyediakan sarana untuk membuat server HTTP lengkap dengan pembacaan HTTP Request dan pembuatan HTTP Response, NodeJS sediakan sarana untuk membuat suatu HTTP Klien. Sejumlah fitur yang diberi untuk HTTP Klien pada NodeJS fokus pada pembuatan HTTP Request dan pembacaan HTTP Response, kebalikan dari yang sudah dilakukan oleh HTTP Server.

HTTP Klien sendiri mempunyai banyak manfaat, misalkan untuk ambil data dari server lain untuk diolah selanjutnya dari segi server. Saat meningkatkan program dari segi klien, manfaat HTTP Klien tentu saja tidak perlu ditanyakan kembali. Program kekinian biasanya akan terkait dengan server berbentuk apa saja, dari HTTP sampai ke prosedur buatan sendiri.

Fungsi khusus yang kita pakai untuk HTTP Klien pada NodeJS yakni http.request. Peranan ini terima dua buah argument, yakni:

  1. options. Parameter ini bisa berbentuk string atau object. Saat berisi string, fungsi akan membaca patokan ini sebagai URL yang ingin dituju oleh klien. URL akan dibaca dengan url.parse. Bila parameter ini berisikan object, kita bisa mengisikan data query yang ingin kita kerjakan. Info selanjutnya ada di sisi selanjutnya.
  2. callback. Parameter diisikan dengan fungsi yang hendak digerakkan saat HTTP Response diberi oleh server yang menerima request. Fungsi mempunyai satu patokan, yakni instant http.IncomingMessage dengan dua properti tambahan, yakni http.IncomingMessage.statusCode dan http.IncomingMessage.statusMessage. Kedua properti berisi data yang serupa tepat dengan namanya.

Object yang bisa kita masukan ke options mempunyai beberapa properti yang bisa kita isilah, yakni:

  • host, nama domain atau IP server arah. Nilai standard ialah "localhost".
  • hostname, sama dengan host. Pakai nilai ini untuk memberikan dukungan url.parse.
  • port, port dari server tujuan. Nilai standard ialah 80.
  • localAddress, antar-muka lokal yang ingin diikatkan pada jaringan lokal.
  • soketPath, Unix Domain Soket (pakai salah satunya dari host:port atau soketPath).
  • metode, metode dari HTTP Request. Nilai standard ialah GET.
  • path, path dari request. Nilai standard ialah /. Bila ada, query string diikutkan, misalkan: indeks.html?data=123. Bila ada watak ilegal sebuah Exception akan dilempar. Untuk saat ini, watak ilegal cuma spasi.
  • headers, sebuah object yang berisi header HTTP.
  • auth, info autentikasi dengan HTTP Basic Authentication (pemakai:pass) bila server membutuhkan info ini.
  • agent, dipakai untuk atur HTTP Agent. Ulasan HTTP Agent akan dilaksanakan di bagian lain.
  • keepAlive, sebuah boolean untuk tentukan apa jaringan masih tetap diletakkan untuk request seterusnya. Nilai standard ialah false.
  • keepAliveMsecs, tentukan waktu jaringan tetap dibuka, dalam ukuran milisecond. Nilai standard ialah 1000. Properti ini cuma berkaitan bila keepAlive berharga true.

Catatan paling akhir, peranan http.request akan kembalikan http.ClientRequest, sebuah object stream.Writable. Bila kita mengirim file atau data lewat request POST, data akan diisikan pada stream ini.

Saat ini silahkan kita lihat contoh penggunaan fungsi http.request:

var http = require('http');

var options = {
    hostname: 'bertzzie.com',
    port: 80,
    path: '/',
    method: 'GET'
};

var req = http.request(options, function (response) {
    console.log(response.statusCode);
    console.log(response.statusMessage);
    console.log(response.headers);
});

req.end();

Code di atas terlihat cukuplah sederhana dan jelas. Salah satu hal yang penting dicatat ialah jika di akhir request, kita harus memanggil req.end untuk menandakan jika request sudah usai. Ini khususnya benar-benar bermanfaat bila kita mengirim data tambahan ke server, sebagai berikut:

var http        = require('http');
var querystring = require('querystring');
var data = querystring.stringify({
    'pesan': 'Halo'
});

var options = {
    hostname: 'contoh.com',
    port: 80,
    path: '/upload',
    method: 'POST',
    headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': data.length
    }
};

var req = http.request(options, function (response) {
    console.log(response.statusCode);
    console.log(response.statusMessage);
    console.log(response.headers);
});

req.write(data);
req.end();

Dari contoh code di atas, kita bisa melihat bagaimana kita panggil contoh.com/unggah dan masukkan data ke request lewat req.write. Seperti stream secara umum, penulisan akan dilakukan saat kita memanggil res.end sebagai pertanda stream sudah habis. Hal inilah yang menyebabkan kita harus memanggil res.end, baik pada kondisi data kosong atau berisi.

Untuk tangani error pada pengiriman request, misalkan bila jaringan terputus atau ada pelanggaran prosedur HTTP, kita bisa dengarkan moment error pada object http.ClientRequest sebagai berikut:

req.on('error', function (e) {
    console.log('Terjadi kesalahan ' + e.message);
});

Feature lain dari HTTP Klien pada NodeJS yakni fungsi yang membantu kita saat membuat request GET secara mudah, yakni http.get. Fungsi ini mempunyai parameter yang serupa dengan http.request, dengan perbedaan khusus yakni:

  1. http.get akan mengirim request GET.
  2. http.get tidak membutuhkan pemanggilan req.end sebagai pertanda akhir request.

Penggunaan dari http.get persis sama dengan http.request, misalkan:

var http = require('http');
var qs   = require('querystring');

var options = {
    host: 'www.google.com',
    port: 80,
    path: '/?' + qs.stringify({'q': 'tutorial javascript'})
};

var req = http.get(options, function(response) {
    var data = '';
    response.on('data', function(chunk) {
        data += chunk;
    });

    response.on('end', function() {
        console.log(data);
    });
});

req.on('error', function(e) {
    console.log("Error: " + e.message);
});

Contoh di atas akhiri ulasan kita tentang HTTP Klien dengan NodeJS.

Penutup

Sampai di bagian ini kita sudah melihat bagaimana NodeJS berhubungan dengan HTTP, baik sebagai HTTP Server atau sebagai HTTP Klien. Kita tidak bisa membuat program situs yang terlampau kompleks dengan yang kita dalami selama ini, tapi kita sudah bisa berbicara dengan beragam HTTP Klien atau Server dengan singkat.