

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 resolvedores de pipeline em AWS AppSync
<a name="tutorial-pipeline-resolvers"></a>

**nota**  
Agora, oferecemos suporte principalmente ao runtime do APPSYNC\$1JS e sua documentação. Considere usar o runtime do APPSYNC\$1JS e seus guias disponíveis [aqui](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html).

AWS AppSync fornece uma maneira simples de conectar um campo GraphQL a uma única fonte de dados por meio de resolvedores de unidades. No entanto, a execução de uma única operação pode não ser suficiente. Os resolvedores de pipeline oferecem a capacidade de executar operações em série mediante fontes de dados. Crie funções na sua API e anexe-as a um resolvedor de pipeline. Cada resultado de execução da função é direcionado para a próxima até que nenhuma função fique sem execução. Com os resolvedores de pipeline, agora você pode criar fluxos de trabalho mais complexos diretamente no AWS AppSync. Neste tutorial, você cria um aplicativo de visualização de fotos simples, no qual os usuários podem publicar e visualizar fotos publicadas por seus amigos.

## Configuração com um clique
<a name="one-click-setup"></a>

Se você quiser configurar automaticamente o endpoint do GraphQL AWS AppSync com todos os resolvedores configurados e os AWS recursos necessários, você pode usar o seguinte modelo: AWS CloudFormation 

[https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/pipeline/pipeline-resolvers-full.yaml](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/pipeline/pipeline-resolvers-full.yaml)

Esta pilha cria os seguintes recursos na sua conta:
+ Função do IAM AWS AppSync para acessar os recursos em sua conta
+ 2 Tabelas do DynamoDB
+ 1 grupo de usuários do Amazon Cognito
+ 2 grupos de usuários do Amazon Cognito
+ 3 usuários do grupo de usuários do Amazon Cognito
+ 1 AWS AppSync API

No final do processo de criação da AWS CloudFormation pilha, você recebe um e-mail para cada um dos três usuários do Amazon Cognito que foram criados. Cada e-mail contém uma senha temporária que você usa para fazer login como usuário do Amazon Cognito no AWS AppSync console. Salve as senhas para o restante do tutorial.

## Configuração manual
<a name="manual-setup"></a>

Se você preferir passar manualmente por um step-by-step processo pelo AWS AppSync console, siga o processo de configuração abaixo.

### Configurando seus AWS AppSync recursos não relacionados
<a name="setting-up-your-non-aws-appsync-resources"></a>

A API se comunica com duas tabelas do DynamoDB: uma tabela **pictures** que armazena fotos e uma tabela **friends** que armazena os relacionamentos entre os usuários. A API é configurada para usar o grupo de usuários do Amazon Cognito como tipo de autenticação. A CloudFormation pilha a seguir configura esses recursos na conta.

[https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/pipeline/pipeline-resolvers-resources-only.yaml](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/pipeline/pipeline-resolvers-resources-only.yaml)

No final do processo de criação da AWS CloudFormation pilha, você recebe um e-mail para cada um dos três usuários do Amazon Cognito que foram criados. Cada e-mail contém uma senha temporária que você usa para fazer login como um usuário do Amazon Cognito no console do AWS AppSync. Salve as senhas para o restante do tutorial.

### Criação da API GraphQL
<a name="creating-your-graphql-api"></a>

Para criar a API GraphQL em: AWS AppSync

1. Abra o AWS AppSync console, escolha **Build From Scratch** e escolha **Start**.

1. Defina o nome da API como `AppSyncTutorial-PicturesViewer`.

1. Escolha **Criar**.

O AWS AppSync console cria uma nova API GraphQL para você usando o modo de autenticação por chave de API. Você pode usar o console para configurar o restante da API GraphQL e executar consultas nela durante o restante desse tutorial.

### Configurar a API do GraphQL
<a name="configuring-the-graphql-api"></a>

Você precisa configurar a AWS AppSync API com o grupo de usuários do Amazon Cognito que você acabou de criar.

1. Escolha a guia **Configurações**.

1. Na seção **Authorization Type**, escolha *Grupo de usuários do Amazon Cognito*.

1. Em **Configuração do grupo de usuários**, escolha **US-WEST-2** para a *região da AWS *.

1. Escolha o **AppSyncTutorial-** grupo de UserPool usuários.

1. Escolha **DENY** como *Ação padrão*.

1. Deixe o campo **regex AppId do cliente** em branco.

1. Escolha **Salvar**.

Agora, a API está configurada para usar o grupo de usuários do Amazon Cognito como seu tipo de autorização.

### Configuração da fonte de dados para as tabelas do DynamoDB
<a name="configuring-data-sources-for-the-ddb-tables"></a>

**Depois que as tabelas do DynamoDB forem criadas, navegue até a API do AWS AppSync GraphQL no console e escolha a guia Fontes de dados.** Agora, você criará uma fonte de dados AWS AppSync para cada uma das tabelas do DynamoDB que você acabou de criar.

1. Escolha a guia **Fonte de dados**.

1. Selecione **Novo** para criar uma nova fonte de dados.

1. Para o nome da fonte de dados, insira `PicturesDynamoDBTable`.

1. Para o tipo de fonte de dados, escolha **Tabela do Amazon DynamoDB**.

1. Para a região, escolha **US-WEST-2**.

1. Na lista de tabelas, escolha a tabela **AppSyncTutorial-Pictures DynamoDB**.

1. Na seção **Criar ou usar um perfil existente**, escolha **Perfil existente**.

1. Escolha a função que acabou de ser criada a partir do CloudFormation modelo. Se você não alterou o *ResourceNamePrefix*, o nome da função deverá ser **AppSyncTutorialDBRole-Dynamo**.

1. Escolha **Criar**.

Repita o mesmo processo para a tabela de **amigos**. O nome da tabela do DynamoDB deve **AppSyncTutorialser** -Friends se você não alterou *ResourceNamePrefix*o parâmetro no momento da criação da pilha. CloudFormation 

### Criação do esquema do GraphQL
<a name="creating-the-graphql-schema"></a>

Agora que as fontes de dados estão conectadas às suas tabelas do DynamoDB, vamos criar um esquema do GraphQL. No editor de esquemas no AWS AppSync console, verifique se o esquema corresponde ao esquema a seguir:

```
schema {
    query: Query
    mutation: Mutation
}

type Mutation {
    createPicture(input: CreatePictureInput!): Picture!
    @aws_auth(cognito_groups: ["Admins"])
    createFriendship(id: ID!, target: ID!): Boolean
    @aws_auth(cognito_groups: ["Admins"])
}

type Query {
    getPicturesByOwner(id: ID!): [Picture]
    @aws_auth(cognito_groups: ["Admins", "Viewers"])
}

type Picture {
    id: ID!
    owner: ID!
    src: String
}

input CreatePictureInput {
    owner: ID!
    src: String!
}
```

Escolha **Salvar esquema** para salvar o esquema.

Alguns dos campos do esquema foram anotados com a diretiva *@aws\$1auth*. Como a configuração de ação padrão da API é definida como *DENY*, a API rejeita todos os usuários que não são membros dos grupos mencionados na diretiva *@aws\$1auth*. Para obter mais informações sobre como proteger sua API, você pode ler a página [Segurança](security-authz.md#aws-appsync-security). **Nesse caso, somente usuários administradores têm acesso aos campos *mutation.createPicture e *mutation.createFriendship**, enquanto usuários que são membros dos grupos Administradores ou Visualizadores podem acessar a Consulta.** * getPicturesByCampo do proprietário*. Todos os outros usuários não têm acesso.

### Configurar resolvedores
<a name="configuring-resolvers"></a>

Agora que você tem um esquema do GraphQL válido e duas fontes de dados, é possível anexar resolvedores aos campos do GraphQL no esquema. A API oferece os seguintes recursos:
+ Crie uma foto por meio do campo *Mutation.createPicture*
+ Estabeleça a amizade por meio do campo *Mutation.createFriendship*
+ Recupere uma foto por meio do campo *Query.getPicture*

#### Mutation.createPicture
<a name="mutation-createpicture"></a>

No editor de esquemas no AWS AppSync console, no lado direito, escolha **Attach Resolver** for`createPicture(input: CreatePictureInput!): Picture!`. Escolha a fonte de dados do *PicturesDynamoDBTable*DynamoDB. Na seção **modelo de mapeamento de solicitação**, adicione o seguinte modelo:

```
#set($id = $util.autoId())

{
    "version" : "2018-05-29",

    "operation" : "PutItem",

    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($id),
        "owner": $util.dynamodb.toDynamoDBJson($ctx.args.input.owner)
    },

    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args.input)
}
```

Na seção **modelo de mapeamento de resposta**, adicione o seguinte modelo:

```
#if($ctx.error)
    $util.error($ctx.error.message, $ctx.error.type)
#end
$util.toJson($ctx.result)
```

A funcionalidade de criação de fotos está concluída. Você está salvando uma foto na tabela **Pictures**, usando um UUID gerado aleatoriamente como id da foto e usando o nome de usuário do Cognito como proprietário da foto.

#### Mutation.createFriendship
<a name="mutation-createfriendship"></a>

No editor de esquemas no AWS AppSync console, no lado direito, escolha **Attach Resolver** for`createFriendship(id: ID!, target: ID!): Boolean`. Escolha a fonte de dados do **FriendsDynamoDBTable**DynamoDB. Na seção **modelo de mapeamento de solicitação**, adicione o seguinte modelo:

```
#set($userToFriendFriendship = { "userId" : "$ctx.args.id", "friendId": "$ctx.args.target" })
#set($friendToUserFriendship = { "userId" : "$ctx.args.target", "friendId": "$ctx.args.id" })
#set($friendsItems = [$util.dynamodb.toMapValues($userToFriendFriendship), $util.dynamodb.toMapValues($friendToUserFriendship)])

{
    "version" : "2018-05-29",
    "operation" : "BatchPutItem",
    "tables" : {
        ## Replace 'AppSyncTutorial-' default below with the ResourceNamePrefix you provided in the CloudFormation template
        "AppSyncTutorial-Friends": $util.toJson($friendsItems)
    }
}
```

Importante: no modelo de **BatchPutItem**solicitação, o nome exato da tabela do DynamoDB deve estar presente. O nome padrão da tabela é *AppSyncTutorial-Friends.* Se você estiver usando o nome errado da tabela, você receberá um erro ao AppSync tentar assumir a função fornecida.

Para simplificar este tutorial, proceda como se a solicitação de amizade tivesse sido aprovada e salve a entrada do relacionamento diretamente na **AppSyncTutorialFriends**tabela.

Efetivamente, você está armazenando dois itens para cada amizade, pois o relacionamento é bidirecional. Para obter mais detalhes sobre as melhores práticas do Amazon DynamoDB para many-to-many representar relacionamentos, consulte [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-adjacency-graphs.html) Best Practices.

Na seção **modelo de mapeamento de resposta**, adicione o seguinte modelo:

```
#if($ctx.error)
    $util.error($ctx.error.message, $ctx.error.type)
#end
true
```

Nota: certifique-se de que o seu modelo de solicitação contenha o nome da tabela correta. O nome padrão é *AppSyncTutorial-Friends*, mas o nome da tabela pode ser diferente se você alterar o CloudFormation **ResourceNamePrefix**parâmetro.

#### Consulta. getPicturesByProprietário
<a name="query-getpicturesbyowner"></a>

Agora que você tem amizades e fotos, precisa fornecer aos usuários a capacidade de ver as fotos de seus amigos. Para atender a esse requisito, você precisa primeiro verificar se o solicitante é amigo do proprietário e, por fim, consultar as fotos.

Como essa funcionalidade requer duas operações de fonte de dados, você criará duas funções. A primeira função, **isFriend**, verifica se o solicitante e o proprietário são amigos. A segunda função, **getPicturesByProprietário**, recupera as fotos solicitadas com o ID do proprietário. Vamos dar uma olhada no fluxo de execução abaixo para o resolvedor proposto na *Consulta. getPicturesByCampo do proprietário*:

1. Antes do modelo de mapeamento: prepare os argumentos de entrada de contexto e campo.

1. Função isFriend: verifica se o solicitante é o proprietário da foto. Caso contrário, ele verifica se os usuários solicitantes e proprietários são amigos fazendo uma operação do GetItem DynamoDB na tabela de amigos.

1. getPicturesByFunção de proprietário: recupera imagens da tabela Imagens usando uma operação de consulta do DynamoDB no Índice Secundário Global do índice *do* proprietário.

1. Após o modelo de mapeamento: mapeie o resultado da foto para que os atributos do DynamoDB mapeiem corretamente para os campos esperados do tipo GraphQL.

Primeiro, vamos criar as funções.

##### Função isFriend
<a name="isfriend-function"></a>

1. Escolha a guia **Funções**.

1. Escolha **Criar função** para criar uma função.

1. Para o nome da fonte de dados, insira `FriendsDynamoDBTable`.

1. Para o nome da função, digite *isFriend*.

1. Dentro da área de texto do modelo de mapeamento de solicitação, cole o seguinte modelo:

   ```
   #set($ownerId = $ctx.prev.result.owner)
   #set($callerId = $ctx.prev.result.callerId)
   
   ## if the owner is the caller, no need to make the check
   #if($ownerId == $callerId)
       #return($ctx.prev.result)
   #end
   
   {
       "version" : "2018-05-29",
   
       "operation" : "GetItem",
   
       "key" : {
           "userId" : $util.dynamodb.toDynamoDBJson($callerId),
           "friendId" : $util.dynamodb.toDynamoDBJson($ownerId)
       }
   }
   ```

1. Dentro da área de texto do modelo de mapeamento de resposta, cole o seguinte modelo:

   ```
   #if($ctx.error)
       $util.error("Unable to retrieve friend mapping message: ${ctx.error.message}", $ctx.error.type)
   #end
   
   ## if the users aren't friends
   #if(!$ctx.result)
       $util.unauthorized()
   #end
   
   $util.toJson($ctx.prev.result)
   ```

1. Escolha **Criar função**.

Resultado: você criou a função **isFriend**.

##### getPicturesByFunção do proprietário
<a name="getpicturesbyowner-function"></a>

1. Escolha a guia **Funções**.

1. Escolha **Criar função** para criar uma função.

1. Para o nome da fonte de dados, insira `PicturesDynamoDBTable`.

1. Para o nome da função, digite `getPicturesByOwner`.

1. Dentro da área de texto do modelo de mapeamento de solicitação, cole o seguinte modelo:

   ```
   {
       "version" : "2018-05-29",
   
       "operation" : "Query",
   
       "query" : {
           "expression": "#owner = :owner",
           "expressionNames": {
               "#owner" : "owner"
           },
           "expressionValues" : {
               ":owner" : $util.dynamodb.toDynamoDBJson($ctx.prev.result.owner)
           }
       },
   
       "index": "owner-index"
   }
   ```

1. Dentro da área de texto do modelo de mapeamento de resposta, cole o seguinte modelo:

   ```
   #if($ctx.error)
       $util.error($ctx.error.message, $ctx.error.type)
   #end
   
   $util.toJson($ctx.result)
   ```

1. Escolha **Criar função**.

Resultado: você criou a função **getPicturesByProprietário**. Agora que as funções foram criadas, anexe um resolvedor de pipeline à *consulta. getPicturesByCampo do proprietário*.

No editor de esquemas no AWS AppSync console, no lado direito, escolha **Attach Resolver** for`Query.getPicturesByOwner(id: ID!): [Picture]`. Na página seguinte, escolha o link **Converter para resolvedor de pipeline** exibido abaixo da lista suspensa da fonte de dados. Use o seguinte para o modelo de mapeamento anterior:

```
#set($result = { "owner": $ctx.args.id, "callerId": $ctx.identity.username })
$util.toJson($result)
```

Na seção **modelo de mapeamento posterior**, use o seguinte modelo:

```
#foreach($picture in $ctx.result.items)
    ## prepend "src://" to picture.src property
    #set($picture['src'] = "src://${picture['src']}")
#end
$util.toJson($ctx.result.items)
```

Escolha **Criar resolvedor**. Você anexou seu primeiro resolvedor de pipeline com sucesso. Na mesma página, adicione as duas funções criadas anteriormente. Na seção de funções, escolha **Adicionar uma função** e escolha ou digite o nome da primeira função, **isFriend**. Adicione a segunda função seguindo o mesmo processo para a função **getPicturesByProprietário**. Certifique-se de que a função **isFriend** apareça primeiro na lista, seguida pela função **getPicturesByOwner**. Você pode usar as setas para cima e para baixo para reorganizar a ordem de execução das funções no pipeline.

Agora que o resolvedor de pipeline foi criado e você anexou as funções, vamos testar a API do GraphQL recém-criada.

## Teste da API GraphQL
<a name="testing-your-graphql-api"></a>

Primeiro, você precisa preencher fotos e amizades executando algumas mutações usando o usuário administrador que você criou. No lado esquerdo do AWS AppSync console, escolha a guia **Consultas.**

### Mutação createPicture
<a name="createpicture-mutation"></a>

1. No AWS AppSync console, escolha a guia **Consultas.**

1. Escolha **Login com grupos de usuários**.

1. No modal, insira o Cognito Sample Client ID que foi criado pela pilha (por exemplo, CloudFormation 37solo6mmhh7k4v63cqdfgdg5d).

1. Insira o nome de usuário que você passou como parâmetro para a CloudFormation pilha. O padrão é **nadia**.

1. Use a senha temporária que foi enviada para o e-mail que você forneceu como parâmetro para a CloudFormation pilha (por exemplo, *UserPoolUserEmail*).

1. Escolha Fazer login. Agora você deve ver o botão renomeado para **Logout nadia**, ou qualquer nome de usuário que você escolheu ao criar a CloudFormation pilha (ou seja,). *UserPoolUsername*

Vamos enviar algumas mutações *createPicture* para preencher a tabela de fotos. Execute a seguinte consulta do GraphQL dentro do console:

```
mutation {
  createPicture(input:{
    owner: "nadia"
    src: "nadia.jpg"
  }) {
    id
    owner
    src
  }
}
```

A resposta deve ter a aparência abaixo:

```
{
  "data": {
    "createPicture": {
      "id": "c6fedbbe-57ad-4da3-860a-ffe8d039882a",
      "owner": "nadia",
      "src": "nadia.jpg"
    }
  }
}
```

Vamos adicionar mais algumas fotos:

```
mutation {
  createPicture(input:{
    owner: "shaggy"
    src: "shaggy.jpg"
  }) {
    id
    owner
    src
  }
}
```

```
mutation {
  createPicture(input:{
    owner: "rex"
    src: "rex.jpg"
  }) {
    id
    owner
    src
  }
}
```

Você adicionou três fotos usando **nadia** como usuário administrador.

### Mutação createFriendship
<a name="createfriendship-mutation"></a>

Vamos adicionar uma entrada de amizade. Execute as seguintes mutações no console.

Observação: você ainda deve estar conectado como o usuário admin (o usuário admin padrão é **nadia**).

```
mutation {
  createFriendship(id: "nadia", target: "shaggy")
}
```

A resposta deve ter a seguinte aparência:

```
{
  "data": {
    "createFriendship": true
  }
}
```

 **nadia** e **shaggy** são amigos. **rex** não é amigo de ninguém.

### getPicturesByConsulta do proprietário
<a name="getpicturesbyowner-query"></a>

Para esta etapa, faça login como o usuário **nadia** usando os Grupos de usuários do Cognito, com as credenciais configuradas no início desse tutorial. Como usuário **nadia**, recupere as fotos de propriedade do usuário **shaggy**.

```
query {
    getPicturesByOwner(id: "shaggy") {
        id
        owner
        src
    }
}
```

Como **nadia** e **shaggy** são amigos, a consulta deve retornar a foto correspondente.

```
{
  "data": {
    "getPicturesByOwner": [
      {
        "id": "05a16fba-cc29-41ee-a8d5-4e791f4f1079",
        "owner": "shaggy",
        "src": "src://shaggy.jpg"
      }
    ]
  }
}
```

Da mesma forma, se o usuário **nadia** tentar recuperar suas próprias fotos, ele também terá êxito. O resolvedor de pipeline foi otimizado para evitar a execução da GetItem operação **isFriend** nesse caso. Tente a seguinte consulta:

```
query {
    getPicturesByOwner(id: "nadia") {
        id
        owner
        src
    }
}
```

Se você habilitar o registro em log em sua API (no painel **Configurações**), definir o nível de depuração como **TODOS** e executar a mesma consulta novamente, ele retornará os logs para a execução do campo. Observando os logs, você pode determinar se a função **isFriend** retornou anteriormente no estágio **Modelo de mapeamento da solicitação**:

```
{
  "errors": [],
  "mappingTemplateType": "Request Mapping",
  "path": "[getPicturesByOwner]",
  "resolverArn": "arn:aws:appsync:us-west-2:XXXX:apis/XXXX/types/Query/fields/getPicturesByOwner",
  "functionArn": "arn:aws:appsync:us-west-2:XXXX:apis/XXXX/functions/o2f42p2jrfdl3dw7s6xub2csdfs",
  "functionName": "isFriend",
  "earlyReturnedValue": {
    "owner": "nadia",
    "callerId": "nadia"
  },
  "context": {
    "arguments": {
      "id": "nadia"
    },
    "prev": {
      "result": {
        "owner": "nadia",
        "callerId": "nadia"
      }
    },
    "stash": {},
    "outErrors": []
  },
  "fieldInError": false
}
```

A *earlyReturnedValue*chave representa os dados que foram retornados pela diretiva *\$1return*.

**Finalmente, embora **rex** seja membro do **Viewers** Cognito UserPool Group e porque **rex** não seja amigo de ninguém, ele não poderá acessar nenhuma das fotos de propriedade de **shaggy** ou nadia.** Se você fizer login como **rex** no console e executar a seguinte consulta:

```
query {
    getPicturesByOwner(id: "nadia") {
        id
        owner
        src
    }
}
```

Você receberá o seguinte erro não autorizado:

```
{
  "data": {
    "getPicturesByOwner": null
  },
  "errors": [
    {
      "path": [
        "getPicturesByOwner"
      ],
      "data": null,
      "errorType": "Unauthorized",
      "errorInfo": null,
      "locations": [
        {
          "line": 2,
          "column": 9,
          "sourceName": null
        }
      ],
      "message": "Not Authorized to access getPicturesByOwner on type Query"
    }
  ]
}
```

Você implementou com sucesso a autorização complexa usando resolvedores de pipeline.