🏠 | 💻 IT | API |

Работа с API github

Curl

Рассмотрим обращения к API сайта github.com с помощью Curl

Нужно проверить установлен ли Curl

curl -V

Command 'curl' not found, but can be installed with:

sudo apt install curl

Если не установлен - нужно выполнить

sudo apt install curl

А если у вас CentOS , RedHat или другой .rpm то

sudo yum install curl

[sudo] password for andrei: Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: curl 0 upgraded, 1 newly installed, 0 to remove and 6 not upgraded. Need to get 161 kB of archives. After this operation, 411 kB of additional disk space will be used. Get:1 http://fi.archive.ubuntu.com/ubuntu focal-updates/main amd64 curl amd64 7.68.0-1ubuntu2.4 [161 kB] Fetched 161 kB in 0s (2,485 kB/s) Selecting previously unselected package curl. (Reading database ... 302218 files and directories currently installed.) Preparing to unpack .../curl_7.68.0-1ubuntu2.4_amd64.deb ... Unpacking curl (7.68.0-1ubuntu2.4) ... Setting up curl (7.68.0-1ubuntu2.4) ... Processing triggers for man-db (2.9.1-1) ...

После установки нужно убедиться в успехе

curl -V

curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3 Release-Date: 2020-01-08 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets

Выполните запрос к api.github.com/zen чтобы получить мудрое иречение

curl https://api.github.com/zen

Practicality beats purity.

Или что-то в этом духе

Выполним GET запрос к профилю пользователя defunkt

curl https://api.github.com/users/defunkt

{ "login": "defunkt", "id": 2, "node_id": "MDQ6VXNlcjI=", "avatar_url": "https://avatars.githubusercontent.com/u/2?v=4", "gravatar_id": "", "url": "https://api.github.com/users/defunkt", … }

Похоже, что ответ в виде JSON

curl -i https://api.github.com/users/defunkt

HTTP/2 200 date: Mon, 08 Feb 2021 13:15:21 GMT content-type: application/json; charset=utf-8 server: GitHub.com cache-control: public, max-age=60, s-maxage=60 vary: Accept, Accept-Encoding, Accept, X-Requested-With, Accept-Encoding etag: W/"e9d01ee58678d144f1a7409ff7d7d7c7e624e193e248a29188d0302f808e3938" last-modified: Fri, 01 Nov 2019 21:56:00 GMT x-github-media-type: github.v3; format=json access-control-expose-headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset access-control-allow-origin: * strict-transport-security: max-age=31536000; includeSubdomains; preload x-frame-options: deny x-content-type-options: nosniff x-xss-protection: 1; mode=block referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin content-security-policy: default-src 'none' x-ratelimit-limit: 60 x-ratelimit-remaining: 55 x-ratelimit-reset: 1612793303 x-ratelimit-used: 5 accept-ranges: bytes content-length: 1305 x-github-request-id: 30FD:5608:38B0A98:3E19DCC:60213968 { "login": "defunkt", "id": 2, "node_id": "MDQ6VXNlcjI=", "avatar_url": "https://avatars.githubusercontent.com/u/2?v=4", "gravatar_id": "", "url": "https://api.github.com/users/defunkt", … }

Как и ожидалось формат ответа это JSON

content-type: application/json

Все заголовки (headers), которые начиются с X- это специальные заголовки (custom headers), они не включены в спецификацию HTTP.

Например:

X-GitHub-Media-Type имеет значение github.v3. Это информация о специфичном для Github типе media в ответе.

С помощью полученного типа media можно сделать вывод о версии API к которому мы обращались (API v3)

Обратите внимание на заголовки X-RateLimit-Limit и X-RateLimit-Remaining. Эта пара показывает сколько запросов клиент может сделать за один временной цикл (обычно это час) и сколько уже потрачено.

Аутентификация

Незарегистрированный пользователь может делать максимум 60 запросов к api.github.com в час.

Создайте профиль на github.com и переходите к генерации токена.

Зайдите на github.com/settings/tokens

Personal access tokens → Generate new token

Токен будет выглядеть как набор символов похожий на

b69c3bd7bbhc71645275688850269c3bd7bd68s5

Если возникли сложности - прочитайте инструкцию

Выполните в bash команду

token=b69c3bd7bbhc71645275688850269c3bd7bd68s5

Вместо b69c3… подставьте свой токен

Теперь вы можете выполнить запрос

curl -i -u your_username:$token https://api.github.com/users/your_username

Вместо your_username подставьте имя своего аккаунта на github и вы получите информацию о своём аккаунте без ввода пароля.

X-RateLimit-Limit должен увеличится до 5000

x-ratelimit-limit: 5000

To получить персональную информацию о вашем профиле имея токен не обязательно обращатсья на /users/your_username

Можно использовать просто user

curl -i -u your_username:$token https://api.github.com/user

your_username замените на имя профиля а вот user в конце трогать не нужно - это часть эндпойнта

To получить информацию о публичном репозитории, например, Gulp execute

curl -i https://api.github.com/repos/gulpjs/gulp

HTTP/2 200 date: Mon, 08 Feb 2021 15:31:12 GMT content-type: application/json; charset=utf-8 server: GitHub.com cache-control: public, max-age=60, s-maxage=60 vary: Accept, Accept-Encoding, Accept, X-Requested-With, Accept-Encoding etag: W/"3d5c4fe70d9cf6c1cf4a2ecc79a437598f9c7dd89f4534408f243021edfa4a3f" last-modified: Mon, 08 Feb 2021 15:02:57 GMT x-github-media-type: github.v3; format=json access-control-expose-headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset access-control-allow-origin: * strict-transport-security: max-age=31536000; includeSubdomains; preload x-frame-options: deny x-content-type-options: nosniff x-xss-protection: 1; mode=block referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin content-security-policy: default-src 'none' x-ratelimit-limit: 60 x-ratelimit-remaining: 58 x-ratelimit-reset: 1612801683 x-ratelimit-used: 2 accept-ranges: bytes content-length: 6192 x-github-request-id: B4E6:AA66:ABF984:C01840:60215940 { "id": 11167738, "node_id": "MDEwOlJlcG9zaXRvcnkxMTE2NzczOA==", "name": "gulp", "full_name": "gulpjs/gulp", "private": false, "owner": { "login": "gulpjs", "id": 6200624, "node_id": "MDEyOk9yZ2FuaXphdGlvbjYyMDA2MjQ=", "avatar_url": "https://avatars.githubusercontent.com/u/6200624?v=4", "gravatar_id": "", "url": "https://api.github.com/users/gulpjs", "html_url": "https://github.com/gulpjs", "followers_url": "https://api.github.com/users/gulpjs/followers", "following_url": "https://api.github.com/users/gulpjs/following{/other_user}", "gists_url": "https://api.github.com/users/gulpjs/gists{/gist_id}", "starred_url": "https://api.github.com/users/gulpjs/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/gulpjs/subscriptions", "organizations_url": "https://api.github.com/users/gulpjs/orgs", "repos_url": "https://api.github.com/users/gulpjs/repos", "events_url": "https://api.github.com/users/gulpjs/events{/privacy}", "received_events_url": "https://api.github.com/users/gulpjs/received_events", "type": "Organization", "site_admin": false }, "html_url": "https://github.com/gulpjs/gulp", "description": "A toolkit to automate & enhance your workflow", "fork": false, "url": "https://api.github.com/repos/gulpjs/gulp", "forks_url": "https://api.github.com/repos/gulpjs/gulp/forks", "keys_url": "https://api.github.com/repos/gulpjs/gulp/keys{/key_id}", "collaborators_url": "https://api.github.com/repos/gulpjs/gulp/collaborators{/collaborator}", "teams_url": "https://api.github.com/repos/gulpjs/gulp/teams", "hooks_url": "https://api.github.com/repos/gulpjs/gulp/hooks", "issue_events_url": "https://api.github.com/repos/gulpjs/gulp/issues/events{/number}", "events_url": "https://api.github.com/repos/gulpjs/gulp/events", "assignees_url": "https://api.github.com/repos/gulpjs/gulp/assignees{/user}", "branches_url": "https://api.github.com/repos/gulpjs/gulp/branches{/branch}", "tags_url": "https://api.github.com/repos/gulpjs/gulp/tags", "blobs_url": "https://api.github.com/repos/gulpjs/gulp/git/blobs{/sha}", "git_tags_url": "https://api.github.com/repos/gulpjs/gulp/git/tags{/sha}", "git_refs_url": "https://api.github.com/repos/gulpjs/gulp/git/refs{/sha}", "trees_url": "https://api.github.com/repos/gulpjs/gulp/git/trees{/sha}", "statuses_url": "https://api.github.com/repos/gulpjs/gulp/statuses/{sha}", "languages_url": "https://api.github.com/repos/gulpjs/gulp/languages", "stargazers_url": "https://api.github.com/repos/gulpjs/gulp/stargazers", "contributors_url": "https://api.github.com/repos/gulpjs/gulp/contributors", "subscribers_url": "https://api.github.com/repos/gulpjs/gulp/subscribers", "subscription_url": "https://api.github.com/repos/gulpjs/gulp/subscription", "commits_url": "https://api.github.com/repos/gulpjs/gulp/commits{/sha}", "git_commits_url": "https://api.github.com/repos/gulpjs/gulp/git/commits{/sha}", "comments_url": "https://api.github.com/repos/gulpjs/gulp/comments{/number}", "issue_comment_url": "https://api.github.com/repos/gulpjs/gulp/issues/comments{/number}", "contents_url": "https://api.github.com/repos/gulpjs/gulp/contents/{+path}", "compare_url": "https://api.github.com/repos/gulpjs/gulp/compare/{base}...{head}", "merges_url": "https://api.github.com/repos/gulpjs/gulp/merges", "archive_url": "https://api.github.com/repos/gulpjs/gulp/{archive_format}{/ref}", "downloads_url": "https://api.github.com/repos/gulpjs/gulp/downloads", "issues_url": "https://api.github.com/repos/gulpjs/gulp/issues{/number}", "pulls_url": "https://api.github.com/repos/gulpjs/gulp/pulls{/number}", "milestones_url": "https://api.github.com/repos/gulpjs/gulp/milestones{/number}", "notifications_url": "https://api.github.com/repos/gulpjs/gulp/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/gulpjs/gulp/labels{/name}", "releases_url": "https://api.github.com/repos/gulpjs/gulp/releases{/id}", "deployments_url": "https://api.github.com/repos/gulpjs/gulp/deployments", "created_at": "2013-07-04T05:26:06Z", "updated_at": "2021-02-08T15:02:57Z", "pushed_at": "2021-01-29T11:54:48Z", "git_url": "git://github.com/gulpjs/gulp.git", "ssh_url": "git@github.com:gulpjs/gulp.git", "clone_url": "https://github.com/gulpjs/gulp.git", "svn_url": "https://github.com/gulpjs/gulp", "homepage": "https://gulpjs.com", "size": 1089, "stargazers_count": 32106, "watchers_count": 32106, "language": "JavaScript", "has_issues": true, "has_projects": true, "has_downloads": true, "has_wiki": false, "has_pages": false, "forks_count": 4395, "mirror_url": null, "archived": false, "disabled": false, "open_issues_count": 24, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "https://api.github.com/licenses/mit", "node_id": "MDc6TGljZW5zZTEz" }, "forks": 4395, "open_issues": 24, "watchers": 32106, "default_branch": "master", "temp_clone_token": null, "organization": { "login": "gulpjs", "id": 6200624, "node_id": "MDEyOk9yZ2FuaXphdGlvbjYyMDA2MjQ=", "avatar_url": "https://avatars.githubusercontent.com/u/6200624?v=4", "gravatar_id": "", "url": "https://api.github.com/users/gulpjs", "html_url": "https://github.com/gulpjs", "followers_url": "https://api.github.com/users/gulpjs/followers", "following_url": "https://api.github.com/users/gulpjs/following{/other_user}", "gists_url": "https://api.github.com/users/gulpjs/gists{/gist_id}", "starred_url": "https://api.github.com/users/gulpjs/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/gulpjs/subscriptions", "organizations_url": "https://api.github.com/users/gulpjs/orgs", "repos_url": "https://api.github.com/users/gulpjs/repos", "events_url": "https://api.github.com/users/gulpjs/events{/privacy}", "received_events_url": "https://api.github.com/users/gulpjs/received_events", "type": "Organization", "site_admin": false }, "network_count": 4395, "subscribers_count": 1102 }

To получить список своих репозиториев execute

curl -i -H "Authorization: token $token" https://api.github.com/user/repos

HTTP/2 200 date: Mon, 08 Feb 2021 15:36:03 GMT content-type: application/json; charset=utf-8 … [ { "id": 274622933, "node_id": "POLdiuJlcG9zaXRvcnkzMDkxMjI5MzM=", "name": "your_firts_repo", "full_name": "your_username/your_firts_repo", "private": false, "owner": { "login": "your_username", …

Изучить репозитории другого пользователя, например Django

curl -i https://api.github.com/users/django/repos

Точно также вы можете изучить и свой репозиторий - не обязательно использовать аутентификацию если аккаунт публичный.

Помимо пользователей - есть ещё и аккаунты организаций. К ним тоже можно делать запросы

curl -i https://api.github.com/orgs/octo-org/repos

Области применения (scopes)

Токены различаются своей областью применения

Выполнив один и тот же запрос с двумя разными токенами можно получить разные ответы

Информация, которую возвращают запросы зависит от области применения которую имел токен с помощью которого прошла аутентификация

Share in social media: