Tuesday, July 13, 2021

Exploring GitHub API

What is GitHub?

GitHub is a site for hosting code. It is a great place to share a portfolio. 

GitHub Website

GitHub User Account

GitHub Repository

Organizations that companies can create

GitHub REST API Authentication

APIs use authentication for security reasons and for rate limiting. What is rate limiting? To make sure an API is available and responsive for all users, it will prevent you from making too many requests too quickly. This restriction is rate limiting.

Access Tokens

To authenticate with the GitHub API, we need to use an access token. An access token is a credential we can generate on the GitHub's website. The token is a string that the API can read and connect with your account.

Using Tokens is better than using a username and password for a few reasons:

  • Typically, you will be accessing API from a script. Your username and password is visible in the script and if someone finds it they can take over your account. With Tokens, it can be revoked to cancel an unauthorized person's access.
  • Tokens can have scopes and specific permissions. For example, you can create a token that has permission to write to your GitHub repositories and make new repositories. You can also make a token that can only read from your repositories.

We need to pass our token to the GitHub API through an authorization header using Python's request library. Just make a dictionary of headers and pass it into our request.

script.py
Output
{'repos_url': 'https://api.github.com/users/VikParuchuri/repos', 'followers_url': 'https://api.github.com/users/VikParuchuri/followers', 'received_events_url': 'https://api.github.com/users/VikParuchuri/received_events', 'blog': 'http://www.vikparuchuri.com', 'owned_private_repos': 17, 'name': 'Vik Paruchuri', 'organizations_url': 'https://api.github.com/users/VikParuchuri/orgs', 'avatar_url': 'https://avatars.githubusercontent.com/u/913340?v=3', 'location': 'Boston, MA', 'followers': 100, 'public_repos': 60, 'starred_url': 'https://api.github.com/users/VikParuchuri/starred{/owner}{/repo}', 'following_url': 'https://api.github.com/users/VikParuchuri/following{/other_user}', 'bio': None, 'hireable': None, 'html_url': 'https://github.com/VikParuchuri', 'following': 10, 'created_at': '2011-07-13T18:18:07Z', 'email': 'vik.paruchuri@gmail.com', 'url': 'https://api.github.com/users/VikParuchuri', 'gravatar_id': '', 'id': 913340, 'gists_url': 'https://api.github.com/users/VikParuchuri/gists{/gist_id}', 'updated_at': '2015-08-19T18:44:48Z', 'subscriptions_url': 'https://api.github.com/users/VikParuchuri/subscriptions', 'total_private_repos': 17, 'events_url': 'https://api.github.com/users/VikParuchuri/events{/privacy}', 'site_admin': False, 'login': 'VikParuchuri', 'type': 'User', 'public_gists': 9, 'company': 'dataquest.io', 'disk_usage': 711120, 'collaborators': 4, 'private_gists': 1, 'plan': {'private_repos': 20, 'name': 'medium', 'space': 976562499, 'collaborators': 0}} Organizations a GitHub user VikParuchuri belongs to is as below: [{'url': 'https://api.github.com/orgs/dataquestio', 'login': 'dataquestio', 'id': 11148054, 'repos_url': 'https://api.github.com/orgs/dataquestio/repos', 'avatar_url': 'https://avatars.githubusercontent.com/u/11148054?v=3', 'events_url': 'https://api.github.com/orgs/dataquestio/events', 'members_url': 'https://api.github.com/orgs/dataquestio/members{/member}', 'public_members_url': 'https://api.github.com/orgs/dataquestio/public_members{/member}', 'description': None}]


Endpoints and Objects:

Collecting information about specific objects (user torvalds in this case) using endpoint as below.

script.py
Output
{'repos_url': 'https://api.github.com/users/torvalds/repos', 'followers_url': 'https://api.github.com/users/torvalds/followers', 'received_events_url': 'https://api.github.com/users/torvalds/received_events', 'blog': None, 'name': 'Linus Torvalds', 'organizations_url': 'https://api.github.com/users/torvalds/orgs', 'avatar_url': 'https://avatars.githubusercontent.com/u/1024025?v=3', 'location': 'Portland, OR', 'followers': 29687, 'public_repos': 2, 'starred_url': 'https://api.github.com/users/torvalds/starred{/owner}{/repo}', 'following_url': 'https://api.github.com/users/torvalds/following{/other_user}', 'bio': None, 'hireable': None, 'html_url': 'https://github.com/torvalds', 'following': 0, 'created_at': '2011-09-03T15:26:22Z', 'email': None, 'url': 'https://api.github.com/users/torvalds', 'gravatar_id': '', 'id': 1024025, 'gists_url': 'https://api.github.com/users/torvalds/gists{/gist_id}', 'updated_at': '2015-06-11T00:46:13Z', 'subscriptions_url': 'https://api.github.com/users/torvalds/subscriptions', 'events_url': 'https://api.github.com/users/torvalds/events{/privacy}', 'site_admin': False, 'login': 'torvalds', 'type': 'User', 'public_gists': 0, 'company': 'Linux Foundation'}
script.py
Output
{'issue_events_url': 'https://api.github.com/repos/octocat/Hello-World/issues/events{/number}', 'blobs_url': 'https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}', 'fork': False, 'network_count': 1109, 'updated_at': '2015-09-05T20:01:28Z', 'labels_url': 'https://api.github.com/repos/octocat/Hello-World/labels{/name}', 'size': 542, 'owner': {'url': 'https://api.github.com/users/octocat', 'gravatar_id': '', 'id': 583231, 'repos_url': 'https://api.github.com/users/octocat/repos', 'gists_url': 'https://api.github.com/users/octocat/gists{/gist_id}', 'received_events_url': 'https://api.github.com/users/octocat/received_events', 'subscriptions_url': 'https://api.github.com/users/octocat/subscriptions', 'login': 'octocat', 'events_url': 'https://api.github.com/users/octocat/events{/privacy}', 'organizations_url': 'https://api.github.com/users/octocat/orgs', 'followers_url': 'https://api.github.com/users/octocat/followers', 'starred_url': 'https://api.github.com/users/octocat/starred{/owner}{/repo}', 'site_admin': False, 'following_url': 'https://api.github.com/users/octocat/following{/other_user}', 'type': 'User', 'avatar_url': 'https://avatars.githubusercontent.com/u/583231?v=3', 'html_url': 'https://github.com/octocat'}, 'has_downloads': True, 'statuses_url': 'https://api.github.com/repos/octocat/Hello-World/statuses/{sha}', 'open_issues_count': 137, 'compare_url': 'https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}', 'default_branch': 'master', 'permissions': {'pull': True, 'admin': False, 'push': False}, 'clone_url': 'https://github.com/octocat/Hello-World.git', 'ssh_url': 'git@github.com:octocat/Hello-World.git', 'git_refs_url': 'https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}', 'stargazers_count': 1400, 'contents_url': 'https://api.github.com/repos/octocat/Hello-World/contents/{+path}', 'subscribers_url': 'https://api.github.com/repos/octocat/Hello-World/subscribers', 'git_commits_url': 'https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}', 'description': 'This your first repo!', 'issues_url': 'https://api.github.com/repos/octocat/Hello-World/issues{/number}', 'events_url': 'https://api.github.com/repos/octocat/Hello-World/events', 'private': False, 'has_issues': True, 'full_name': 'octocat/Hello-World', 'releases_url': 'https://api.github.com/repos/octocat/Hello-World/releases{/id}', 'has_wiki': True, 'language': None, 'comments_url': 'https://api.github.com/repos/octocat/Hello-World/comments{/number}', 'homepage': '', 'watchers_count': 1400, 'has_pages': False, 'forks_count': 1109, 'assignees_url': 'https://api.github.com/repos/octocat/Hello-World/assignees{/user}', 'keys_url': 'https://api.github.com/repos/octocat/Hello-World/keys{/key_id}', 'branches_url': 'https://api.github.com/repos/octocat/Hello-World/branches{/branch}', 'pushed_at': '2015-07-20T20:15:22Z', 'contributors_url': 'https://api.github.com/repos/octocat/Hello-World/contributors', 'collaborators_url': 'https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}', 'name': 'Hello-World', 'git_url': 'git://github.com/octocat/Hello-World.git', 'forks_url': 'https://api.github.com/repos/octocat/Hello-World/forks', 'watchers': 1400, 'downloads_url': 'https://api.github.com/repos/octocat/Hello-World/downloads', 'subscription_url': 'https://api.github.com/repos/octocat/Hello-World/subscription', 'notifications_url': 'https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}', 'mirror_url': None, 'stargazers_url': 'https://api.github.com/repos/octocat/Hello-World/stargazers', 'html_url': 'https://github.com/octocat/Hello-World', 'tags_url': 'https://api.github.com/repos/octocat/Hello-World/tags', 'created_at': '2011-01-26T19:01:12Z', 'trees_url': 'https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}', 'url': 'https://api.github.com/repos/octocat/Hello-World', 'teams_url': 'https://api.github.com/repos/octocat/Hello-World/teams', 'id': 1296269, 'git_tags_url': 'https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}', 'hooks_url': 'https://api.github.com/repos/octocat/Hello-World/hooks', 'forks': 1109, 'languages_url': 'https://api.github.com/repos/octocat/Hello-World/languages', 'archive_url': 'https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}', 'merges_url': 'https://api.github.com/repos/octocat/Hello-World/merges', 'open_issues': 137, 'commits_url': 'https://api.github.com/repos/octocat/Hello-World/commits{/sha}', 'subscribers_count': 1763, 'issue_comment_url': 'https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}', 'milestones_url': 'https://api.github.com/repos/octocat/Hello-World/milestones{/number}', 'svn_url': 'https://github.com/octocat/Hello-World', 'pulls_url': 'https://api.github.com/repos/octocat/Hello-World/pulls{/number}'}


Pagination

What is pagination? When there is too much data to return, it will take a long time and slow the server down. This is not a great user experience, so it is usual for API providers to implement pagination. This means that the API provider will only return a certain number of records per page.

For example, say you want to list out all of a user's repositories, if a user has 1K repositories, requesting all of them might take 10+ seconds which is too much time.

Here is the link to GitHub API documentation on Pagination


script.py
Variables
page2_repos
params
headers
page1_repos
response

POST Requests

POST Requests are for sending information and to create objects on the API's server. With the GitHub API, we can use POST requests to create new repositories.

Not all API's endpoint will accept a POST request and not all will accept a GET request. Refer the API's documentation to figure out which endpoints accept which types of requests.

Use Python's requests.post() method to make POST requests. POST requests almost always include payload. The server will use this payload to create new objects.

script.py
Output
201 201

This code will create repositories under the account of the currently authenticated user. It will convert the payload dictionary to the JSON and pass it along with the POST request.

201 status code means the object has been created on the server. Sometimes, the API returns the JSON representation of the new object as the content of the response.

PUT/PATCH Requests

PATCH is to update an existing object on the server, like changing few attributes(name of repo for example) of the object.

PUT is sending the complete object we are revising as a replacement for the server's existing version.
Sometimes, the API endpoints that accept PUT requests will treat them like PATCH requests and not require us to send the complete object back. So in practice, API developers don't always respect this convention.

script.py
Output
200 200

Status code 200 means the PATCH is SUCCESSFUL.

DELETE Requests

This deletes objects from the server. For example, removing repos in GitHub

cript.py
Output
204 204
script.py

Status code 204 indicates successful deletion.

Here is the takeaway from this article:

  • What is GitHub?
  • API Authentication and Access Tokens
  • Pagination
  • Rate Limiting
  • Different API endpoints choose what type of requests they will accept
  • Explored GitHub REST API requests - POST, PUT/PATCH, DELETE Requests
Skills Acquired:
  • How to make authenticated API requests using Access Tokens
  • Pagination
  • POST, PUT/PATCH and DELETE
Tools Used:
  • Python requests library 
  • requests.get()
  • response.json()
  • Two pagination query parameters page and per_page
  • requests.post(), requests.patch(), requests.delete()

Thank you!

 













































































































No comments: