source

github API에서 링크 헤더를 해석하는 방법

ittop 2023. 3. 18. 09:23
반응형

github API에서 링크 헤더를 해석하는 방법

github API는 http 링크 헤더에 json 결과의 페이지화 데이터를 전송합니다.

Link: <https://api.github.com/repos?page=3&per_page=100>; rel="next",
<https://api.github.com/repos?page=50&per_page=100>; rel="last"

github API만이 이 메서드를 사용하는 것은 아니기 때문에(예를 들어 링크 헤더를 해석하고 배열로 변환하는 등) js앱에 사용할 수 있도록 누군가가 유용한 작은 스니펫을 가지고 있는지 묻고 싶었습니다.

구글에서 검색했지만 json API에서 페이지 매김을 해석하는 방법에 대한 유용한 정보를 찾을 수 없었습니다.

parse-link-header NPM 모듈은 이 목적을 위해 존재합니다.그 소스는 MIT 라이선스로 github에 있습니다(상용에는 무료입니다).

설치는 다음과 같이 간단합니다.

npm install parse-link-header

사용 방법은 다음과 같습니다.

var parse = require('parse-link-header');
var parsed = parse('<https://api.github.com/repos?page=3&per_page=100>; rel="next", <https://api.github.com/repos?page=50&per_page=100>; rel="last"')

...그 후, 한 사람은parsed.next,parsed.last등:

{ next:
   { page: '3',
     per_page: '100',
     rel: 'next',
     url: 'https://api.github.com/repos?page=3&per_page=100' },
  last:
   { page: '50',
     per_page: '100',
     rel: 'last',
     url: ' https://api.github.com/repos?page=50&per_page=100' } }

GitHub Java API에는 PageLinks 클래스가 있습니다.이 클래스는 PageLinks를 해석하는 방법을 보여줍니다.Linkheader를 클릭합니다.

는 이 Gist를 찾았다:

해석기허브LinksJavaScript의 헤더

Github API에서 테스트한 결과 다음과 같은 오브젝트가 반환됩니다.

var results = {
    last: "https://api.github.com/repositories/123456/issues?access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&state=open&since=2013-07-24T02%3A12%3A30.309Z&direction=asc&page=4"
    next: "https://api.github.com/repositories/123456/issues?access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&state=open&since=2013-07-24T02%3A12%3A30.309Z&direction=asc&page=2"
};

기써브에서 웜블턴/링크헤더를 찾았어요npm 모듈이 아닌 브라우저용으로 만들어진 것 같습니다만, 서버측 환경에서 동작하도록 수정하는 것은 어렵지 않을 것 같습니다.문자열 분할이 아닌 실제 RFC 5988 파서를 생성하기 위해 pegjs를 사용하기 때문에 Github뿐만 아니라 링크 헤더에서도 정상적으로 동작합니다.

이게 '기술적으로' 중요한 일이라는 걸 완전히 이해해요JavaScript실.하지만 저와 마찬가지로 구글의 "링크 헤더를 해석하는 방법"을 통해 이곳에 도착했다면 제 환경(C#)을 위한 솔루션을 공유하려고 합니다.

public class LinkHeader
{
    public string FirstLink { get; set; }
    public string PrevLink { get; set; }
    public string NextLink { get; set; }
    public string LastLink { get; set;}

    public static LinkHeader FromHeader(string linkHeader)
    {
        LinkHeader linkHeader = null;

        if (!string.IsNullOrWhiteSpace(linkHeader))
        {
            string[] linkStrings = linkHeader.Split("\",");

            if (linkStrings != null && linkStrings.Any())
            {
                linkHeader = new LinkHeader();

                foreach (string linkString in linkStrings)
                {
                    var relMatch = Regex.Match(linkString, "(?<=rel=\").+?(?=\")", RegexOptions.IgnoreCase);
                    var linkMatch = Regex.Match(linkString, "(?<=<).+?(?=>)", RegexOptions.IgnoreCase);

                    if (relMatch.Success && linkMatch.Success)
                    {
                        string rel = relMatch.Value.ToUpper();
                        string link = linkMatch.Value;

                        switch (rel)
                        {
                            case "FIRST":
                                linkHeader.FirstLink = link;
                                break;
                            case "PREV":
                                linkHeader.PrevLink = link;
                                break;
                            case "NEXT":
                                linkHeader.NextLink = link;
                                break;
                            case "LAST":
                                linkHeader.LastLink = link;
                                break;
                        }
                    }
                }
            }
        }

        return linkHeader;
    }
}

GitHub의 예인 Link 헤더를 사용하여 콘솔 앱에서 테스트:

void Main()
{
    string link = "<https://api.github.com/user/repos?page=3&per_page=100>; rel=\"next\",< https://api.github.com/user/repos?page=50&per_page=100>; rel=\"last\"";
    LinkHeader linkHeader = LinkHeader.FromHeader(link);
}

링크에서 유용한 정보를 멋진 객체 표기로 추출하는 간단한 Javascript 함수입니다.

var linkParser = (linkHeader) => {
  let re = /<([^\?]+\?[a-z]+=([\d]+))>;[\s]*rel="([a-z]+)"/g;
  let arrRes = [];
  let obj = {};
  while ((arrRes = re.exec(linkHeader)) !== null) {
    obj[arrRes[3]] = {
      url: arrRes[1],
      page: arrRes[2]
    };
  }
  return obj;
}

결과는 다음과 같이 출력됩니다== >

{
  "next": {
    "url": "https://api.github.com/user/9919/repos?page=2",
    "page": "2"
  },
  "last": {
    "url": "https://api.github.com/user/9919/repos?page=10",
    "page": "10"
  }
}

Python을 사용할 수 있고 완전한 사양을 구현하고 싶지 않지만 Github API에 적합한 것이 필요한 경우 다음과 같이 하십시오.

import re
header_link = '<https://api.github.com/repos?page=3&per_page=100>; rel="next", <https://api.github.com/repos?page=50&per_page=100>; rel="last"'
if re.search(r'; rel="next"', header_link):
    print re.sub(r'.*<(.*)>; rel="next".*', r'\1', header_link)

여기 긴 쿼리에서 모든 페이지를 가져올 수 있는 컬과 sed를 포함한 간단한 bash 스크립트가 있습니다.

url="https://api.github.com/repos/$GIT_USER/$GIT_REPO/issues"
while [ "$url" ]; do
      echo "$url" >&2
      curl -Ss -n "$url"
      url="$(curl -Ss -I -n "$url" | sed -n -E 's/Link:.*<(.*?)>; rel="next".*/\1/p')"
done > issues.json

Java에서 Link Header 파서를 검색하게 된 사용자는 다음을 사용할 수 있습니다.javax.ws.rs.core.Link예를 들면, 이하를 참조해 주세요.

import javax.ws.rs.core.Link

String linkHeaderValue = "<https://api.github.com/repos?page=3&per_page=100>; rel='next'";
Link link = Link.valueOf(linkHeaderValue);

원래 parse-link-header 패키지를 사용하는 대신 다른 옵션은 @web3-storage/parse-link-header입니다.오리지널 NPM 패키지의 포크 버전입니다.API는 동일하지만 다음과 같은 이점이 있습니다.

  • TypeScript 지원
  • 의존 관계가 없음
  • Node.js 글로벌 및 ESM 없음

설치:

npm install @web3-storage/parse-link-header

사용방법:

import { parseLinkHeader } from '@web3-storage/parse-link-header'

const linkHeader =
  '<https://api.github.com/user/9287/repos?page=3&per_page=100>; rel="next", ' +
  '<https://api.github.com/user/9287/repos?page=1&per_page=100>; rel="prev"; pet="cat", ' +
  '<https://api.github.com/user/9287/repos?page=5&per_page=100>; rel="last"'

const parsed = parseLinkHeader(linkHeader)
console.log(parsed)

출력:

{
   "next":{
      "page":"3",
      "per_page":"100",
      "rel":"next",
      "url":"https://api.github.com/user/9287/repos?page=3&per_page=100"
   },
   "prev":{
      "page":"1",
      "per_page":"100",
      "rel":"prev",
      "pet":"cat",
      "url":"https://api.github.com/user/9287/repos?page=1&per_page=100"
   },
   "last":{
      "page":"5",
      "per_page":"100",
      "rel":"last",
      "url":"https://api.github.com/user/9287/repos?page=5&per_page=100"
   }
}

여기 모든 github repo에 대한 기여자 수를 얻기 위한 Python 솔루션이 있습니다.

import requests
from urllib.parse import parse_qs

rsp = requests.head('https://api.github.com/repos/fabric8-analytics/fabric8-analytics-server/contributors?per_page=1')
contributors_count = parse_qs(rsp.links['last']['url'])['page'][0]

Java Script에서 GitHub의 링크 헤더를 해석하기 위한 간단한 코드입니다.

var parse = require('parse-link-header');
    var parsed = parse(res.headers.link);
    no_of_pages = parsed.last.page;

이것은 목적에 맞는 Java 함수이며 제공된 파라미터 키와 파라미터 값의 링크를 찾을 수 있습니다.주의사항:이것은 개인적인 목적을 위해 만든 것이므로 시나리오에 대한 잘못된 증거가 아닐 수 있으므로 검토 후 변경하십시오.

https://github.com/akshaysom/LinkExtract/blob/main/LinkExtract.java

  public static String getLinkFromLinkHeaderByParamAndValue(String header, String param, String value) {
            if (header != null && param != null && value != null && !"".equals(header.trim()) && !"".equals(param.trim())
                    && !"".equals(value)) {
    
                String[] links = header.split(",");
    
                LINKS_LOOP: for (String link : links) {
    
                    String[] segments = link.split(";");
    
                    if (segments != null) {
    
                        String segmentLink = "";
    
                        SEGMENT_LOOP: for (String segment : segments) {
                            segment = segment.trim();
                            if (segment.startsWith("<") && segment.endsWith(">")) {
    
                                segmentLink = segment.substring(1, segment.length() - 1);
                                continue SEGMENT_LOOP;
    
                            } else {
                                if (segment.split("=").length > 1) {
    
                                    String currentSegmentParam = segment.split("=")[0].trim();
                                    String currentSegmentValue = segment.split("=")[1].trim();
    
                                    if (param.equals(currentSegmentParam) && value.equals(currentSegmentValue)) {
                                        return segmentLink;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return null;
        }

언급URL : https://stackoverflow.com/questions/8735792/how-to-parse-link-header-from-github-api

반응형