Pengembangan Plugin Kustom untuk APISIX dengan Lua dan ChatGPT
June 12, 2023
Salah satu fitur utama dari Apache APISIX adalah kemampuannya untuk diperluas melalui plugin. APISIX memungkinkan Anda untuk membangun plugin kustom sendiri untuk menambahkan fungsionalitas tambahan dan mengelola lalu lintas API dengan lebih efisien. Seringkali, Anda menggunakan bahasa pemrograman Lua untuk mengimplementasikan plugin baru atau memanfaatkan plugin runner untuk mengembangkan plugin dalam bahasa pemrograman favorit Anda. Namun, APISIX memiliki dukungan terbaik untuk Lua. Setelah menulis beberapa plugin untuk APISIX dalam Lua, saya menyadari bahwa Anda tidak perlu mengetahui dasar-dasar pemrograman Lua atau menjadi ahli dalam bahasa ini sama sekali ketika teman ChatGPT Anda selalu bersama Anda. Misalnya, dengan latar belakang saya dalam Java dan C#, saya dapat memahami kode dan logika yang ditulis dalam Lua dan saya yakin Anda juga bisa melakukannya.
Artikel ini akan memandu Anda melalui proses pengembangan plugin kustom baru yang disebut file-proxy untuk APISIX menggunakan Lua dan ChatGPT (Kami menggunakannya untuk menulis beberapa kode Lua untuk kami). Plugin ini akan digunakan untuk mengekspos file statis melalui API dan mengambil file dari URL yang ditentukan.
APISIX dibangun untuk meningkatkan fungsionalitas yang ada dari Nginx, dan Nginx menyediakan kumpulan modul Lua yang dapat digunakan kembali yang dimanfaatkan oleh APISIX.
Tujuan pembelajaran
Anda akan mempelajari hal-hal berikut sepanjang artikel:
- Bagaimana mengembangkan plugin file-proxy baru.
- Bagaimana menggunakan ChatGPT secara efisien untuk menghasilkan kode Lua.
- Langkah-langkah untuk membangun plugin Anda sendiri untuk APISIX.
Kasus penggunaan plugin file-proxy baru
Sebelum melompat ke implementasi plugin yang sebenarnya, mari kita pahami terlebih dahulu mengapa kita membutuhkan plugin ini. Pada saat penulisan artikel ini, APISIX mungkin tidak menyediakan plugin bawaan untuk kasus yang serupa. Itulah mengapa kita akan membangun yang baru. Seringkali, kita ingin mengekspos file statis (Yaml, JSON, JavaScript, CSS, atau file gambar) melalui API.
Misalnya, APISIX API Gateway berfungsi sebagai pintu depan dalam aplikasi Anda untuk merutekan permintaan masuk ke beberapa endpoint API, ini adalah tempat yang tepat untuk mendefinisikan semua URL server, jalur, parameter, deskripsi dari setiap endpoint API serta input dan outputnya. Dan Anda membangun spesifikasi OpenAPI untuk mendokumentasikan API. File .yaml OpenAPI seperti peta yang memandu pengguna API Anda dalam memahami dan berinteraksi dengan API Anda. Dengan menyediakan jalur file openapi.yaml (di mana file tersebut disimpan di server Anda) ke plugin, Anda dapat mengambil dan menyajikan file tersebut langsung melalui gateway API Anda, memberikan antarmuka yang konsisten untuk konsumen API. Kemudian pengguna API Anda dapat mengakses file .yaml di URL yang ditentukan (https://example.com/openapi.yaml).
Ada juga kasus penggunaan lainnya, Anda mungkin berpikir untuk menggunakan plugin file-proxy ini sebagai pengganti sederhana untuk Content Delivery Network (CDN). Jika Anda memiliki aplikasi skala kecil dan tidak ingin menggunakan CDN yang lengkap, Anda dapat menggunakan plugin file-proxy untuk menyajikan file statis dari lokasi tertentu. Plugin file-proxy dapat digunakan sebagai lapisan caching untuk file. Jika Anda memiliki file yang mahal untuk diambil atau dihasilkan, Anda dapat menggunakan plugin untuk mengambil file sekali dan kemudian menyajikan versi yang di-cache untuk permintaan berikutnya.
Langkah-langkah untuk mengembangkan plugin file-proxy
Kita akan menjalankan APISIX secara lokal dan API Gateway kita akan dihosting di
http://localhost:9080. Ketika pengembangan selesai, Anda dapat mendeploynya ke server Anda atau penyedia cloud apa pun. Pada dasarnya, kita ingin menempatkan file openapi.yaml ke jalur http://localhost:9080/openapi.yaml. Anda akan mempelajari cara mencapai ini.
Prasyarat
- Sebelum memulai, ada baiknya Anda memiliki pemahaman dasar tentang APISIX. Keakraban dengan gateway API, dan konsep-konsep utamanya seperti rute, upstream, Admin API, plugin. Pemahaman dasar tentang protokol HTTP juga bermanfaat.
- Docker digunakan untuk menginstal etcd dan APISIX yang dikontainerisasi.
- curl digunakan untuk mengirim permintaan ke APISIX Admin API. Anda juga dapat menggunakan alat seperti Postman untuk berinteraksi dengan API.
Memahami proyek demo dan file
Kami akan memanfaatkan proyek demo file-proxy yang ada di GitHub. Ini memiliki struktur yang cukup mirip dengan repo contoh docker Apisix yang ada, hanya saja kami menghapus file yang tidak diperlukan untuk menjaga demo tetap sederhana. Proyek ini memiliki 3 folder, docker-compose.yml, dan file sampel openapi.yaml.
- docker-compose.yml mendefinisikan dua kontainer, satu untuk APISIX dan satu lagi untuk etcd (yang merupakan penyimpanan konfigurasi untuk APISIX).
- Folder custom-plugins berisi implementasi plugin file-proxy dalam Lua. Kami akan meninjau ini di bagian berikutnya.
- openapi.yaml hanyalah contoh spesifikasi OpenAPI yang kami ekspos.
Implementasi plugin file-proxy
Kami mulai dengan menanyakan ChatGPT bagaimana mengimplementasikan plugin file-proxy kustom untuk APISIX dalam Lua. ChatGPT menghasilkan panduan yang hampir mirip dengan implementasi sebenarnya, tetapi jawabannya terlalu abstrak dan ketika Anda mengikuti prosesnya, Anda akan berakhir dengan plugin yang tidak berfungsi. Namun, ini membantu kami mengekstrak kode Lua yang berguna. Jika kita mengetahui proses nyata dalam mengembangkan plugin, akan lebih mudah untuk menggabungkan kedua pengetahuan tersebut dalam praktik.

1. Buat File Lua
Kami membuat file Lua baru yang kosong di direktori /custom-plugins dari proyek. Nama file harus sesuai dengan nama plugin kami. Misalnya, jika plugin Anda bernama file-proxy, Anda harus membuat file bernama file-proxy.lua.
2. Daftarkan plugin di APISIX
APISIX perlu mengetahui di mana file plugin ini berada dan dapat menjalankan plugin tersebut dengan sesuai. Untuk melakukannya, kita harus terlebih dahulu mendefinisikan jalur file di mana APISIX menemukan file file-proxy.lua dengan menambahkan jalur file ke atribut extra_lua_path dari APISIX di config.yaml.
apisix: extra_lua_path: "/opt/?.lua" node_listen: 9080
Sekarang Anda mungkin bertanya mengapa jalur file diatur ke /opt/?.lua. Karena kami menjalankan APISIX menggunakan docker. Anda mungkin memperhatikan ini di file docker-compose.yml ada 3 volume ./custom-plugins:/opt/apisix/plugins:ro
volumes: - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro - ./openapi.yaml:/usr/local/apisix/conf/openapi.yaml:ro - ./custom-plugins:/opt/apisix/plugins:ro
Ini memasang direktori lokal ./custom-plugins di mana file file-proxy.lua kami dengan implementasi plugin kustom sebagai volume baca-saja di kontainer docker di jalur /opt/apisix/plugins. Ini memungkinkan plugin kustom ditambahkan ke APISIX dalam runtime ke jalur lain di Docker yang berada di dalam /opt/?.lua. Demikian pula, dua file lainnya kami salin ke folder Docker.
Langkah selanjutnya, kami mengaktifkan plugin dalam daftar plugin APISIX. Ini dilakukan dengan menambahkan nama plugin ke daftar plugins di file konfigurasi APISIX (config.yaml):
plugins: - file-proxy
Perhatikan bahwa tindakan ini akan menimpa semua plugin default yang ada yang ditentukan dalam config-default.yaml. Anda perlu menambahkan secara manual plugin lain dengan nama mereka jika Anda ingin menggunakan plugin kustom Anda dalam kombinasi.
3. Pembahasan kode Lua plugin file-proxy
Sampai sekarang, kami hanya mendaftarkan plugin yang tidak melakukan apa-apa. Sekarang saatnya untuk mengimplementasikannya. Logika plugin diimplementasikan sebagai fungsi Lua. Anda dapat memeriksa bagaimana hal ini dilakukan di file-proxy.lua.
Mari kita uraikan file file-proxy.lua untuk lebih memahami struktur kode dan alur yang membantu Anda membuat plugin baru sendiri. Anda dapat dengan mudah meminta ChatGPT untuk menjelaskan kode Lua:

Sebenarnya, kami mendapatkan penjelasan yang cukup baik tentang kode tersebut (Karena sebagian ditulis oleh ChatGPT).

Saya hanya akan memandu Anda melalui bagian penting dari kode ini sehingga Anda tidak tersesat atau sepenuhnya bergantung pada AI untuk menulis plugin Anda.
4. Struktur file plugin
Setiap file plugin Lua harus memiliki struktur berikut:
1. Modul: Anda mengimpor modul/pustaka yang diperlukan untuk plugin
local core = require("apisix.core") ...
2. Nama plugin: Setiap plugin memiliki nama unik, bisa sama dengan nama file Lua kami.
local plugin_name = "file-proxy"
3. Skema plugin: Setiap plugin memiliki skema plugin, di mana kami biasanya menentukan input ke plugin. Input yang akan kami berikan dari konfigurasi rute APISIX, yang dapat Anda lihat nanti ketika kami menguji plugin. Untuk plugin file-proxy, plugin memerlukan jalur file untuk membaca file dan mengembalikan respons sehingga parameter kami adalah path yang bertipe string. Anda memahami skema seperti deklarasi metode dengan parameter dalam bahasa pemrograman lain.
local plugin_schema = { type = "object", properties = { path = { type = "string" -- Jalur file yang akan disajikan }, }, required = {"path"} -- Jalur adalah bidang yang diperlukan }
4. Definisi plugin: Ini adalah bagian yang sangat penting dari implementasi plugin yang kami definisikan sebagai tabel dengan properti untuk version, priority, name, dan schema. name dan schema adalah nama dan skema plugin yang didefinisikan sebelumnya. version dan priority digunakan oleh APISIX untuk mengelola plugin. Versi biasanya merujuk pada versi yang sedang digunakan seperti versi API. Jika Anda mempublikasikan dan memperbarui logika plugin Anda, itu akan menjadi 1.1 (Anda dapat mengatur versi apa pun yang Anda inginkan). Tetapi Anda perlu sangat berhati-hati dalam memilih prioritas. Bidang priority menentukan urutan dan fase di mana plugin Anda harus dieksekusi. Misalnya, plugin 'ip-restriction', dengan prioritas 3000, akan dieksekusi sebelum 'example-plugin', yang memiliki prioritas 0. Ini karena nilai prioritas yang lebih tinggi dari plugin 'ip-restriction'. Jika Anda mengembangkan plugin Anda sendiri, pastikan bahwa Anda mengikuti urutan plugin agar tidak mengacaukan urutan plugin yang ada. Anda dapat memeriksa urutan plugin yang ada di file config-default.yaml dan membuka Panduan Pengembangan Plugin Apache APISIX untuk menentukan.
local _M = { version = 1.0, priority = 1000, name = plugin_name, schema = plugin_schema }
5. Pemeriksaan skema: Fungsi Lua check_schema digunakan untuk memvalidasi plugin dalam konfigurasi rute (Anda akan melihatnya segera di bagian pengujian) terhadap skema plugin yang kami definisikan sebelumnya.
-- Fungsi untuk memeriksa apakah konfigurasi plugin benar function _M.check_schema(conf) -- Validasi konfigurasi terhadap skema local ok, err = core.schema.check(plugin_schema, conf) -- Jika validasi gagal, kembalikan false, dan kesalahan if not ok then return false, err end -- Jika validasi berhasil, kembalikan true return true end
6. Logika plugin: Fungsi access adalah fungsi inti di mana kami dapat menulis logika utama plugin. Ini dipanggil selama fase akses dari pipeline pemrosesan permintaan Nginx dan kami mengontrol lalu lintas dan menulis instruksi kustom. Untuk file-proxy, kami perlu membuka file yang ditentukan dalam konfigurasi plugin, membaca kontennya, dan mengembalikan konten sebagai respons. Jika file tidak dapat dibuka, itu akan mencatat kesalahan dan mengembalikan status 404 Not Found. Ini adalah tempat yang tepat kami memberikan pekerjaan ini kepada ChatGPT:

Setelah kami menyusun dan merestrukturisasi kode, berikut adalah tampilannya:
function _M.access(conf, ctx) -- Buka file yang ditentukan dalam konfigurasi local fd = io.open(conf.path, "rb") -- Jika file berhasil dibuka, baca kontennya dan kembalikan sebagai respons if fd then local content = fd:read("*all") fd:close() ngx.header.content_length = #content ngx.say(content) ngx.exit(ngx.OK) else -- Jika file tidak dapat dibuka, catat kesalahan dan kembalikan status 404 Not Found ngx.exit(ngx.HTTP_NOT_FOUND) core.log.error("File tidak ditemukan: ", conf.path, ", info kesalahan: ", err) end end
7. Logika logging: Selalu lebih disukai untuk mencatat konfigurasi plugin sehingga kami dapat melakukan debug dan memeriksa apakah plugin berfungsi seperti yang kami harapkan. Kami dapat mencatat permintaan ke plugin dan respons.
-- Fungsi yang akan dipanggil selama fase log function _M.log(conf, ctx) -- Catat konfigurasi plugin dan konteks permintaan core.log.warn("conf: ", core.json.encode(conf)) core.log.warn("ctx: ", core.json.encode(ctx, true)) end
Instal Apache APISIX
Setelah kami mempelajari cara mengembangkan plugin file-proxy kustom kami, mendaftarkannya di APISIX. Sekarang saatnya untuk menguji plugin. Anda dapat dengan mudah menginstal proyek apisix-file-proxy-plugin-demo dengan menjalankan docker compose up dari folder root proyek setelah Anda fork/klon proyek.
Buat rute dengan plugin file-proxy
Untuk menggunakan dan menguji plugin file-proxy baru kami, kami perlu membuat rute di APISIX yang menggunakan plugin:
curl "http://127.0.0.1:9180/apisix/admin/routes/open-api-definition" -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "name":"OpenAPI Definition", "desc":"Rute untuk file Definisi OpenAPI", "uri":"/openapi.yaml", "plugins":{ "file-proxy":{ "path":"/usr/local/apisix/conf/openapi.yaml" } } }'
Anda dapat meminta ChatGPT untuk menjelaskan konfigurasi di atas:

Uji plugin
Kemudian, Anda dapat mengirim permintaan cURL ke rute atau membuka tautan http://127.0.0.1:9080/openapi.yaml di browser Anda. Responsnya harus berupa konten dari file openapi.yaml di URL yang ditentukan.
curl -i http://127.0.0.1:9080/openapi.yaml
Plugin bekerja seperti yang kami harapkan. Dengan konfigurasi plugin ini, Anda sekarang dapat mengakses file apa pun menggunakan rute yang ditentukan.
Ringkasan
Mengembangkan plugin kustom untuk APISIX dengan Lua adalah cara yang kuat untuk memperluas fungsionalitas gateway API. Kami telah menunjukkan cara membuat plugin file-proxy dalam posting ini, mendefinisikan definisi dan skema plugin, memvalidasi konfigurasi plugin, dan mengimplementasikan logika kustom selama fase akses dan log dari pipeline pemrosesan permintaan di APISIX. ChatGPT membantu kami menulis kode Lua untuk fungsionalitas utama dengan mengisi pengetahuan kami yang kurang dalam bahasa pemrograman ini. Selamat coding!