

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Uso de solucionadores de canalizaciones en AWS AppSync
<a name="tutorial-pipeline-resolvers"></a>

**nota**  
Ahora admitimos de forma básica el tiempo de ejecución APPSYNC\$1JS y su documentación. Considere la opción de utilizar el tiempo de ejecución APPSYNC\$1JS y sus guías [aquí](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html).

AWS AppSync proporciona una forma sencilla de conectar un campo GraphQL a una única fuente de datos mediante resolutores unitarios. Sin embargo, ejecutar una sola operación podría no ser suficiente. Los solucionadores de canalización ofrecen la posibilidad de ejecutar operaciones en serie con respecto a los orígenes de datos. Cree funciones en su API y asócielas a un solucionador de canalización. Cada resultado de ejecución de la función se canaliza a la siguiente hasta que no quede ninguna función que ejecutar. Con los solucionadores de canalización ahora puede crear flujos de trabajo más complejos directamente en AWS AppSync. En este tutorial, se crea una aplicación sencilla de visualización de imágenes, en la que los usuarios pueden publicar y ver imágenes publicadas por sus amigos.

## Configuración en un clic
<a name="one-click-setup"></a>

Si quieres configurar automáticamente el punto final de GraphQL AWS AppSync con todos los resolutores configurados y los AWS recursos necesarios, puedes usar la siguiente plantilla: 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 pila crea los siguientes recursos en su cuenta:
+ Función de IAM para acceder AWS AppSync a los recursos de tu cuenta
+ 2 tablas de DynamoDB
+ 1 grupo de usuarios de Amazon Cognito
+ 2 grupos de grupos de usuarios de Amazon Cognito
+ 3 usuarios de grupos de usuarios de Amazon Cognito
+ 1 API AWS AppSync 

Al final del proceso de creación de la AWS CloudFormation pila, recibirá un correo electrónico para cada uno de los tres usuarios de Amazon Cognito que se crearon. Cada correo electrónico contiene una contraseña temporal que se utiliza para iniciar sesión en la consola como usuario de Amazon Cognito. AWS AppSync Guarde las contraseñas para el resto del tutorial.

## Configuración manual
<a name="manual-setup"></a>

Si prefiere realizar un step-by-step proceso manualmente a través de la AWS AppSync consola, siga el proceso de configuración que se indica a continuación.

### Configuración de sus AWS AppSync recursos no relacionados
<a name="setting-up-your-non-aws-appsync-resources"></a>

La API se comunica con dos tablas de DynamoDB: una tabla de **imágenes** que almacena imágenes y una tabla de **amigos** que almacena las relaciones entre los usuarios. La API está configurada para utilizar el grupo de usuarios de Amazon Cognito como el tipo de autenticación. La siguiente CloudFormation pila configura estos recursos en la cuenta.

[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)

Al final del proceso de creación de la AWS CloudFormation pila, recibirá un correo electrónico para cada uno de los tres usuarios de Amazon Cognito que se crearon. Cada correo electrónico contiene una contraseña temporal que se utiliza para iniciar sesión como un usuario de Amazon Cognito en la consola de AWS AppSync. Guarde las contraseñas para el resto del tutorial.

### Creación de la API de GraphQL
<a name="creating-your-graphql-api"></a>

Para crear la API GraphQL en: AWS AppSync

1. Abre la AWS AppSync consola, selecciona **Build From Scratch** y selecciona **Start**.

1. Establezca como nombre de la API `AppSyncTutorial-PicturesViewer`.

1. Seleccione **Crear**.

La AWS AppSync consola crea una nueva API de GraphQL para usted mediante el modo de autenticación con clave de API. Puede utilizar la consola para configurar el resto de la API de GraphQL y ejecutar consultas en ella durante el resto de este tutorial.

### Configuración de la API de GraphQL
<a name="configuring-the-graphql-api"></a>

Debe configurar la AWS AppSync API con el grupo de usuarios de Amazon Cognito que acaba de crear.

1. Elija la pestaña **Settings**.

1. En la sección **Authorization Type (Tipo de autorización)**, elija *Amazon Cognito User Pool (Grupo de usuarios de Amazon Cognito)*.

1. En **Configuración del grupo de usuarios**, elija **US-WEST-2** para la *Región de AWS *.

1. Elija el grupo **AppSyncTutorialde UserPool usuarios:**

1. Elija **DENY (DENEGAR)** como *Default Action (Acción predeterminada)*.

1. Deje en blanco el campo **de expresiones regulares del AppId cliente**.

1. Seleccione **Save**.

La API ahora está configurada para utilizar el grupo de usuarios de Amazon Cognito como el tipo de autenticación.

### Configuración de orígenes de datos para las tablas de DynamoDB
<a name="configuring-data-sources-for-the-ddb-tables"></a>

**Una vez creadas las tablas de DynamoDB, vaya a la API de AWS AppSync GraphQL en la consola y seleccione la pestaña Fuentes de datos.** Ahora, va a crear una fuente de datos AWS AppSync para cada una de las tablas de DynamoDB que acaba de crear.

1. Elija la pestaña **Data source (Origen de datos)**.

1. Elija **New (Nuevo)** para crear un nuevo origen de datos.

1. Escriba `PicturesDynamoDBTable` como nombre del origen de datos.

1. En Tipo de origen de datos, elija **Tabla de Amazon DynamoDB**.

1. Elija **US-WEST-2** como región.

1. En la lista de tablas, elija la tabla **AppSyncTutorial-Pictures DynamoDB**.

1. En la sección **Create or use an existing role (Crear o usar un rol existente)**, elija **Existing role (Rol existente)**.

1. Elija el rol que se acaba de crear a partir de la plantilla. CloudFormation Si no ha cambiado el *ResourceNamePrefix*, el nombre del rol debería ser **AppSyncTutorial-Dynamo DBRole**.

1. Seleccione **Crear**.

Repita el mismo proceso para la tabla de **amigos**, el nombre de la tabla de DynamoDB debería **AppSyncTutorialser** -Friends si no cambió *ResourceNamePrefix*el parámetro en el momento de crear la pila. CloudFormation 

### Creación del esquema de GraphQL
<a name="creating-the-graphql-schema"></a>

Ahora que los orígenes de datos están conectados a las tablas de DynamoDB, vamos a crear un esquema de GraphQL. En el editor de esquemas de la AWS AppSync consola, asegúrese de que el esquema coincide con el siguiente esquema:

```
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!
}
```

Elija **Save Schema (Guardar esquema)** para guardar el esquema.

Algunos de los campos de esquema se han comentado con la directiva *@aws\$1auth*. Dado que la API de configuración de acción predeterminada está establecida en *DENY (DENEGAR)*, la API rechaza a todos los usuarios que no son miembros de los grupos mencionados dentro de la directiva *@aws\$1auth*. Para obtener más información acerca de cómo proteger la API, puede leer la página de [seguridad](security-authz.md#aws-appsync-security). **En este caso, solo los usuarios administradores tienen acceso a los campos *Mutation.createPicture y Mutation.createFriendship**, mientras que los usuarios que son miembros* de los grupos de administradores o de espectadores pueden acceder a la consulta.** * getPicturesByCampo propietario.* Todos los demás usuarios no tienen acceso.

### Configuración de solucionadores
<a name="configuring-resolvers"></a>

Ahora que tiene un esquema GraphQL válido y dos orígenes de datos, puede asociar los solucionadores a los campos de GraphQL en el esquema. La API ofrece las siguientes capacidades:
+ Crear una imagen a través del campo *Mutation.createPicture*
+ Crear una amistad a través del campo *Mutation.createFriendship*
+ Recuperar una imagen a través del campo *Query.getPicture*

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

En el editor de esquemas de la AWS AppSync consola, en el lado derecho, selecciona **Attach Resolver** for`createPicture(input: CreatePictureInput!): Picture!`. Elija la fuente de datos de *PicturesDynamoDBTable*DynamoDB. En la sección **Plantilla de mapeo de solicitudes**, añada la siguiente plantilla:

```
#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)
}
```

En la sección **Plantilla de mapeo de respuestas**, añada la siguiente plantilla:

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

La funcionalidad de creación de imagen está lista. Va a guardar una imagen en la tabla **Pictures (Imágenes)** utilizando un UUID generado de forma aleatoria como id de la imagen y utilizando el nombre de usuario de Cognito como propietario de la imagen.

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

En el editor de esquemas de la AWS AppSync consola, en la parte derecha, elija **Attach Resolver for**. `createFriendship(id: ID!, target: ID!): Boolean` Elija la fuente de datos de **FriendsDynamoDBTable**DynamoDB. En la sección **Plantilla de mapeo de solicitudes**, añada la siguiente plantilla:

```
#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: En la plantilla de **BatchPutItem**solicitud, debe estar presente el nombre exacto de la tabla de DynamoDB. *El nombre predeterminado de la tabla es -FriendsAppSyncTutorial.* Si utilizas un nombre de tabla incorrecto, aparecerá un error cuando AppSync intentes asumir el rol proporcionado.

Para simplificar este tutorial, proceda como si la solicitud de amistad hubiera sido aprobada y guarde la entrada sobre la relación directamente en la **AppSyncTutorialFriends**tabla.

Efectivamente, está almacenando dos elementos para cada amistad, ya que la relación es bidireccional. Para obtener más información sobre las prácticas recomendadas de Amazon DynamoDB para many-to-many representar relaciones, consulte Prácticas recomendadas de [DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-adjacency-graphs.html).

En la sección **Plantilla de mapeo de respuestas**, añada la siguiente plantilla:

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

Nota: Asegúrese de que su plantilla de solicitud contiene el nombre de la tabla correcto. El nombre predeterminado es *AppSyncTutorial-Friends*, pero el nombre de la tabla podría ser diferente si cambiara el parámetro. CloudFormation **ResourceNamePrefix**

#### Consulta. getPicturesByDueño
<a name="query-getpicturesbyowner"></a>

Ahora que tiene amistades e imágenes, debe proporcionar la capacidad a los usuarios de ver las imágenes de sus amigos. Para cumplir este requisito, debe comprobar primero que el solicitante es amigo con el propietario y, por último, consultar las imágenes.

Dado que esta funcionalidad requiere dos operaciones de origen de datos, va a crear dos funciones. La primera función, **isFriend**, comprueba si el solicitante y el propietario son amigos. La segunda función, **getPicturesByPropietario**, recupera las imágenes solicitadas con un identificador de propietario. Veamos el siguiente flujo de ejecución para el solucionador propuesto en la *consulta. getPicturesByCampo propietario*:

1. Plantilla de mapeo Antes: Prepare los argumentos de entrada de contexto y campo.

1. Función isFriend: Comprueba si el solicitante es el propietario de la imagen. De lo contrario, comprueba si los usuarios solicitantes y propietarios son amigos realizando una operación de GetItem DynamoDB en la tabla de amigos.

1. getPicturesByFunción propietario: recupera imágenes de la tabla Pictures mediante una operación de consulta de DynamoDB en *el* índice secundario global owner-index.

1. Plantilla de mapeo Después: Mapea el resultado de la imagen para que los atributos de DynamoDB se mapeen correctamente en los campos de tipo GraphQL esperados.

Primero, vamos a crear las funciones.

##### Función isFriend
<a name="isfriend-function"></a>

1. Elija la pestaña **Functions (Funciones)**.

1. Elija **Create Function (Crear función)** para crear una función.

1. Escriba `FriendsDynamoDBTable` como nombre del origen de datos.

1. Para el nombre de la función, escriba *isFriend*.

1. Dentro del área de texto de la plantilla de mapeo de solicitudes, pegue la siguiente plantilla:

   ```
   #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 del área de texto de la plantilla de mapeo de respuestas, pegue la siguiente plantilla:

   ```
   #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. Elija **Crear función**.

Resultado: Ha creado la función **isFriend**.

##### getPicturesByFunción de propietario
<a name="getpicturesbyowner-function"></a>

1. Elija la pestaña **Functions (Funciones)**.

1. Elija **Create Function (Crear función)** para crear una función.

1. Escriba `PicturesDynamoDBTable` como nombre del origen de datos.

1. Para el nombre de la función, escriba `getPicturesByOwner`.

1. Dentro del área de texto de la plantilla de mapeo de solicitudes, pegue la siguiente plantilla:

   ```
   {
       "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 del área de texto de la plantilla de mapeo de respuestas, pegue la siguiente plantilla:

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

1. Elija **Crear función**.

Resultado: ha creado la función **getPicturesByPropietario**. Ahora que se han creado las funciones, adjunta un solucionador de canalizaciones a la *consulta. getPicturesByCampo propietario*.

En el editor de esquemas de la AWS AppSync consola, en el lado derecho, selecciona **Attach Resolver** for`Query.getPicturesByOwner(id: ID!): [Picture]`. En la página siguiente, elija el enlace **Convert to pipeline resolver (Convertir a solucionador de canalización)** que aparece debajo de la lista desplegable del origen de datos. Use lo siguiente para la plantilla de mapeo de antes:

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

En la sección **after mapping template (plantilla de mapeo de después)**, use lo siguiente:

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

Elija **Create Resolver (Crear solucionador)**. Acaba de asociar su primer solucionador de canalización. En la misma página, añada las dos funciones que ha creado anteriormente. En sección de funciones, seleccione **Add A Function (Añadir una función)** y, a continuación, elija o escriba el nombre de la primera función, **isFriend**. Añada la segunda función siguiendo el mismo proceso para la función **getPicturesByOwner**. Asegúrese de que la función **IsFriend** aparezca en primer lugar de la lista, seguida de la función **getPicturesByPropietario**. Puede utilizar las flechas hacia arriba y abajo para cambiar el orden de ejecución de las funciones de la canalización.

Ahora que el solucionador de canalización se ha creado y ha asociado las funciones, vamos a probar la nueva API de GraphQL.

## Prueba de la API de GraphQL
<a name="testing-your-graphql-api"></a>

En primer lugar, debe rellenar las imágenes y amistades ejecutando algunas mutaciones mediante el usuario administrador que ha creado. En la parte izquierda de la AWS AppSync consola, selecciona la pestaña **Consultas**.

### Mutación createPicture
<a name="createpicture-mutation"></a>

1. En AWS AppSync la consola, selecciona la pestaña **Consultas**.

1. Elija **Login With User Pools (Inicio de sesión con grupos de usuarios)**.

1. En el modal, introduzca el ID de cliente de muestra de Cognito que creó la CloudFormation pila (por ejemplo, 37solo6mmhh7k4v63cqdfgdg5d).

1. Introduzca el nombre de CloudFormation usuario que ha pasado como parámetro a la pila. El valor predeterminado es **nadia**.

1. Usa la contraseña temporal que se envió al correo electrónico que proporcionaste como parámetro de la CloudFormation pila (por ejemplo, *UserPoolUserEmail*).

1. Seleccione Iniciar sesión. Ahora deberías ver el botón con el nombre de **Logout nadia**, o el nombre de usuario que hayas elegido al crear la CloudFormation pila (es decir, *UserPoolUsername*).

Vamos a enviar unas mutaciones de *createPicture* para rellenar la tabla de imágenes. Ejecute la siguiente consulta de GraphQL dentro de la consola:

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

La respuesta debe tener un aspecto similar al siguiente:

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

Agreguemos algunas imágenes más:

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

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

Ha agregado tres imágenes usando a **nadia** como usuario administrador.

### Mutación createFriendship
<a name="createfriendship-mutation"></a>

Vamos a añadir una entrada de amistad. Ejecute las siguientes mutaciones en la consola.

Nota: Debe permanecer con la sesión iniciada como usuario administrador (el valor predeterminado es **nadia**).

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

La respuesta debe tener un aspecto similar al siguiente:

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

 **nadia** y **shaggy** son amigos. **rex** no es amigo de nadie.

### getPicturesByConsulta de propietario
<a name="getpicturesbyowner-query"></a>

En este paso, inicie sesión como el usuario **nadia** con los grupos de usuarios de Cognito, con las credenciales configuradas al principio de este tutorial. Como **nadia**, recupere las imágenes propiedad de **shaggy**.

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

Dado que **nadia** y **shaggy** son amigos, la consulta debe devolver la imagen correspondiente.

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

Del mismo modo, si **nadia** intenta recuperar sus propias imágenes, también se ejecuta satisfactoriamente. El solucionador de canalizaciones se ha optimizado para evitar ejecutar la GetItem operación **IsFriend** en ese caso. Pruebe la siguiente consulta:

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

Si habilita el registro en la API (en el panel **Settings (Configuración)**), configure el nivel de depuración a **ALL (TODO)** y ejecute la misma consulta de nuevo, devuelve los registros a la ejecución del campo. Observando los registros, puede determinar si la función **isFriend** se ha devuelto pronto en la etapa **Request Mapping Template (Plantilla de mapeo de solicitud)**:

```
{
  "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
}
```

La *earlyReturnedValue*clave representa los datos devueltos por la directiva *\$1return*.

**Por último, aunque **rex** es miembro del UserPool Grupo Cognito de los **espectadores** y, dado que **Rex** no es amigo de nadie, no podrá acceder a ninguna de las imágenes propiedad de **Shaggy** o Nadia.** Si iniciar sesión como **rex** en la consola y ejecuta la siguiente consulta:

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

Obtiene el siguiente error de no 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"
    }
  ]
}
```

Ha implementado con éxito la autorización compleja con los solucionadores de canalización.