GitHub limite de taxa de API excedido: o que significa e como lidar com ela

GitHub limita quantas solicitações de API REST seu aplicativo pode enviar. Quando você ultrapassa um limite, GitHub recusa suas solicitações com um 403 ou 429 status até que o limite seja redefinido ou o tempo de espera passe. GitHub tem dois tipos de limites: um limite primário de solicitações por hora e limites secundários que protegem contra picos. Se o aplicativo continuar enviando solicitações enquanto estiver sujeito a limite de taxa, GitHub poderá proibir sua integração. Para obter mais informações, consulte Os limites de taxa para a API REST.

Como são os limites de taxa de GitHub

Limit Value Quando você analisa isso
Primário, não autenticado 60 solicitações por hora, por endereço IP 403 ou 429, e x-ratelimit-remaining é 0
Token de acesso principal, pessoal 5.000 solicitações por hora O mesmo que acima
Primary, GITHUB_TOKEN em GitHub Actions 1.000 solicitações por hora, por repositório O mesmo que acima
Secundário Por exemplo, não mais do que 100 solicitações simultâneas, 900 pontos por minuto para endpoints REST e cerca de 80 solicitações de geração de conteúdo por minuto 403 ou 429 com uma mensagem de erro. retry-after pode estar presente.

GitHub pode alterar os limites secundários sem aviso prévio e não há como verificar o quão perto você está deles.

Cada resposta inclui cabeçalhos que informam onde você está no limite primário:

Header O que isso te diz
x-ratelimit-limit O máximo de solicitações que você pode enviar por hora
x-ratelimit-remaining Quantas solicitações você ainda tem na janela atual
x-ratelimit-used Quantas solicitações você enviou na janela atual
x-ratelimit-reset Quando a janela é redefinida, em segundos de época UTC
x-ratelimit-resource Em qual limite a solicitação foi contabilizada

Como lidar com um limite de requisições do GitHub

  1. Diferencie um limite de taxa de um erro de permissão. GitHub também retorna 403 quando o token não tem permissão de acesso. Se a resposta não tiver retry-after, x-ratelimit-remaining não for 0 e a mensagem não mencionar um limite de taxa, é um problema de permissão. Não tente de novo.
  2. Siga retry-after primeiro. Se o cabeçalho estiver presente, aguarde esse número de segundos.
  3. Caso contrário, aguarde a reinicialização. Se x-ratelimit-remaining for 0, não tente novamente até a hora exibida em x-ratelimit-reset.
  4. Caso contrário, aguarde pelo menos 1 minuto. Para um limite secundário sem nenhum dos cabeçalhos, GitHub solicita que você aguarde pelo menos 1 minuto e aguarde mais tempo após cada tentativa com falha. Pare após um número definido de tentativas e gere um erro.
  5. Vá com calma antes que seus créditos acabem. Use x-ratelimit-remaining e x-ratelimit-reset para controlar o ritmo das suas solicitações. Não baseie sua lógica em um número exato restante, porque o GitHub pode alterar os limites. Os x-ratelimit-* cabeçalhos são a fonte da verdade, não o GET /rate_limit endpoint.
async function githubWaitMs(response, attempt) {
  if (response.status !== 403 && response.status !== 429) {
    return null;
  }
  const retryAfter = response.headers.get('retry-after');
  if (retryAfter) {
    return Number(retryAfter) * 1000;
  }
  if (response.headers.get('x-ratelimit-remaining') === '0') {
    const resetMs = Number(response.headers.get('x-ratelimit-reset')) * 1000;
    return Math.max(resetMs - Date.now(), 0);
  }
  const { message = '' } = await response.clone().json().catch(() => ({}));
  if (response.status === 429 || /rate limit/i.test(message)) {
    return 60_000 * 2 ** attempt;
  }
  // A 403 without rate limit signals is a permission problem: don't retry
  return null;
}

O chamador tenta novamente quando a função retorna um número e para após algumas tentativas.

Como testar se seu aplicativo lida com os limites de taxa do GitHub

Você raramente esbarra no limite de requisições do GitHub enquanto desenvolve. Você envia algumas solicitações, e 5.000 por hora parece não ter fim. Portanto, a forma como você testa o tratamento da limitação de taxa determina se você vai encontrar os bugs antes que seus usuários encontrem.

Approach O que você encontra Do que você sente falta
Aguardar produção Falhas reais Tudo, até que um usuário toque nele
Fazer mock da API em seus testes ou deixar seu agente de codificação escrever o mock Se a ramificação de repetição for executada os cabeçalhos reais e os corpos de erro do GitHub e a política de repetição do SDK. Seu aplicativo também precisa de uma opção somente de teste para acessar o mock.
Chame a API de produção até atingir o limite de taxa Comportamento real São necessárias até 5.000 solicitações, você não pode disparar um limite secundário sob demanda e sua integração pode ser banida
Interceptar o tráfego real do aplicativo e retornar respostas de limite de taxa sob demanda URLs reais, seu SDK real e política de repetição e os cabeçalhos e o formato de erro do próprio GitHub Nada no aplicativo muda, portanto, ele não testa seu código isoladamente. Mantenha seus testes de unidade para isso.

Experimente em seu aplicativo

Dev Proxy intercepta as solicitações do seu aplicativo para api.github.com e retorna respostas de limite de taxa no estilo do GitHub, enquanto seu aplicativo continua chamando as URLs reais. A predefinição github-rate-limiting contabiliza suas solicitações em um limite de 60 por hora, envia os cabeçalhos x-ratelimit-* e retorna um 429 com API rate limit exceeded quando esse limite se esgota. Até lá, suas solicitações vão para o GitHub e também contam em seu limite real.

Baixe o preset e inicie o Dev Proxy com ele:

devproxy config get github-rate-limiting
devproxy --config-file "~dataFolder/configs/github-rate-limiting/.devproxy/devproxyrc.json"

Para testar os limites secundários, inicie o Proxy de Desenvolvimento com devproxyrc-secondary.json da mesma pasta. Ele retorna aleatoriamente um limite secundário de taxa 429 com um cabeçalho retry-after.

Em seguida, execute seu aplicativo como de costume e observe o que ele faz. Para instalar o Dev Proxy, consulte Configurar o Dev Proxy.

Próximas Etapas 

Consulte também