---
title: "OpenResty Adalah NGINX yang Ditingkatkan dengan Permintaan dan Respons Dinamis - API7.ai"
description: "OpenResty adalah NGINX yang ditingkatkan dengan kemampuan untuk menangani permintaan dan respons dinamis, dan artikel ini menjelaskan API untuk memanipulasi Request dan Response di OpenResty, seperti \"ngx.req.set_method\", \"ngx.req.set_uri_args\", \"ngx.req.set_header\", dan lain-lain."
url: "https://api7.ai/id/learning-center/openresty/handling-requests-responses-dynamically"
---

# OpenResty Adalah NGINX yang Ditingkatkan dengan Permintaan dan Respons Dinamis

API7.ai

October 23, 2022

[OpenResty (NGINX + Lua)](https://api7.ai/learning-center/openresty)

Setelah pengenalan sebelumnya, Anda pasti sudah memahami konsep OpenResty dan cara mempelajarinya. Artikel ini akan memandu kita tentang bagaimana OpenResty menangani permintaan dan respons klien.

Meskipun OpenResty adalah server web berbasis NGINX, ia pada dasarnya berbeda dari NGINX: NGINX digerakkan oleh file konfigurasi statis, sementara OpenResty digerakkan oleh API Lua, menawarkan fleksibilitas dan kemampuan pemrograman yang lebih besar.

Mari saya ajak Anda melalui manfaat dari API Lua.

## Kategori API

Pertama, kita perlu tahu bahwa API OpenResty dibagi menjadi beberapa kategori besar berikut.

- Pemrosesan permintaan dan respons.
- Terkait SSL.
- Shared dict.
- Cosocket.
- Menangani lalu lintas empat lapis.
- Proses dan worker.
- Akses ke variabel dan konfigurasi NGINX.
- String, waktu, codec, dan fungsi umum lainnya, dll.

Di sini, saya menyarankan Anda juga membuka dokumentasi API Lua OpenResty dan memeriksanya terhadap [daftar API](https://github.com/openresty/lua-nginx-module/#nginx-api-for-lua) untuk melihat apakah Anda dapat menghubungkannya dengan kategori ini.

API OpenResty tidak hanya ada di proyek `lua-nginx-module`, tetapi juga di proyek `lua-resty-core`, seperti `ngx.ssl`, `ngx.base64`, `ngx.errlog`, `ngx.process`, `ngx.re.split`, `ngx.resp.add_header`, `ngx.balancer`, `ngx.semaphore`, `ngx.ocsp`, dan API lainnya.

Untuk API yang tidak ada di proyek `lua-nginx-module`, Anda perlu memuatnya secara terpisah untuk menggunakannya. Misalnya, jika Anda ingin menggunakan fungsi split, Anda perlu memanggilnya seperti berikut.

```
$ resty -e 'local ngx_re = require "ngx.re"
 local res, err = ngx_re.split("a,b,c,d", ",", nil, {pos = 5})
 print(res)
 '
```

Tentu saja, ini mungkin membingungkan Anda: di proyek `lua-nginx-module`, ada beberapa API yang dimulai dengan `ngx.re.sub`, `ngx.re.find`, dll. Mengapa hanya API `ngx.re.split` yang perlu dimuat terlebih dahulu sebelum digunakan?

Seperti yang kami sebutkan di bab `lua-resty-core` sebelumnya, API OpenResty baru diimplementasikan di repositori `lua-rety-core` dengan cara FFI, sehingga ada perasaan terfragmentasi. Saya berharap masalah ini dapat diselesaikan di masa depan dengan menggabungkan proyek `lua-nginx-module` dan `lua-resty-core`.

## Permintaan

Selanjutnya, mari kita lihat bagaimana OpenResty menangani permintaan dan respons klien. Pertama, mari kita lihat API untuk menangani permintaan, tetapi ada lebih dari 20 API yang dimulai dengan `ngx.req`, jadi bagaimana kita memulainya?

Kita tahu bahwa pesan permintaan HTTP terdiri dari tiga bagian: baris permintaan, header permintaan, dan badan permintaan, jadi saya akan memperkenalkan API dalam tiga bagian ini.

### Baris Permintaan

Pertama adalah baris permintaan, yang berisi metode permintaan, URI, dan versi protokol HTTP. Di NGINX, Anda bisa mendapatkan nilai ini menggunakan variabel bawaan, sementara di OpenResty, ini sesuai dengan API `ngx.var.*`. Mari kita lihat dua contoh.

- Variabel bawaan `$scheme`, yang mewakili nama protokol di NGINX, adalah `http` atau `https`; di OpenResty, Anda dapat menggunakan `ngx.var.scheme` untuk mengembalikan nilai yang sama.
- `$request_method` mewakili metode permintaan seperti `GET`, `POST`, dll.; di OpenResty, Anda dapat mengembalikan nilai yang sama melalui `ngx.var.request_method`.

Anda dapat mengunjungi dokumentasi resmi NGINX untuk mendapatkan daftar lengkap variabel bawaan NGINX: <http://nginx.org/en/docs/http/ngx_http_core_module.html#variables>.

Jadi pertanyaannya muncul: mengapa OpenResty menyediakan API terpisah untuk baris permintaan ketika Anda bisa mendapatkan data dalam baris permintaan dengan mengembalikan nilai variabel seperti `ngx.var.*`?

Hasilnya mengandung banyak faktor:

- Pertama, tidak disarankan untuk membaca `ngx.var` berulang kali karena kinerjanya tidak efisien.
- Kedua, dari pertimbangan aspek yang ramah program, `ngx.var` mengembalikan string, bukan objek Lua. Ini sulit ditangani ketika mendapatkan `args`, yang mungkin mengembalikan banyak nilai.
- Ketiga, dari aspek fleksibilitas, sebagian besar `ngx.var` hanya dapat dibaca, dan hanya beberapa variabel yang dapat ditulis, seperti `$args` dan `limit_rate`. Namun, kita sering perlu memodifikasi metode, URI, dan args.

Oleh karena itu, OpenResty menyediakan beberapa API khusus untuk memanipulasi baris permintaan, yang dapat menulis ulang baris permintaan untuk operasi selanjutnya seperti pengalihan.

Mari kita lihat bagaimana mendapatkan nomor versi protokol HTTP melalui API. API OpenResty `ngx.req.http_version` melakukan hal yang sama dengan variabel NGINX `$server_protocol`: mengembalikan nomor versi protokol HTTP. Namun, nilai kembalian API ini bukan string tetapi dalam format numerik, nilai yang mungkin adalah `2.0`, `1.0`, `1.1`, dan `0.9`. `Nil` dikembalikan jika hasilnya di luar rentang nilai ini.

Mari kita lihat metode mendapatkan permintaan dalam baris permintaan. Seperti yang disebutkan, peran dan nilai kembalian `ngx.req.get_method` dan variabel NGINX `$request_method` adalah sama: dalam format string.

Namun, format parameter dari metode permintaan HTTP saat ini `ngx.req.set_method` bukan string tetapi konstanta numerik bawaan. Misalnya, kode berikut menulis ulang metode permintaan menjadi POST.

```
ngx.req.set_method(ngx.HTTP_POST)
```

Untuk memverifikasi bahwa konstanta bawaan, `ngx.HTTP_POST` memang angka dan bukan string, Anda dapat mencetak nilainya dan melihat apakah outputnya adalah 8.

```
resty -e 'print(ngx.HTTP_POST)'
```

Dengan cara ini, nilai kembalian dari metode `get` adalah string, sementara nilai input dari metode `set` adalah angka. Ini tidak masalah ketika metode set melewati nilai yang membingungkan karena API bisa crash dan melaporkan kesalahan `500`. Namun, dalam logika penilaian berikut:

```
if (ngx.req.get_method() == ngx.HTTP_POST) then
    -- do something
 end
```

Jenis kode ini bekerja dengan baik, tidak melaporkan kesalahan, dan sulit ditemukan bahkan selama tinjauan kode. Saya pernah membuat kesalahan serupa sebelumnya dan masih mengingatnya: saya sudah melalui dua putaran tinjauan kode dan kasus uji yang tidak lengkap untuk mencoba menutupinya. Pada akhirnya, anomali lingkungan online melacak saya ke masalah tersebut.

Tidak ada cara praktis untuk menyelesaikan masalah seperti ini kecuali lebih berhati-hati atau menambahkan lapisan enkapsulasi lain. Ketika Anda merancang API bisnis Anda, Anda juga dapat mempertimbangkan dan menjaga format parameter yang konsisten dari metode `get` dan `set`, bahkan jika Anda perlu mengorbankan beberapa kinerja.

Selain itu, di antara metode untuk menulis ulang baris permintaan, ada dua API, `ngx.req.set_uri` dan `ngx.req.set_uri_args`, yang dapat digunakan untuk menulis ulang URI dan args. Mari kita lihat konfigurasi NGINX ini.

```
rewrite ^ /foo?a=3? break;
```

Jadi, bagaimana kita bisa menyelesaikannya dengan API Lua yang setara? Jawabannya adalah dua baris kode berikut.

```
ngx.req.set_uri_args("a=3")
ngx.req.set_uri("/foo")
```

Jika Anda telah membaca dokumentasi resmi, Anda akan menemukan bahwa `ngx.req.set_uri` memiliki parameter kedua: `jump`, yang secara default adalah "false". Jika Anda mengaturnya sebagai "true", itu sama dengan mengatur flag perintah `rewrite` ke `last` alih-alih `break` dalam contoh di atas.

Namun, saya tidak terlalu menyukai konfigurasi flag dari perintah `rewrite` karena tidak mudah dibaca dan dikenali serta jauh kurang intuitif dan mudah dipelihara daripada kode.

### Header Permintaan

Seperti yang kita tahu, header permintaan HTTP dalam format `key : value`, misalnya:

```
  Accept: text/css,*/*;q=0.1
  Accept-Encoding: gzip, deflate, br
```

Di OpenResty, Anda dapat menggunakan `ngx.req.get_headers` untuk memparsing dan mendapatkan header permintaan, dan tipe nilai kembalian adalah tabel.

```
local h, err = ngx.req.get_headers()
  if err == "truncated" then
      -- one can choose to ignore or reject the current request here
  end
  for k, v in pairs(h) do
      ...
  end
```

Secara default, ini akan mengembalikan 100 header pertama. Jika jumlahnya melebihi 100, itu akan melaporkan kesalahan `truncated`, membiarkan pengembang memutuskan bagaimana menanganinya. Anda mungkin bertanya-tanya mengapa mengambil cara ini, yang akan saya sebutkan nanti di bagian tentang kerentanan keamanan.

Namun, kita harus mencatat bahwa OpenResty tidak menyediakan API khusus untuk mendapatkan header permintaan tertentu, yang berarti tidak ada bentuk seperti `ngx.req.header['host']`. Jika Anda memiliki kebutuhan seperti itu, Anda harus mengandalkan variabel NGINX `$http_xxx` untuk mencapainya. Kemudian di OpenResty, Anda bisa mendapatkannya dengan `ngx.var.http_xxx`.

Sekarang mari kita lihat bagaimana kita harus menulis ulang dan menghapus header permintaan. API untuk kedua operasi ini cukup intuitif:

```
ngx.req.set_header("Content-Type", "text/css")
ngx.req.clear_header("Content-Type")
```

Tentu saja, dokumentasi resmi juga menyebutkan metode lain untuk menghapus header permintaan, seperti mengatur nilai judul ke `nil`, dll. Namun, saya masih merekomendasikan menggunakan `clear_header` untuk melakukannya secara seragam demi kejelasan kode.

### Badan Permintaan

Terakhir, mari kita lihat badan permintaan. Untuk alasan kinerja, OpenResty tidak secara aktif membaca badan permintaan kecuali Anda memaksa mengaktifkan direktif `lua_need_request_body` di `nginx.conf`. Selain itu, untuk badan permintaan yang lebih besar, OpenResty menyimpan konten ke file sementara di disk, sehingga seluruh proses membaca badan permintaan terlihat seperti ini.

```
ngx.req.read_body()
local data = ngx.req.get_body_data()
if not data then
    local tmp_file = ngx.req.get_body_file()
     -- io.open(tmp_file)
     -- ...
 end
```

Kode ini memiliki operasi IO-blocking untuk membaca file disk. Anda harus menyesuaikan konfigurasi `client_body_buffer_size` (16 KB secara default pada sistem 64-bit) untuk meminimalkan operasi blocking; Anda juga dapat mengonfigurasi `client_body_buffer_size` dan `client_max_body_size` menjadi sama dan menanganinya sepenuhnya dalam memori, tergantung pada ukuran memori Anda dan jumlah permintaan bersamaan yang Anda tangani.

Selain itu, badan permintaan dapat ditulis ulang. Dua API `ngx.req.set_body_data` dan `ngx.req.set_body_file` menerima string dan file disk lokal sebagai parameter input untuk menyelesaikan penulisan ulang badan permintaan. Namun, jenis operasi ini tidak umum, dan Anda dapat memeriksa dokumentasi untuk detail lebih lanjut.

## Respons

Setelah permintaan diproses, kita perlu mengirim respons kembali ke klien. Seperti pesan permintaan, pesan respons juga terdiri dari beberapa bagian: baris status, header respons, dan badan respons. Saya akan memperkenalkan API yang sesuai menurut tiga bagian ini.

### Baris Status

Hal utama yang kita perhatikan dalam baris status adalah kode status. Secara default, kode status HTTP yang dikembalikan adalah 200, yang merupakan konstanta `ngx.HTTP_OK` yang dibangun dalam OpenResty. Tetapi dalam dunia kode, selalu ada kode yang menangani kasus yang paling luar biasa.

Jika Anda mendeteksi pesan permintaan dan menemukan bahwa itu adalah permintaan jahat, maka Anda perlu menghentikan permintaan:

```
ngx.exit(ngx.HTTP_BAD_REQUEST)
```

Namun, ada konstanta khusus dalam kode status HTTP OpenResty: `ngx.OK`. Dalam situasi `ngx.exit(ngx.OK)`, permintaan keluar dari fase pemrosesan saat ini dan beralih ke tahap berikutnya alih-alih kembali langsung ke klien.

Tentu saja, Anda juga dapat memilih untuk tidak keluar dan hanya menulis ulang kode status menggunakan `ngx.status`, seperti yang ditulis dalam cara berikut.

```
ngx.status = ngx.HTTP_FORBIDDEN
```

Anda dapat mencarinya di [dokumentasi](https://github.com/openresty/lua-nginx-module/#http-status-constants) jika Anda ingin tahu lebih banyak tentang konstanta kode status.

### Header Respons

Mengenai header respons, ada dua cara Anda dapat mengaturnya. Yang pertama adalah yang paling sederhana.

```
ngx.header.content_type = 'text/plain'
ngx.header["X-My-Header"] = 'blah blah'
ngx.header["X-My-Header"] = nil -- hapus
```

Di sini `ngx.header` menyimpan informasi header respons, yang dapat dibaca, dimodifikasi, dan dihapus.

Cara kedua untuk mengatur header respons adalah `ngx_resp.add_header`, dari repositori `lua-resty-core`, yang menambahkan pesan header, dipanggil dengan:

```
local ngx_resp = require "ngx.resp"
ngx_resp.add_header("Foo", "bar")
```

Perbedaan dengan metode pertama adalah bahwa `add_header` tidak menimpa bidang yang sudah ada dengan nama yang sama.

### Badan Respons

Terakhir, lihat badan respons. Di OpenResty, Anda dapat menggunakan `ngx.say` dan `ngx.print` untuk mengeluarkan badan respons.

```
ngx.say('hello, world')
```

Fungsi dari dua API ini identik, satu-satunya perbedaan adalah bahwa `ngx.say` memiliki baris baru di akhir.

Untuk menghindari ketidakefisienan penggabungan string, `ngx.say / ngx.print` mendukung string dan format array sebagai parameter.

```
$ resty -e 'ngx.say({"hello", ", ", "world"})'
 hello, world
```

Metode ini melewati penggabungan string di tingkat Lua dan membiarkannya ditangani oleh fungsi C.

## Ringkasan

Mari kita tinjau konten hari ini. Kami memperkenalkan API OpenResty yang terkait dengan pesan permintaan dan respons. Seperti yang Anda lihat, API OpenResty lebih fleksibel dan kuat daripada direktif NGINX.

Akibatnya, apakah API Lua yang disediakan oleh OpenResty cukup untuk memenuhi kebutuhan Anda ketika Anda menangani permintaan HTTP? Silakan tinggalkan komentar Anda dan bagikan artikel ini dengan kolega dan teman Anda sehingga kita dapat berkomunikasi dan meningkatkan bersama.

Share article link

Share

Related Posts

[![OpenResty FAQ | Bagaimana OpenResty Digunakan dalam Praktik](https://static.api7.ai/uploads/2023/02/12/jbv9M0zi_Hello%20World%20in%20OpenResty%20%283%29.png)](https://api7.ai/learning-center/openresty/faq-5)

## [OpenResty FAQ | Bagaimana OpenResty Digunakan dalam Praktik](https://api7.ai/learning-center/openresty/faq-5)

[![Bagian 3: Cara Membangun Microservices API Gateway Menggunakan OpenResty](https://static.api7.ai/uploads/2023/02/07/3XJXY9Jy_45.png)](https://api7.ai/learning-center/openresty/how-to-build-a-microservices-api-gateway-part-3)

## [Bagian 3: Cara Membangun Microservices API Gateway Menggunakan OpenResty](https://api7.ai/learning-center/openresty/how-to-build-a-microservices-api-gateway-part-3)

Table of Contents

- [Kategori API](#kategori-api)

- [Permintaan](#permintaan)

  - [Baris Permintaan](#baris-permintaan)
  - [Header Permintaan](#header-permintaan)
  - [Badan Permintaan](#badan-permintaan)

- [Respons](#respons)

  - [Baris Status](#baris-status)
  - [Header Respons](#header-respons)
  - [Badan Respons](#badan-respons)

- [Ringkasan](#ringkasan)
