Tutorial: Menggunakan Aurora Tanpa Server dengan AWS AppSync - AWS AppSync

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Tutorial: Menggunakan Aurora Tanpa Server dengan AWS AppSync

AWS AppSync menyediakan sumber data untuk menjalankan SQL perintah terhadap klaster Amazon Aurora Tanpa Server yang telah diaktifkan dengan Data. API Anda dapat menggunakan AppSync resolver untuk mengeksekusi SQL pernyataan terhadap Data dengan kueri, mutasi, dan API langganan GraphQL.

Buat cluster

Sebelum menambahkan sumber RDS data ke AppSync Anda harus terlebih dahulu mengaktifkan Data API pada cluster Aurora Tanpa Server dan mengkonfigurasi rahasia menggunakan. AWS Secrets Manager Anda dapat membuat cluster Aurora Tanpa Server terlebih dahulu dengan: AWS CLI

aws rds create-db-cluster --db-cluster-identifier http-endpoint-test --master-username USERNAME \ --master-user-password COMPLEX_PASSWORD --engine aurora --engine-mode serverless \ --region us-east-1

Ini akan mengembalikan ARN untuk cluster.

Buat Rahasia melalui AWS Secrets Manager Konsol atau juga melalui CLI dengan file input seperti berikut menggunakan USERNAME dan COMPLEX _ PASSWORD dari langkah sebelumnya:

{ "username": "USERNAME", "password": "COMPLEX_PASSWORD" }

Berikan ini sebagai parameter ke AWS CLI:

aws secretsmanager create-secret --name HttpRDSSecret --secret-string file://creds.json --region us-east-1

Ini akan mengembalikan rahasia. ARN

Perhatikan klaster Aurora Tanpa Server dan Rahasia Anda untuk digunakan nanti di AppSync konsol saat membuat sumber data. ARN

Aktifkan Data API

Anda dapat mengaktifkan Data API pada klaster Anda dengan mengikuti petunjuk dalam RDS dokumentasi. Data API harus diaktifkan sebelum menambahkan sebagai sumber AppSync data.

Buat database dan tabel

Setelah Anda mengaktifkan Data Anda, API Anda dapat memastikannya berfungsi dengan aws rds-data execute-statement perintah di file AWS CLI. Ini akan memastikan bahwa cluster Aurora Serverless Anda dikonfigurasi dengan benar sebelum menambahkannya ke Anda. AppSync API Pertama buat database yang disebut TESTDBdengan --sql parameter seperti:

aws rds-data execute-statement --resource-arn "arn:aws:rds:us-east-1:123456789000:cluster:http-endpoint-test" \ --schema "mysql" --secret-arn "arn:aws:secretsmanager:us-east-1:123456789000:secret:testHttp2-AmNvc1" \ --region us-east-1 --sql "create DATABASE TESTDB"

Jika ini berjalan tanpa kesalahan, tambahkan tabel dengan perintah create table:

aws rds-data execute-statement --resource-arn "arn:aws:rds:us-east-1:123456789000:cluster:http-endpoint-test" \ --schema "mysql" --secret-arn "arn:aws:secretsmanager:us-east-1:123456789000:secret:testHttp2-AmNvc1" \ --region us-east-1 \ --sql "create table Pets(id varchar(200), type varchar(200), price float)" --database "TESTDB"

Jika semuanya berjalan tanpa masalah, Anda dapat melanjutkan untuk menambahkan cluster sebagai sumber data di file Anda AppSync API.

GraphQL skema

Sekarang setelah Data API Tanpa Server Aurora Anda aktif dan berjalan dengan tabel, kami akan membuat skema GraphQL dan melampirkan resolver untuk melakukan mutasi dan langganan. Buat yang baru API di AWS AppSync konsol dan arahkan ke halaman Skema, dan masukkan yang berikut ini:

type Mutation { createPet(input: CreatePetInput!): Pet updatePet(input: UpdatePetInput!): Pet deletePet(input: DeletePetInput!): Pet } input CreatePetInput { type: PetType price: Float! } input UpdatePetInput { id: ID! type: PetType price: Float! } input DeletePetInput { id: ID! } type Pet { id: ID! type: PetType price: Float } enum PetType { dog cat fish bird gecko } type Query { getPet(id: ID!): Pet listPets: [Pet] listPetsByPriceRange(min: Float, max: Float): [Pet] } schema { query: Query mutation: Mutation }

Simpan skema Anda dan arahkan ke halaman Sumber Data dan buat sumber data baru. Pilih Database relasional untuk tipe sumber data, dan berikan nama yang ramah. Gunakan nama database yang Anda buat pada langkah terakhir, serta Cluster ARN tempat Anda membuatnya. Untuk Peran, Anda dapat AppSync membuat peran baru atau membuat peran dengan kebijakan yang mirip dengan di bawah ini:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "rds-data:DeleteItems", "rds-data:ExecuteSql", "rds-data:ExecuteStatement", "rds-data:GetItems", "rds-data:InsertItems", "rds-data:UpdateItems" ], "Resource": [ "arn:aws:rds:us-east-1:123456789012:cluster:mydbcluster", "arn:aws:rds:us-east-1:123456789012:cluster:mydbcluster:*" ] }, { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue" ], "Resource": [ "arn:aws:secretsmanager:us-east-1:123456789012:secret:mysecret", "arn:aws:secretsmanager:us-east-1:123456789012:secret:mysecret:*" ] } ] }

Perhatikan ada dua Pernyataan dalam kebijakan ini yang Anda berikan akses peran. Sumber daya pertama adalah cluster Aurora Tanpa Server Anda dan yang kedua adalah milik Anda. AWS Secrets Manager ARN Anda harus menyediakan BOTHARNsdalam konfigurasi sumber AppSync data sebelum mengklik Buat.

Mengkonfigurasi Resolver

Sekarang kita memiliki skema GraphQL yang valid dan RDS sumber data, kita dapat melampirkan resolver ke bidang GraphQL pada skema kita. Kami API akan menawarkan kemampuan berikut:

  1. buat hewan peliharaan melalui Mutasi. createPetlapangan

  2. perbarui hewan peliharaan melalui Mutasi. updatePetlapangan

  3. hapus hewan peliharaan melalui Mutasi. deletePetlapangan

  4. dapatkan satu hewan peliharaan melalui Query. getPetlapangan

  5. daftar semua hewan peliharaan melalui Query. listPetslapangan

  6. daftar hewan peliharaan dalam kisaran harga melalui Query. listPetsByPriceRangelapangan

Mutasi. createPet

Dari editor skema di AWS AppSync konsol, di sisi kanan pilih Lampirkan Resolver untuk. createPet(input: CreatePetInput!): Pet Pilih sumber RDS data Anda. Di bagian template pemetaan permintaan, tambahkan template berikut:

#set($id=$utils.autoId()) { "version": "2018-05-29", "statements": [ "insert into Pets VALUES (:ID, :TYPE, :PRICE)", "select * from Pets WHERE id = :ID" ], "variableMap": { ":ID": "$ctx.args.input.id", ":TYPE": $util.toJson($ctx.args.input.type), ":PRICE": $util.toJson($ctx.args.input.price) } }

SQLPernyataan akan mengeksekusi secara berurutan, berdasarkan urutan dalam array pernyataan. Hasilnya akan kembali dalam urutan yang sama. Karena ini adalah mutasi, kami menjalankan pernyataan pilih setelah sisipan untuk mengambil nilai yang dikomit untuk mengisi template pemetaan respons GraphQL.

Di bagian template pemetaan respons, tambahkan templat berikut:

$utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0])

Karena pernyataan memiliki dua SQL query, kita perlu menentukan hasil kedua dalam matriks yang datang kembali dari database dengan:$utils.rds.toJsonString($ctx.result))[1][0]).

Mutasi. updatePet

Dari editor skema di AWS AppSync konsol, di sisi kanan pilih Lampirkan Resolver untuk. updatePet(input: UpdatePetInput!): Pet Pilih sumber RDS data Anda. Di bagian template pemetaan permintaan, tambahkan template berikut:

{ "version": "2018-05-29", "statements": [ $util.toJson("update Pets set type=:TYPE, price=:PRICE WHERE id=:ID"), $util.toJson("select * from Pets WHERE id = :ID") ], "variableMap": { ":ID": "$ctx.args.input.id", ":TYPE": $util.toJson($ctx.args.input.type), ":PRICE": $util.toJson($ctx.args.input.price) } }

Di bagian template pemetaan respons, tambahkan templat berikut:

$utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0])

Mutasi. deletePet

Dari editor skema di AWS AppSync konsol, di sisi kanan pilih Lampirkan Resolver untuk. deletePet(input: DeletePetInput!): Pet Pilih sumber RDS data Anda. Di bagian template pemetaan permintaan, tambahkan template berikut:

{ "version": "2018-05-29", "statements": [ $util.toJson("select * from Pets WHERE id=:ID"), $util.toJson("delete from Pets WHERE id=:ID") ], "variableMap": { ":ID": "$ctx.args.input.id" } }

Di bagian template pemetaan respons, tambahkan templat berikut:

$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0])

Permintaan. getPet

Sekarang mutasi dibuat untuk skema Anda, kami akan menghubungkan tiga kueri untuk menampilkan cara mendapatkan item individual, daftar, dan menerapkan pemfilteran. SQL Dari editor skema di AWS AppSync konsol, di sisi kanan pilih Lampirkan Resolver untuk. getPet(id: ID!): Pet Pilih sumber RDS data Anda. Di bagian template pemetaan permintaan, tambahkan template berikut:

{ "version": "2018-05-29", "statements": [ $util.toJson("select * from Pets WHERE id=:ID") ], "variableMap": { ":ID": "$ctx.args.id" } }

Di bagian template pemetaan respons, tambahkan templat berikut:

$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0])

Permintaan. listPets

Dari editor skema di AWS AppSync konsol, di sisi kanan pilih Lampirkan Resolver untuk. getPet(id: ID!): Pet Pilih sumber RDS data Anda. Di bagian template pemetaan permintaan, tambahkan template berikut:

{ "version": "2018-05-29", "statements": [ "select * from Pets" ] }

Di bagian template pemetaan respons, tambahkan templat berikut:

$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])

Permintaan. listPetsByPriceRange

Dari editor skema di AWS AppSync konsol, di sisi kanan pilih Lampirkan Resolver untuk. getPet(id: ID!): Pet Pilih sumber RDS data Anda. Di bagian template pemetaan permintaan, tambahkan template berikut:

{ "version": "2018-05-29", "statements": [ "select * from Pets where price > :MIN and price < :MAX" ], "variableMap": { ":MAX": $util.toJson($ctx.args.max), ":MIN": $util.toJson($ctx.args.min) } }

Di bagian template pemetaan respons, tambahkan templat berikut:

$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])

Jalankan mutasi

Sekarang setelah Anda mengonfigurasi semua resolver Anda dengan SQL pernyataan dan menghubungkan GraphQL Anda ke Data Aurora API Tanpa Server Anda, Anda dapat mulai API melakukan mutasi dan kueri. Di AWS AppSync konsol, pilih tab Kueri dan masukkan yang berikut ini untuk membuat Pet:

mutation add { createPet(input : { type:fish, price:10.0 }){ id type price } }

Respons harus berisi id, tipe, dan harga seperti:

{ "data": { "createPet": { "id": "c6fedbbe-57ad-4da3-860a-ffe8d039882a", "type": "fish", "price": "10.0" } } }

Anda dapat memodifikasi item ini dengan menjalankan updatePetmutasi:

mutation update { updatePet(input : { id: ID_PLACEHOLDER, type:bird, price:50.0 }){ id type price } }

Perhatikan bahwa kami menggunakan id yang dikembalikan dari createPetoperasi sebelumnya. Ini akan menjadi nilai unik untuk catatan Anda saat resolver dimanfaatkan. $util.autoId() Anda dapat menghapus catatan dengan cara yang sama:

mutation delete { deletePet(input : {id:ID_PLACEHOLDER}){ id type price } }

Buat beberapa catatan dengan mutasi pertama dengan nilai harga yang berbeda dan kemudian jalankan beberapa kueri.

Jalankan Kueri

Masih di tab Kueri konsol, gunakan pernyataan berikut untuk mencantumkan semua catatan yang telah Anda buat:

query allpets { listPets { id type price } }

Ini bagus tapi mari kita manfaatkan SQL WHEREpredikat yang ada where price > :MIN and price < :MAX di template pemetaan kami untuk Query. listPetsByPriceRangedengan query GraphQL berikut:

query petsByPriceRange { listPetsByPriceRange(min:1, max:11) { id type price } }

Anda seharusnya hanya melihat catatan dengan harga lebih dari $1 atau kurang dari $10. Akhirnya, Anda dapat melakukan kueri untuk mengambil catatan individual sebagai berikut:

query onePet { getPet(id:ID_PLACEHOLDER){ id type price } }

Sanitasi Masukan

Kami menyarankan agar pengembang menggunakan variableMap untuk perlindungan terhadap serangan SQL injeksi. Jika peta variabel tidak digunakan, pengembang bertanggung jawab untuk membersihkan argumen operasi GraphQL mereka. Salah satu cara untuk melakukannya adalah dengan memberikan masukan langkah-langkah validasi spesifik dalam template pemetaan permintaan sebelum eksekusi SQL pernyataan terhadap Data Anda. API Mari kita lihat bagaimana kita dapat memodifikasi template pemetaan permintaan dari listPetsByPriceRange contoh. Alih-alih hanya mengandalkan input pengguna, Anda dapat melakukan hal berikut:

#set($validMaxPrice = $util.matches("\d{1,3}[,\\.]?(\\d{1,2})?",$ctx.args.maxPrice)) #set($validMinPrice = $util.matches("\d{1,3}[,\\.]?(\\d{1,2})?",$ctx.args.minPrice)) #if (!$validMaxPrice || !$validMinPrice) $util.error("Provided price input is not valid.") #end { "version": "2018-05-29", "statements": [ "select * from Pets where price > :MIN and price < :MAX" ], "variableMap": { ":MAX": $util.toJson($ctx.args.maxPrice), ":MIN": $util.toJson($ctx.args.minPrice) } }

Cara lain untuk melindungi terhadap masukan jahat saat mengeksekusi resolver terhadap Data Anda API adalah dengan menggunakan pernyataan yang disiapkan bersama dengan prosedur tersimpan dan input berparameter. Misalnya, dalam resolver untuk listPets menentukan prosedur berikut yang mengeksekusi pilih sebagai pernyataan yang disiapkan:

CREATE PROCEDURE listPets (IN type_param VARCHAR(200)) BEGIN PREPARE stmt FROM 'SELECT * FROM Pets where type=?'; SET @type = type_param; EXECUTE stmt USING @type; DEALLOCATE PREPARE stmt; END

Ini dapat dibuat di Aurora Serverless Instance Anda menggunakan perintah execute sql berikut:

aws rds-data execute-statement --resource-arn "arn:aws:rds:us-east-1:xxxxxxxxxxxx:cluster:http-endpoint-test" \ --schema "mysql" --secret-arn "arn:aws:secretsmanager:us-east-1:xxxxxxxxxxxx:secret:httpendpoint-xxxxxx" \ --region us-east-1 --database "DB_NAME" \ --sql "CREATE PROCEDURE listPets (IN type_param VARCHAR(200)) BEGIN PREPARE stmt FROM 'SELECT * FROM Pets where type=?'; SET @type = type_param; EXECUTE stmt USING @type; DEALLOCATE PREPARE stmt; END"

Kode resolver yang dihasilkan untuk listPets disederhanakan karena kita sekarang hanya memanggil prosedur tersimpan. Minimal, setiap input string harus memiliki tanda kutip tunggal yang lolos.

#set ($validType = $util.isString($ctx.args.type) && !$util.isNullOrBlank($ctx.args.type)) #if (!$validType) $util.error("Input for 'type' is not valid.", "ValidationError") #end { "version": "2018-05-29", "statements": [ "CALL listPets(:type)" ] "variableMap": { ":type": $util.toJson($ctx.args.type.replace("'", "''")) } }

String melarikan diri

Tanda kutip tunggal mewakili awal dan akhir string literal dalam sebuah SQL pernyataan, misalnya. 'some string value'. Untuk memungkinkan nilai string dengan satu atau lebih karakter kutipan tunggal (') untuk digunakan dalam string, masing-masing harus diganti dengan dua tanda kutip tunggal (''). Misalnya, jika string inputnyaNadia's dog, Anda akan menghindarinya untuk SQL pernyataan seperti

update Pets set type='Nadia''s dog' WHERE id='1'