As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Usando o Aurora Serverless com AWS AppSync
AWS AppSync fornece uma fonte de dados para executar SQL comandos em clusters Amazon Aurora Serverless que foram habilitados com dados. API Você pode usar AppSync resolvedores para executar SQL instruções em relação às consultas, mutações e assinaturas do Data API with GraphQL.
Criar cluster
Antes de adicionar uma fonte de RDS dados, AppSync você deve primeiro habilitar os dados API em um cluster Aurora Serverless e configurar um segredo usando. AWS Secrets Manager Você pode criar um cluster Aurora Serverless primeiro com: 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
Isso retornará um ARN para o cluster.
Crie um segredo por meio do AWS Secrets Manager console ou também por meio do CLI com um arquivo de entrada, como o seguinte, usando o USERNAME e COMPLEX _ PASSWORD da etapa anterior:
{ "username": "USERNAME", "password": "COMPLEX_PASSWORD" }
Passe isso como um parâmetro para AWS CLI:
aws secretsmanager create-secret --name HttpRDSSecret --secret-string file://creds.json --region us-east-1
Isso retornará e ARN recuperará o segredo.
Anote o cluster e o segredo ARN do Aurora Serverless para uso posterior no AppSync console ao criar uma fonte de dados.
Habilitar dados API
Você pode habilitar os dados API em seu cluster seguindo as instruções na RDS documentação. Os dados API devem ser habilitados antes de serem adicionados como fonte AppSync de dados.
Criar banco de dados e tabela
Depois de habilitar seus dados, API você pode garantir que eles funcionem com o aws
rds-data execute-statement
comando no AWS CLI. Isso garantirá que seu cluster Aurora Serverless seja configurado corretamente antes de adicioná-lo ao seu. AppSync API Primeiro, crie um banco de dados chamado TESTDBcom o --sql
parâmetro da seguinte forma:
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"
Se isso for executado sem erro, inclua uma tabela com o comando 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"
Se tudo tiver funcionado sem problemas, você pode prosseguir com a adição do cluster como fonte de dados no seu AppSync API.
Esquema do GraphQL
Agora que seus dados API sem servidor do Aurora estão funcionando com uma tabela, criaremos um esquema GraphQL e anexaremos resolvedores para realizar mutações e assinaturas. Crie um novo API no AWS AppSync console, navegue até a página Esquema e digite o seguinte:
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 }
Salve seu esquema e navegue até a página Fontes de dados e crie uma nova fonte de dados. Selecione Banco de dados relacional para o tipo de fonte de dados e forneça um nome amigável. Use o nome do banco de dados que você criou na última etapa, bem como o Cluster em ARN que você o criou. Para a função, você pode AppSync criar uma nova função ou criar uma com uma política semelhante à abaixo:
{ "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:*" ] } ] }
Observe que há duas instruções nesta política que você está concedendo acesso à função. O primeiro recurso é seu cluster Aurora Serverless e o segundo é seu. AWS Secrets Manager ARN Você precisará fornecer a configuração BOTHARNsda fonte de AppSync dados antes de clicar em Criar.
Configurar resolvedores
Agora que temos um esquema GraphQL válido e uma fonte de RDS dados, podemos anexar resolvedores aos campos do GraphQL em nosso esquema. Nós API ofereceremos os seguintes recursos:
-
crie um animal de estimação por meio da Mutação. createPetcampo
-
atualize um animal de estimação por meio da Mutação. updatePetcampo
-
exclua um animal de estimação por meio da Mutação. deletePetcampo
-
obtenha um único animal de estimação por meio do Query. getPetcampo
-
liste todos os animais de estimação por meio da consulta. listPetscampo
-
liste animais de estimação em uma faixa de preço por meio do Query. listPetsByPriceRangecampo
Mutação. createPet
No editor de esquemas no AWS AppSync console, no lado direito, escolha Attach Resolver forcreatePet(input:
CreatePetInput!): Pet
. Selecione a fonte de dados do RDS. Na seção modelo de mapeamento de solicitação, adicione o seguinte modelo:
#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) } }
As SQL instruções serão executadas sequencialmente, com base na ordem na matriz de instruções. Os resultados retornarão na mesma ordem. Como isso é uma mutação, executamos uma instrução select após a insert para recuperar os valores confirmados, a fim de preencher o modelo de mapeamento de resposta do GraphQL.
Na seção modelo de mapeamento de resposta, adicione o seguinte modelo:
$utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0])
Como as declarações têm duas SQL consultas, precisamos especificar o segundo resultado na matriz que volta do banco de dados com:$utils.rds.toJsonString($ctx.result))[1][0])
.
Mutação. updatePet
No editor de esquemas no AWS AppSync console, no lado direito, escolha Attach Resolver forupdatePet(input:
UpdatePetInput!): Pet
. Selecione a fonte de dados do RDS. Na seção modelo de mapeamento de solicitação, adicione o seguinte modelo:
{ "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) } }
Na seção modelo de mapeamento de resposta, adicione o seguinte modelo:
$utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0])
Mutação. deletePet
No editor de esquemas no AWS AppSync console, no lado direito, escolha Attach Resolver fordeletePet(input:
DeletePetInput!): Pet
. Selecione a fonte de dados do RDS. Na seção modelo de mapeamento de solicitação, adicione o seguinte modelo:
{ "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" } }
Na seção modelo de mapeamento de resposta, adicione o seguinte modelo:
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0])
Consulta. getPet
Agora que as mutações foram criadas para seu esquema, conectaremos as três consultas para mostrar como obter itens individuais, listas e aplicar filtragem. SQL No editor de esquemas no AWS AppSync console, no lado direito, escolha Attach Resolver forgetPet(id: ID!): Pet
. Selecione a fonte de dados do RDS. Na seção modelo de mapeamento de solicitação, adicione o seguinte modelo:
{ "version": "2018-05-29", "statements": [ $util.toJson("select * from Pets WHERE id=:ID") ], "variableMap": { ":ID": "$ctx.args.id" } }
Na seção modelo de mapeamento de resposta, adicione o seguinte modelo:
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0])
Consulta. listPets
No editor de esquemas no AWS AppSync console, no lado direito, escolha Attach Resolver forgetPet(id: ID!):
Pet
. Selecione a fonte de dados do RDS. Na seção modelo de mapeamento de solicitação, adicione o seguinte modelo:
{ "version": "2018-05-29", "statements": [ "select * from Pets" ] }
Na seção modelo de mapeamento de resposta, adicione o seguinte modelo:
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])
Consulta. listPetsByPriceRange
No editor de esquemas no AWS AppSync console, no lado direito, escolha Attach Resolver forgetPet(id: ID!):
Pet
. Selecione a fonte de dados do RDS. Na seção modelo de mapeamento de solicitação, adicione o seguinte modelo:
{ "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) } }
Na seção modelo de mapeamento de resposta, adicione o seguinte modelo:
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])
Executar mutações
Agora que você configurou todos os seus resolvedores com SQL instruções e conectou seu API GraphQL aos seus API dados do Aurora sem servidor, você pode começar a realizar mutações e consultas. No AWS AppSync console, escolha a guia Consultas e digite o seguinte para criar um animal de estimação:
mutation add { createPet(input : { type:fish, price:10.0 }){ id type price } }
A resposta deve conter o id, o tipo e o preço da seguinte forma:
{ "data": { "createPet": { "id": "c6fedbbe-57ad-4da3-860a-ffe8d039882a", "type": "fish", "price": "10.0" } } }
Você pode modificar esse item executando a updatePetmutação:
mutation update { updatePet(input : { id: ID_PLACEHOLDER, type:bird, price:50.0 }){ id type price } }
Observe que usamos o id que foi retornado da createPetoperação anterior. Esse será um valor único para o seu registro, já que o resolvedor utilizou $util.autoId()
. Você pode excluir um registro de maneira semelhante:
mutation delete { deletePet(input : {id:ID_PLACEHOLDER}){ id type price } }
Crie alguns registros com a primeira mutação com valores diferentes para preço e execute algumas consultas.
Executar consultas
Ainda na guia Consultas do console, use a seguinte instrução para listar todos os registros que você criou:
query allpets { listPets { id type price } }
Isso é bom, mas vamos aproveitar o SQL WHEREpredicado que havia where price > :MIN and price <
:MAX
em nosso modelo de mapeamento para o Query. listPetsByPriceRangecom a seguinte consulta do GraphQL:
query petsByPriceRange { listPetsByPriceRange(min:1, max:11) { id type price } }
Você só deve ver registros com um preço acima de US$ 1 ou abaixo de US$ 10. Por fim, é possível realizar consultas para recuperar registros individuais da seguinte maneira:
query onePet { getPet(id:ID_PLACEHOLDER){ id type price } }
Limpeza de entradas
Recomendamos que os desenvolvedores usem variableMap
para proteção contra ataques SQL de injeção. Se os mapas de variáveis não forem usados, os desenvolvedores serão responsáveis por limpar os argumentos de suas operações do GraphQL. Uma maneira de fazer isso é fornecer etapas de validação específicas de entrada no modelo de mapeamento da solicitação antes da execução de uma SQL declaração em seus dadosAPI. Vamos ver como podemos modificar o modelo de mapeamento de solicitação do exemplo listPetsByPriceRange
. Em vez de contar apenas com a entrada do usuário, você pode fazer o seguinte:
#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) } }
Outra forma de se proteger contra entradas não autorizadas ao executar resolvedores em seus dados API é usar instruções preparadas junto com procedimentos armazenados e entradas parametrizadas. Por exemplo, no resolvedor para listPets
, defina o seguinte procedimento que executa select como uma instrução preparada:
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
Isso pode ser criado em sua instância do Aurora Serverless usando o seguinte comando sql de execução:
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"
O código de resolução resultante para listPets é simplificado, pois agora simplesmente chamamos o procedimento armazenado. No mínimo, qualquer entrada de string deve ter aspas simples com caracteres de escape.
#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("'", "''")) } }
Escape de strings
As aspas simples representam o início e o fim dos literais de string em uma SQL declaração, por exemplo. 'some string value'
. Para permitir que valores de string com um ou mais caracteres de aspas simples ('
) sejam usados em uma string, cada um deve ser substituído por duas aspas simples (''
). Por exemplo, se a string de entrada forNadia's dog
, você a escapará para a SQL declaração como
update Pets set type='Nadia''s dog' WHERE id='1'