---
title: "Pengenalan API Umum dalam OpenResty - API7.ai"
description: "Artikel ini akan memperkenalkan Anda pada penggunaan API umum OpenResty untuk manipulasi waktu, ekspresi reguler, dan masalah umum lainnya."
url: "https://api7.ai/id/learning-center/openresty/introduction-openresty-common-apis"
---

# Pengenalan API Umum dalam OpenResty

API7.ai

November 4, 2022

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

Pada artikel sebelumnya, Anda telah mengenal banyak API Lua penting di OpenResty. Hari ini, kita akan mempelajari beberapa API umum lainnya, terutama yang terkait dengan ekspresi reguler, waktu, proses, dll.

## API Terkait Ekspresi Reguler

Mari kita mulai dengan melihat ekspresi reguler yang paling sering digunakan dan paling penting. Di OpenResty, kita harus menggunakan set API yang disediakan oleh `ngx.re.*` untuk menangani logika yang terkait dengan ekspresi reguler, alih-alih menggunakan pencocokan pola Lua. Ini bukan hanya untuk alasan kinerja, tetapi juga karena regularitas Lua bersifat mandiri dan bukan spesifikasi `PCRE`, yang akan menyulitkan bagi sebagian besar pengembang.

Pada artikel sebelumnya, Anda telah mengenal beberapa API `ngx.re.*`, dokumentasinya sangat detail. Jadi, saya tidak akan mendaftarnya lagi. Di sini, saya akan memperkenalkan dua API berikut secara terpisah.

### `ngx.re.split`

Yang pertama adalah `ngx.re.split`. Pemotongan string adalah fungsi yang sangat umum, dan OpenResty juga menyediakan API yang sesuai, tetapi banyak pengembang tidak dapat menemukan fungsi tersebut dan memilih untuk mengimplementasikannya sendiri.

Mengapa? API `ngx.re.split` tidak ada di `lua-nginx-module` tetapi di `lua-resty-core`; tidak ada di dokumentasi beranda `lua-resty-core` tetapi di dokumentasi direktori tingkat ketiga `lua-resty-core/lib/ngx/re.md`. Akibatnya, banyak pengembang sama sekali tidak menyadari keberadaan API ini.

Demikian pula, API yang sulit ditemukan termasuk `ngx_resp.add_header`, `enable_privileged_agent`, dll., yang telah kita sebutkan sebelumnya. Jadi, bagaimana kita dapat dengan cepat menyelesaikan masalah ini? Selain membaca dokumentasi beranda `lua-resty-core`, Anda perlu membaca dokumentasi `*.md` di direktori `lua-resty-core/lib/ngx/` juga.

### `lua_regex_match_limit`

Kedua, saya ingin memperkenalkan `lua_regex_match_limit`. Kami belum membahas perintah NGINX yang disediakan oleh OpenResty sebelumnya karena, dalam kebanyakan kasus, nilai default sudah cukup, dan tidak perlu memodifikasinya saat runtime. Pengecualian untuk ini adalah perintah `lua_regex_match_limit`, yang terkait dengan ekspresi reguler.

Kita tahu bahwa jika kita menggunakan mesin reguler yang diimplementasikan berdasarkan backtracking NFA, maka ada risiko Catastrophic Backtracking, di mana reguler terlalu banyak melakukan backtracking saat mencocokkan, menyebabkan CPU menjadi 100% dan layanan terblokir.

Setelah backtrace katastropik terjadi, kita perlu menggunakan `gdb` untuk menganalisis dump atau menggunakan `systemtap` untuk menganalisis lingkungan online untuk melokalisasinya. Sayangnya, mendeteksinya sebelumnya tidak mudah karena hanya permintaan khusus yang akan memicunya. Ini memungkinkan penyerang memanfaatkan ini, dan `ReDoS` (RegEx Denial of Service) mengacu pada jenis serangan ini.

Di sini, saya terutama memperkenalkan cara menggunakan baris kode berikut di OpenResty untuk menghindari masalah di atas dengan sederhana dan efektif:

`lua_regex_match_limit` digunakan untuk membatasi jumlah backtracking oleh mesin reguler `PCRE`. Dengan cara ini, bahkan jika terjadi backtracking katastropik, konsekuensinya akan dibatasi dalam rentang yang tidak akan membuat CPU Anda penuh.

```
lua_regex_match_limit 100000;
```

## API Terkait Waktu

API waktu yang paling sering digunakan adalah `ngx.now`, yang mencetak timestamp saat ini, seperti baris kode berikut:

```
resty -e 'ngx.say(ngx.now())'
```

Seperti yang dapat Anda lihat dari hasil cetakan, `ngx.now` mencakup bagian pecahan, sehingga lebih akurat. API terkait `ngx.time` hanya mengembalikan bagian integer dari nilai tersebut. Yang lainnya, `ngx.localtime`, `ngx.utctime`, `ngx.cookie_time`, dan `ngx.http_time` terutama digunakan untuk mengembalikan dan memproses waktu dalam format yang berbeda. Jika Anda ingin menggunakannya, Anda dapat memeriksa dokumentasinya, mereka tidak sulit dipahami, jadi saya tidak perlu membahasnya.

Namun, perlu disebutkan bahwa **API ini yang mengembalikan waktu saat ini, jika tidak dipicu oleh operasi IO jaringan non-blocking, akan selalu mengembalikan nilai yang di-cache daripada waktu real-time saat ini seperti yang kita inginkan**. Lihatlah contoh kode berikut:

```
$ resty -e 'ngx.say(ngx.now())
os.execute("sleep 1")
ngx.say(ngx.now())'
```

Di antara dua panggilan ke `ngx.now`, kami menggunakan fungsi blocking Lua untuk tidur selama `1` detik, tetapi timestamp yang dikembalikan sama pada kedua kesempatan, seperti yang ditunjukkan oleh hasil cetakan.

Jadi, bagaimana jika kita menggantinya dengan fungsi tidur non-blocking? Misalnya, kode baru berikut:

```
$ resty -e 'ngx.say(ngx.now())
ngx.sleep(1)
ngx.say(ngx.now())'
```

Ini akan mencetak timestamp yang berbeda. Ini membawa kita ke `ngx.sleep`, fungsi tidur non-blocking. Selain tidur selama waktu yang ditentukan, fungsi ini memiliki tujuan khusus lainnya.

Misalnya, jika Anda memiliki sepotong kode yang melakukan perhitungan intensif, yang memakan banyak waktu, permintaan yang sesuai dengan kode ini akan terus mengambil alih sumber daya worker dan CPU selama waktu ini, menyebabkan permintaan lain mengantri dan tidak mendapatkan respons tepat waktu. Pada titik ini, kita dapat menyisipkan `ngx.sleep(0)` untuk membuat kode ini melepaskan kontrol sehingga permintaan lain juga dapat diproses.

## API Worker dan Proses

OpenResty menyediakan API `ngx.worker.*` dan `ngx.process.*` untuk mendapatkan informasi tentang worker dan proses. Yang pertama terkait dengan proses worker Nginx, sedangkan yang kedua mengacu pada semua proses Nginx secara umum, tidak hanya proses worker, tetapi juga proses master, proses istimewa, dan sebagainya.

## Masalah Nilai `true` dan `null`

Terakhir, mari kita lihat masalah nilai `true` dan `null`. Di OpenResty, penentuan nilai `true` dan `null` telah menjadi titik yang sangat merepotkan dan membingungkan.

Mari kita lihat definisi nilai `true` di Lua: kecuali `nil` dan `false`, semuanya adalah nilai `true`.

Jadi, nilai `true` juga akan mencakup `0`, `string` kosong, `table` kosong, dll.

Mari kita lihat `nil` di Lua, yang berarti `undefined`. Misalnya, jika Anda mendeklarasikan variabel tetapi belum menginisialisasinya, nilainya adalah `nil`.

```
$ resty -e 'local a
ngx.say(type(a))'
```

Dan `nil` juga merupakan tipe data di Lua. Setelah memahami dua poin ini, mari kita lihat masalah lain yang berasal dari dua definisi ini.

### `ngx.null`

Masalah pertama adalah `ngx.null`. Karena `nil` Lua tidak dapat digunakan sebagai nilai `table`, OpenResty memperkenalkan `ngx.null` sebagai nilai `null` dalam tabel.

```
$ resty -e  'print(ngx.null)'
null
```

```
$ resty -e 'print(type(ngx.null))'
userdata
```

Seperti yang dapat Anda lihat dari dua potong kode di atas, `ngx.null` dicetak sebagai `null`, dan tipenya adalah `userdata`, jadi apakah itu dapat diperlakukan sebagai nilai `false`? Tentu saja tidak. Nilai boolean dari `ngx.null` adalah `true`.

```
$ resty -e 'if ngx.null then
ngx.say("true")
end'
```

Jadi, ingatlah bahwa hanya `nil` dan `false` yang merupakan nilai `false`. Jika Anda melewatkan poin ini, sangat mudah untuk terjebak dalam jebakan, misalnya, ketika Anda menggunakan `lua-resty-redis` dan membuat penilaian berikut:

```
local res, err = red:get("dog")
if not res then
    res = res + "test"
end
```

Jika nilai kembalian `res` adalah `nil`, panggilan fungsi telah gagal; jika `res` adalah `ngx.null`, kunci `dog` tidak ada di redis, maka kode akan crash jika kunci `dog` tidak ada.

### `cdata:NULL`

Masalah kedua adalah `cdata:NULL`. Ketika Anda memanggil fungsi C melalui antarmuka LuaJIT FFI, dan fungsi mengembalikan pointer `NULL`, maka Anda akan menemukan jenis nilai `null` lain, `cdata:NULL`.

```
$ resty -e 'local ffi = require "ffi"
local cdata_null = ffi.new("void*", nil)
if cdata_null then
    ngx.say("true")
end'
```

Seperti `ngx.null`, `cdata:NULL` juga `true`. Tetapi yang lebih membingungkan adalah bahwa kode berikut, yang mencetak `true`, berarti bahwa `cdata:NULL` setara dengan `nil`.

```
$ resty -e 'local ffi = require "ffi"
local cdata_null = ffi.new("void*", nil)
ngx.say(cdata_null == nil)'
```

Jadi, bagaimana kita harus menangani `ngx.null` dan `cdata:NULL`? Bukan solusi yang baik untuk membiarkan lapisan aplikasi peduli dengan masalah ini. Lebih baik melakukan pembungkusan tingkat kedua dan tidak membiarkan pemanggil mengetahui detail ini.

Lebih baik melakukan pembungkusan tingkat kedua dan tidak membiarkan pemanggil mengetahui detail ini.

### `cjson.null`

Terakhir, mari kita lihat nilai `null` yang muncul di `cjson`. Pustaka `cjson` mengambil `NULL` dalam json, mendekodenya menjadi `lightuserdata` Lua, dan menggunakan `cjson.null` untuk mewakilinya.

```
$ resty -e 'local cjson = require "cjson"
local data = cjson.encode(nil)
local decode_null = cjson.decode(data)
ngx.say(decode_null == cjson.null)'
```

`nil` Lua menjadi `cjson.null` setelah dienkode dan didekode oleh JSON. Seperti yang dapat Anda bayangkan, ini diperkenalkan untuk alasan yang sama dengan `ngx.null`, karena `nil` tidak dapat digunakan sebagai nilai dalam `table`.

Sejauh ini, apakah Anda bingung dengan begitu banyak jenis nilai `null` di OpenResty? Jangan khawatir. Baca bagian ini beberapa kali dan susun sendiri, maka Anda tidak akan bingung. Tentu saja, kita perlu berpikir lebih banyak di masa depan tentang apakah itu berfungsi ketika menulis sesuatu seperti `if not foo then`.

## Ringkasan

Artikel hari ini memperkenalkan Anda pada API Lua yang umum digunakan di OpenResty.

Terakhir, saya akan meninggalkan Anda dengan pertanyaan: Dalam contoh `ngx.now`, mengapa nilai `ngx.now` tidak dimodifikasi ketika tidak ada operasi `yield`? Silakan bagikan pendapat Anda di komentar, dan juga silakan bagikan artikel ini 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

- [API Terkait Ekspresi Reguler](#api-terkait-ekspresi-reguler)

  - [`ngx.re.split`](#ngxresplit)
  - [`lua_regex_match_limit`](#lua_regex_match_limit)

- [API Terkait Waktu](#api-terkait-waktu)

- [API Worker dan Proses](#api-worker-dan-proses)

- [Masalah Nilai `true` dan `null`](#masalah-nilai-true-dan-null)

  - [`ngx.null`](#ngxnull)
  - [`cdata:NULL`](#cdatanull)
  - [`cjson.null`](#cjsonnull)

- [Ringkasan](#ringkasan)
