Autenticarse con GraphQL
Puedes autenticarte en la API de GraphQL mediante un personal access token, una GitHub App o una OAuth app.
Autenticación con un personal access token
Para autenticarse con un personal access token, siga los pasos descritos en Administración de tokens de acceso personal. Los datos que solicitas determinarán qué ámbitos o permisos necesitarás.
Por ejemplo, seleccione el permiso "issues:read" para leer todos los problemas de los repositorios a los que el token tiene acceso.
Todos los fine-grained personal access token incluyen acceso de lectura a repositorios públicos. Para acceder a los repositorios públicos con un personal access token (classic), seleccione el alcance "public_repo".
Si el token no tiene los ámbitos o permisos necesarios para access un recurso, la API devolverá un mensaje de error que indica los ámbitos o permisos que necesita el token.
Autenticación con una GitHub App
Si deseas usar la API en nombre de una organización u otro usuario, GitHub recomienda usar un GitHub App. Para atribuir la actividad a la aplicación, puedes hacer que la aplicación se autentique como una instalación de aplicación. Para atribuir la actividad de la aplicación a un usuario, puedes hacer que la aplicación se autentique en nombre de un usuario. En ambos casos, generarás un token que puedes usar para autenticarte en la GraphQL API. Para obtener más información, vea Registro de una aplicación de GitHub y Acerca de la autenticación con una aplicación de GitHub.
Autenticarse con OAuth app
Para autenticarte con un token de OAuth desde OAuth app, primero debes autorizar OAuth app mediante un flujo de aplicación web o un flujo de dispositivo. A continuación, puede usar el token de acceso que recibió para acceder a la API. Para más información, consulta Creación de una aplicación de OAuth y Autorización de aplicaciones de OAuth.
Punto de acceso de GraphQL
La API REST tiene numerosos puntos de conexión. Con GraphQL API, el punto de conexión permanece constante sin importar la operación que realices. Para GitHub.com, ese punto de conexión es:
https://api.github.com/graphql
Comunicarse con GraphQL
Dado que las operaciones de GraphQL constan de JSON de varias líneas, GitHub recomienda usar los clientes de GraphQL para realizar llamadas a GraphQL. También puedes utilizar curl o cualquier otra biblioteca que entienda HTTP.
En REST, los verbos HTTP determinan la operación realizada. En GraphQL, tendrá que proporcionar un cuerpo codificado con JSON cuando realice una consulta o una mutación, por lo que el verbo HTTP es POST. La excepción es una consulta de introspección, que es una GET al punto de conexión. Para obtener más información sobre GraphQL frente a REST, consulte Migrar desde Rest hacia GraphQL.
Para consultar GraphQL mediante un comando curl, realiza una solicitud POST con una carga JSON. La carga debe contener una cadena denominada query:
curl -H "Authorization: bearer TOKEN" -X POST -d " \
{ \
\"query\": \"query { viewer { login }}\" \
} \
" https://api.github.com/graphql
Nota:
El valor de cadena de "query" debe aplicar escape a los caracteres de nueva línea o el esquema no lo analizará correctamente. Para el cuerpo POST, use comillas dobles externas y comillas dobles interiores con escape.
Acerca de las operaciones de consulta y mutación
Los dos tipos de operaciones permitidas en graphQL API de GitHub son consultas y mutaciones. Si se compara GraphQL con REST, las consultas funcionan como solicitudes GET, mientras que las mutaciones funcionan comoPOST/PATCH/DELETE. El nombre de la mutación determina qué modificación se ejecuta.
Para obtener información sobre la limitación de tasas, consulta Límites de frecuencia y consulta para GraphQL API.
Las consultas y mutaciones comparten formatos similares con algunas diferencias importantes.
Acerca de las consultas
Las consultas de GraphQL devuelven solo los datos que especifique. Para formar una consulta, debe especificar fields dentro de los campos (también conocidos como nested subfields) hasta que devuelva solo scalars.
Las consultas se estructuran de esta manera:
query {
JSON-OBJECT-TO-RETURN
}
Para obtener un ejemplo real, lee Consulta de ejemplo.
Acerca de las mutaciones
Para formar una mutación, debes especificar tres cosas:
-
_Nombre de la mutación_. El Tipo de modificación que quieres realizar. -
_Objeto de entrada_. Los datos que quiere enviar al servidor, formados por _campos de entrada_. Pásalo como un argumento al nombre de la mutación. -
_Objeto de carga útil_. Los datos que se quieren devolver desde el servidor, compuestos por _campos de retorno_. Pásalos como el cuerpo del nombre de la mutación.
Las mutaciones se estructuran de la siguiente forma:
mutation {
MUTATION-NAME(input: {MUTATION-NAME-INPUT!}) {
MUTATION-NAME-PAYLOAD
}
}
El objeto de entrada de este ejemplo es MutationNameInputy el objeto de carga es MutationNamePayload.
En la referencia de mutaciones, los campos de entrada enumerados son lo que se pasa como objeto de entrada. Los campos devueltos enumerados son lo que se pasa como objeto de carga.
Para obtener un ejemplo real, consulta Mutación de ejemplo.
Trabajo con variables
Las [variables](https://graphql.org/learn/queries/#variables) pueden hacer que las consultas sean más dinámicas y eficaces, y pueden reducir la complejidad al pasar objetos de entrada de mutación.
Aquí hay una consulta de ejemplo con una sola variable:
query($number_of_repos:Int!) {
viewer {
name
repositories(last: $number_of_repos) {
nodes {
name
}
}
}
}
variables {
"number_of_repos": 3
}
Hay tres pasos para utilizar las variables:
-
Defina la variable fuera de la operación en un objeto
variables:variables { "number_of_repos": 3 }El objeto debe ser un JSON válido. En este ejemplo se muestra un tipo de variable
Intsencillo, pero se pueden definir tipos de variable más complejos, como los objetos de entrada. También puedes definir variables múltiples aquí. -
Pasa la variable a la operación como un argumento:
query($number_of_repos:Int!){El argumento es un par clave-valor, donde la clave es el nombre que empieza por
$(por ejemplo,$number_of_repos) y el valor es el tipo (por ejemplo,Int). Agregue!para indicar si el tipo es obligatorio. Si has identificado variables múltiples, inclúyelas aquí como argumentos múltiples. -
Utiliza la variable dentro de la operación:
repositories(last: $number_of_repos) {En este ejemplo, sustituimos la variable por la cantidad de repositorios a devolver. Especificamos un tipo en el paso 2, ya que GraphQL requiere tipado fuerte.
Este proceso vuelve dinámico el argumento de la consulta. Ahora se puede cambiar el valor en el objeto variables y mantener el resto de la consulta igual.
El uso de variables como argumentos permite actualizar los valores del objeto variables de forma dinámica sin cambiar la consulta.
Ejemplo de consulta
Analicemos una consulta más compleja y pongamos esta información en contexto.
La consulta siguiente examina el repositorio octocat/Hello-World, busca las 20 incidencias cerradas más recientes y devuelve el título, la dirección URL y las 5 primeras etiquetas de cada incidencia:
query {
repository(owner:"octocat", name:"Hello-World") {
issues(last:20, states:CLOSED) {
edges {
node {
title
url
labels(first:5) {
edges {
node {
name
}
}
}
}
}
}
}
}
Analizando la composición línea por línea:
-
query {Como el objetivo es leer datos del servidor, no modificarlos, la operación raíz es
query. (Si no especifica una operación,querytambién es el valor predeterminado). -
repository(owner:"octocat", name:"Hello-World") {Para comenzar la consulta, se busca un objeto
repository. La validación del esquema indica que este objeto necesita unownery un argumentoname. -
issues(last:20, states:CLOSED) {Para tener en cuenta todas las incidencias del repositorio, se llama al objeto
issues. (Se podría consultar un únicoissueenrepository, pero para eso sería necesario conocer el número de la incidencia que se quiere devolver y proporcionarlo como argumento).Algunos detalles sobre el objeto
issues:- En la documentación se indica que este objeto tiene el tipo
IssueConnection. - La validación del esquema indica que este objeto necesita un número de resultados
lastofirstcomo argumento, por lo que se proporciona20. - En la documentación también se indica que este objeto acepta un argumento
states, que es una enumeraciónIssueStateque acepta valoresOPENoCLOSED. Para busca solo incidencias cerradas, se asigna un valor destatesa la claveCLOSED.
- En la documentación se indica que este objeto tiene el tipo
-
edges {Se sabe que
issueses una conexión porque tiene el tipoIssueConnection. Para recuperar datos sobre incidencias individuales, tenemos que acceder al nodo a través deedges. -
node {Aquí obtenemos el nodo al final de la arista. En la documentación de
IssueConnectionse indica que el nodo al final del tipoIssueConnectiones un objetoIssue. -
Ahora que se sabe que se va a recuperar un objeto
Issue, se puede examinar la documentación y especificar los campos que se quieren devolver:title url labels(first:5) { edges { node { name } } }Aquí se especifican los campos
title,urlylabelsdel objetoIssue.El campo
labelstiene el tipoLabelConnection. Como sucede con el objetoissues, comolabelses una conexión, es necesario desplazar sus bordes a un nodo conectado: el objetolabel. En el nodo, se pueden especificar los campos del objetolabelque se quieren devolver, en este caso,name.
Es posible que observe que la ejecución de esta consulta en el repositorio Hello-World de Octocat no devuelve muchas etiquetas. Intenta ejecutarlo en uno de tus propios repositorios que utilice etiquetas, y seguramente verás la diferencia.
Mutación de ejemplo
Las mutaciones a menudo requieren información que solo puedes encontrar si realizas una consulta primero. Este ejemplo muestra dos operaciones:
- Una consulta para obtener el ID de una incidencia.
- Una mutación para agregar una reacción de emoji a un problema.
query FindIssueID {
repository(owner:"octocat", name:"Hello-World") {
issue(number:349) {
id
}
}
}
mutation AddReactionToIssue {
addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {
reaction {
content
}
subject {
id
}
}
}
Analicemos el ejemplo. La tarea parece sencilla: agregar una reacción de emoji a una incidencia.
Así que, ¿cómo sabemos que debemos comenzar con una consulta? Aún no sabemos nada.
Ya que queremos modificar los datos en el servidor (agregar un emoji a un informe de problemas), empezamos buscando en el esquema una mutación útil. En la documentación de referencia se muestra la mutación addReaction, con esta descripción: Adds a reaction to a subject. Perfecto.
Los documentos para la mutación listan tres campos de entrada:
-
`clientMutationId` (`String`) -
`subjectId` (`ID!`) -
`content` (`ReactionContent!`)
Los valores ! indican que subjectId y content son campos obligatorios. Un campo content obligatorio tiene sentido: el objetivo es agregar una reacción, por lo que será necesario especificar el emoji que se va a usar.
¿Pero por qué subjectId es obligatorio? Se debe a que subjectId es la única manera de identificar a qué incidencia de qué repositorio se debe reaccionar.
Este es el motivo de comenzar el ejemplo con una consulta: para obtener ID.
Examinemos la consulta línea por línea:
-
query FindIssueID {Aquí se realiza una consulta y se le asigna el nombre
FindIssueID. Tenga en cuenta que asignar un nombre a una consulta es opcional; aquí le damos un nombre para poder incluirla en la misma ventana del cliente de la interfaz gráfica que la mutación. -
repository(owner:"octocat", name:"Hello-World") {Para especificar el repositorio se consulta el objeto
repositoryy se pasan los argumentosowneryname. -
issue(number:349) {Para especificar la incidencia a la que reaccionar se consulta el objeto
issuey se pasa un argumentonumber. -
idAquí es donde recuperamos el
iddehttps://github.com/octocat/Hello-World/issues/349para pasar comosubjectId.
Cuando se ejecuta la consulta, se obtiene id: MDU6SXNzdWUyMzEzOTE1NTE=.
Nota:
El valor id devuelto en la consulta es el que se pasará como subjectID en la mutación. Ni la documentación ni la introspección del esquema indicarán esta relación; necesitarás comprender los conceptos que subyacen a los nombres para descubrirla.
Una vez conociendo la ID, podemos proceder con la mutación:
-
mutation AddReactionToIssue {Aquí se ejecuta una mutación y se le asigna el nombre
AddReactionToIssue. Al igual que con las consultas, la nomenclatura de una mutación es opcional; Aquí se le asigna un nombre para que podamos incluirlo en la misma ventana de cliente de GUI que la consulta. -
addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {Examinemos esta línea:
-
`addReaction` es el nombre de la mutación. -
`input` es la clave de argumento obligatoria. Esto siempre será `input` para una mutación. -
`{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}` es el valor de argumento obligatorio. Siempre será un [objeto de entrada](/graphql/reference/input-objects) (de ahí las llaves) formado por campos de entrada (`subjectId` y `content` en este caso) para una mutación.
¿Cómo sabemos qué valor utilizar para el contenido? El
addReactiondocs nos indican que el campocontenttiene el tipoReactionContent, que es un enum porque solo se permiten ciertas reacciones emoji en problemas de GitHub. Estos son los valores permitidos para las reacciones (nota que algunos valores son diferentes de sus nombres de emoji correspondientes):Contenido Emoji +1👍 -1👎 laugh😄 confused😕 heart❤️ hooray🎉 rocket🚀 eyes👀 -
-
El resto del llamado se compone del objeto de carga útil. Aquí es donde especificamos los datos que queremos recuperar del servidor después de que realicemos la mutación. Estas líneas proceden de la documentación de
addReaction, con tres campos devueltos posibles:-
`clientMutationId` (`String`) -
`reaction` (`Reaction!`) -
`subject` (`Reactable!`)
En este ejemplo, se devuelven los dos campos obligatorios (
reactionysubject), que tienen subcampos obligatorios (contentyid, respectivamente). -
Cuando ejecutamos la mutación, esta es la respuesta:
{
"data": {
"addReaction": {
"reaction": {
"content": "HOORAY"
},
"subject": {
"id": "MDU6SXNzdWUyMTc5NTQ0OTc="
}
}
}
}
Eso es todo. Revisa tu reacción ante el problema pasando el ratón sobre el 🎉 para encontrar tu nombre de usuario.
Una última nota: cuando pasas varios campos en un objeto de entrada, la sintaxis puede ser difícil de manejar. Puede resultar útil mover los campos a una variable. Así es como podrías reescribir la mutación original utilizando una variable:
mutation($myVar:AddReactionInput!) {
addReaction(input:$myVar) {
reaction {
content
}
subject {
id
}
}
}
variables {
"myVar": {
"subjectId":"MDU6SXNzdWUyMTc5NTQ0OTc=",
"content":"HOORAY"
}
}
Nota:
Es posible que observe que el valor del campo content en el ejemplo anterior (donde se usa directamente en la mutación) no tiene comillas alrededor de HOORAY, pero sí cuando se usa en la variable. Esto es por una razón:
- Cuando se usa
contentdirectamente en la mutación, el esquema espera que el valor sea de tipoReactionContent, que es una enumeración, no una cadena. La validación del modelo arrojará un error si agregas comillas antes y después del valor de enumerador, ya que estas están reservadas para las cadenas. - Cuando se usa
contenten una variable, la sección de variables debe ser código JSON válido, por lo que las comillas son obligatorias. La validación del esquema interpreta correctamente el tipoReactionContentcuando la variable se pasa a la mutación durante la ejecución.
Para más información sobre la diferencia entre enumeraciones y cadenas, vea la especificación oficial de GraphQL.
Información adicional
Hay mucho más que puedes hacer cuando realizas llamadas de GraphQL. Aquí hay algunos lugares que te pueden interesar posteriormente:
-
[AUTOTITLE](/graphql/guides/using-pagination-in-the-graphql-api) -
[Fragmentos](https://graphql.org/learn/queries/#fragments) -
[Fragmentos alineados](https://graphql.org/learn/queries/#inline-fragments) -
[Directivas](https://graphql.org/learn/queries/#directives)