Autenticar com o GraphQL
Você pode se autenticar na API do GraphQL usando um personal access token, um GitHub App ou um OAuth app.
Autenticar com um personal access token
Para autenticar com um personal access token, siga os passos em Gerenciar seus tokens de acesso pessoal. Os dados que você está solicitando determinarão as permissões ou os escopos necessários.
Por exemplo, selecione a permissão "issues:read" para ler todas as issues nos repositórios a que seu token tem acesso.
Todos os fine-grained personal access tokens incluem acesso de leitura em repositórios públicos. Para acessar repositórios públicos com um personal access token (classic), selecione o escopo "public_repo".
Se o token não tiver os escopos ou permissões necessários para access um recurso, a API retornará uma mensagem de erro que declara os escopos ou permissões de que seu token precisa.
Autenticação com um GitHub App
Se você quiser usar a API em nome de uma organização ou de outro usuário, a GitHub recomenda que você use um GitHub App. Para atribuir a atividade ao seu aplicativo, você pode fazer com que o aplicativo se autentique como uma instalação de aplicativo. Para atribuir a atividade do aplicativo a um usuário, você pode fazer com que o aplicativo se autentique em nome de um usuário. Em ambos os casos, você vai gerar um token que pode ser usado para se autenticar na API do GraphQL. Para obter mais informações, consulte Registrando um aplicativo GitHub e Sobre a autenticação com um aplicativo GitHub.
Autentique-se com um OAuth app
Para se autenticar com um token OAuth por meio de um OAuth app, primeiro, você precisa autorizar o OAuth app usando um fluxo de aplicativo Web ou um fluxo de dispositivo. Em seguida, você pode usar o token de acesso que recebeu para acessar a API. Para obter mais informações, consulte Criar um aplicativo OAuth e Autorizar aplicativos OAuth.
O ponto final do GraphQL
A API REST tem vários pontos de extremidade. Com a API do GraphQL, o ponto de extremidade permanece constante, seja qual for a operação executada. Para GitHub Enterprise Server, esse ponto de extremidade é:
http(s)://HOSTNAME/api/graphql
Comunicação com o GraphQL
Como as operações do GraphQL consistem em JSON multilinha, GitHub recomenda usar os clientes GraphQL para fazer chamadas graphQL. Você também pode usar curl ou qualquer outra biblioteca que fale HTTP.
Na REST, os verbos HTTP determinam a operação executada. No GraphQL, você fornecerá um texto codificado por JSON se estiver realizando uma consulta ou uma mutação. Portanto, o verbo HTTP é POST. A exceção a isso é uma consulta de introspecção, que é um GET simples para o ponto de extremidade. Para obter mais informações sobre GraphQL versus REST, consulte Fazer a migração de REST para o GraphQL.
Para consultar o GraphQL em um comando curl, faça uma solicitação POST com uma carga JSON. O conteúdo precisa conter uma cadeia de caracteres chamada query:
curl -H "Authorization: bearer TOKEN" -X POST -d " \
{ \
\"query\": \"query { viewer { login }}\" \
} \
" http(s)://HOSTNAME/api/graphql
Observação
O valor da cadeia de caracteres "query" deve fazer o escape de caracteres de nova linha ou o esquema não o analisará corretamente. Para o corpo de POST, use aspas duplas externas e aspas duplas internas com escape.
Sobre consultas e operações de mutação
Os dois tipos de operações permitidas na API do GraphQL do GitHub são queries e mutations. Comparando o GraphQL com a REST, as consultas operam como solicitações GET, enquanto as mutações operam como POST/PATCH/DELETE. O nome da mutação determina a modificação que é executada.
Para obter informações sobre a limitação de taxa, confira Limites de taxas e limites de consultas para a API GraphQL.
As consultas e mutações compartilham formas semelhantes, com algumas diferenças importantes.
Sobre consultas
As consultas do GraphQL retornam apenas os dados especificados. Para formar uma consulta, você precisa especificar campos dentro de campos (também conhecido como subcampos aninhados) até retornar apenas escalares.
As consultas são estruturadas da seguinte forma:
query {
JSON-OBJECT-TO-RETURN
}
Para ver um exemplo do mundo real, confira Exemplo de consulta.
Sobre as mutações
Para formar uma mutação, você deve especificar três coisas:
-
_Nome da mutação_. O tipo de modificação que você deseja realizar. -
_Objeto de entrada_. Os dados que você deseja enviar para o servidor, compostos de _campos de entrada_. Passe-o como um argumento para o nome de mutação. -
_Objeto de carga_. Os dados que você deseja retornar do servidor, compostos de _campos de retorno_. Passe-o como o texto do nome da mutação.
As mutações são estruturadas da seguinte forma:
mutation {
MUTATION-NAME(input: {MUTATION-NAME-INPUT!}) {
MUTATION-NAME-PAYLOAD
}
}
O objeto de entrada deste exemplo é MutationNameInput, e o objeto de conteúdo é MutationNamePayload.
Na referência de mutações, os campos de entrada listados são aqueles que você passa como objeto de entrada. Os campos de retorno listados são o que você transmite como o objeto de conteúdo.
Para ver um exemplo do mundo real, confira Exemplo de mutação.
Trabalhar com variáveis
As [variáveis](https://graphql.org/learn/queries/#variables) podem tornar as consultas mais dinâmicas e eficientes, além de reduzir a complexidade quando transmitir os objetos de entrada de mutação.
Aqui está um exemplo de consulta com uma única variável:
query($number_of_repos:Int!) {
viewer {
name
repositories(last: $number_of_repos) {
nodes {
name
}
}
}
}
variables {
"number_of_repos": 3
}
Existem três etapas para usar variáveis:
-
Defina a variável fora da operação em um objeto
variables:variables { "number_of_repos": 3 }O objeto deve ser um JSON válido. Esse exemplo mostra um tipo de variável
Intsimples, mas é possível definir tipos de variáveis mais complexos, como objetos de entrada. Você também pode definir diversas variáveis aqui. -
Passe a variável para a operação como argumento:
query($number_of_repos:Int!){O argumento é um par chave-valor, em que a chave é o nome que começa com
$(por exemplo,$number_of_repos), e o valor é o tipo (por exemplo,Int). Adicione um!para indicar se o tipo é obrigatório. Se você definiu diversas variáveis, inclua-as aqui como múltiplos argumentos. -
Use a variável dentro da operação:
repositories(last: $number_of_repos) {Neste exemplo, substituímos a variável pelo número de repositórios a ser recuperados. Especificamos um tipo na etapa 2, porque o GraphQL impõe uma digitação forte.
Este processo torna o argumento da consulta dinâmico. Agora, podemos simplesmente alterar o valor no objeto variables e manter o restante da consulta inalterado.
O uso de variáveis como argumentos permite que você atualize os valores dinamicamente no objeto variables sem alterar a consulta.
Consulta de exemplo
Vamos analisar uma questão mais complexa e colocar essas informações no contexto.
A consulta a seguir pesquisa o repositório octocat/Hello-World, encontra as 20 issues fechadas mais recentes e retorna o título, a URL e os 5 rótulos de cada issue:
query {
repository(owner:"octocat", name:"Hello-World") {
issues(last:20, states:CLOSED) {
edges {
node {
title
url
labels(first:5) {
edges {
node {
name
}
}
}
}
}
}
}
}
Observando a composição linha por linha:
-
query {Como queremos ler os dados do servidor e não modificá-los,
queryé a operação raiz. (Se você não especificar uma operação,querytambém será o padrão). -
repository(owner:"octocat", name:"Hello-World") {Para iniciar a consulta, queremos encontrar um objeto
repository. A validação de esquema indica que esse objeto exige umownere um argumentoname. -
issues(last:20, states:CLOSED) {Para considerar todas as questões no repositório, chamamos o objeto
issues. (Podemos consultar um sóissueem umrepository, mas, para isso, precisaremos saber o número do problema que queremos retornar e fornecê-lo como um argumento).Alguns detalhes sobre o objeto
issues:- A documentação nos informa que esse objeto tem o tipo
IssueConnection. - A validação de esquema indica que esse objeto exige um número de resultados
lastoufirstcomo argumento, ou seja, fornecemos20. - A documentação também informa que esse objeto aceita um argumento
states, que é uma enumeraçãoIssueStateque aceita valoresOPENouCLOSED. Para localizar apenas os problemas fechados, damos à chavestatesum valor igual aCLOSED.
- A documentação nos informa que esse objeto tem o tipo
-
edges {Sabemos que
issuesé uma conexão porque ela tem o tipoIssueConnection. Para recuperar dados sobre questões individuais, precisamos acessar o nó por meio deedges. -
node {Aqui, recuperamos o nó no fim da borda. A
IssueConnectiondocumentação indica que o nó no final do tipo é um objetoIssueConnectiontype is anIssue. -
Agora que sabemos que estamos recuperando um objeto
Issue, podemos dar uma olhada na documentação e especificar os campos que queremos retornar:title url labels(first:5) { edges { node { name } } }Aqui, especificamos os campos
title,urlelabelsdo objetoIssue.O campo
labelstem o tipoLabelConnection. Assim como acontece com o objetoissues, comolabelsé uma conexão, precisamos percorrer as bordas até um nó conectado: o objetolabel. No nó, podemos especificar os campos de objetolabelque queremos retornar, nesse caso,name.
Você pode notar que a execução dessa consulta no repositório público Hello-World do Octocat não retornará muitos rótulos. Tente executá-la em um dos seus próprios repositórios que usam etiquetas, e provavelmente você verá uma diferença.
Exemplo de mutação
De modo geral, as mutações exigem informações que você só pode encontrar ao realizar primeiro uma consulta. Este exemplo mostra duas operações:
- Uma consulta para obter um ID de problema.
- Uma mutação para adicionar uma reação de emojis ao 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
}
}
}
Vamos analisar o exemplo. A tarefa parece simples: adicione uma reação emoji a um problema.
Então, como sabemos iniciar com uma consulta? Ainda não sabemos.
Uma vez que desejamos modificar os dados no servidor (anexar um emoji a um problema), começamos procurando uma mutação útil no esquema. A documentação de referência mostra a mutação addReaction, com esta descrição: Adds a reaction to a subject. Perfeito!
A documentação sobre a mutação menciona três campos de entrada:
-
`clientMutationId` (`String`) -
`subjectId` (`ID!`) -
`content` (`ReactionContent!`)
Os !s indicam que subjectId e content são campos obrigatórios. Um content obrigatório faz sentido: desejamos adicionar uma reação e, portanto, precisamos especificar o emoji que deve ser usado.
Mas por que subjectId é obrigatório? Isso ocorre porque a subjectId é a única maneira de identificar a qual problema de qual repositório é preciso reagir.
É por isso que começamos este exemplo com uma consulta: para obter a ID.
Vamos examinar a consulta linha por linha:
-
query FindIssueID {Aqui, estamos executando uma consulta e a nomeamos
FindIssueID. Observe que nomear uma consulta é opcional; nós damos um nome aqui para que possamos incluí-la na mesma janela do cliente da GUI que a mutação. -
repository(owner:"octocat", name:"Hello-World") {Especificamos o repositório consultando o objeto
repositorye transmitindo os argumentosownerename. -
issue(number:349) {Especificamos o problema ao qual é preciso reagir consultando o objeto
issuee transmitindo um argumentonumber. -
idÉ aqui que recuperamos o
iddehttps://github.com/octocat/Hello-World/issues/349para passar como osubjectId.
Quando executamos a consulta, obtemos a id: MDU6SXNzdWUyMzEzOTE1NTE=
Observação
O id retornado na consulta é o valor que passaremos como o subjectID na mutação. Nem a documentação nem a introspecção do esquema indicará essa relação; você precisará entender os conceitos por trás dos nomes para descobrir isso.
Com a identificação conhecida, podemos prosseguir com a mutação:
-
mutation AddReactionToIssue {Aqui, estamos executando uma mutação e a nomeamos
AddReactionToIssue. Assim como acontece com as consultas, nomear uma mutação é opcional; damos um nome aqui para que possamos incluí-lo na mesma janela de cliente gui que a consulta. -
addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {Vamos examinar essa linha:
-
`addReaction` é o nome da mutação. -
`input` é a chave de argumento obrigatória. Isso sempre será `input` para uma mutação. -
`{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}` é o valor de argumento obrigatório. Isso sempre será um [objeto de entrada](/graphql/reference/input-objects) (daí as chaves) composto por campos de entrada (`subjectId` e `content`, neste caso) para uma mutação.
Como sabemos qual é o valor a usar para o conteúdo? A
addReactiondocumentação informa que o campocontenttem o tipoReactionContent, que é um enum, porque só há suporte para algumas reações com emojis nos problemas do GitHub. Estes são os valores permitidos para reações (observe que alguns valores diferem de seus nomes de emojis correspondentes):Conteúdo Emoji +1👍 -1👎 laugh😄 confused😕 heart❤️ hooray🎉 rocket🚀 eyes👀 -
-
O resto da chamada é composto pelo objeto da carga. Aqui é onde especificamos os dados que desejamos que o servidor retorne depois de termos efetuado a mutação. Essas linhas são provenientes da
addReactiondocs, que contêm três campos de retorno possíveis.-
`clientMutationId` (`String`) -
`reaction` (`Reaction!`) -
`subject` (`Reactable!`)
Neste exemplo, retornamos os dois campos obrigatórios (
reactionesubject), ambos com subcampos obrigatórios (contenteid, respectivamente). -
Ao executarmos a mutação, esta é a resposta:
{
"data": {
"addReaction": {
"reaction": {
"content": "HOORAY"
},
"subject": {
"id": "MDU6SXNzdWUyMTc5NTQ0OTc="
}
}
}
}
É isso! Confira sua reção ao problema passando o mouse sobre o 🎉 para localizar seu nome de usuário.
Observação final: quando você passa vários campos em um objeto de entrada, a sintaxe pode ficar pesada. Pode ser útil mover os campos para uma variável. Veja como você poderia reescrever a mutação original usando uma variável:
mutation($myVar:AddReactionInput!) {
addReaction(input:$myVar) {
reaction {
content
}
subject {
id
}
}
}
variables {
"myVar": {
"subjectId":"MDU6SXNzdWUyMTc5NTQ0OTc=",
"content":"HOORAY"
}
}
Observação
Você poderá observar que o valor do campo content no exemplo anterior (em que ele é usado diretamente na mutação) não tem aspas em torno de HOORAY, mas tem aspas quando usado na variável. Há um motivo para isso:
- Quando você usa
contentdiretamente na mutação, o esquema espera que o valor seja do tipoReactionContent, que é uma enumeração, não uma cadeia de caracteres. A validação de esquema causará um erro se você adicionar aspas no valor do enum, já que as aspas são reservadas para strings. - Ao usar
contentem uma variável, a seção de variáveis precisa ser um JSON válido. Portanto, as aspas são obrigatórias. A validação de esquema interpreta corretamente o tipoReactionContentquando a variável é passada para a mutação durante a execução.
Para obter mais informações sobre a diferença entre enumerações e cadeias de caracteres, confira a especificação oficial do GraphQL.
Leitura adicional
Há muito mais que você pode fazer ao formar chamadas no GraphQL. Aqui estão alguns lugares para considerar a seguir:
-
[AUTOTITLE](/graphql/guides/using-pagination-in-the-graphql-api) -
[Fragmentos](https://graphql.org/learn/queries/#fragments) -
[Fragmentos em linha](https://graphql.org/learn/queries/#inline-fragments) -
[Diretivas](https://graphql.org/learn/queries/#directives)