GitHub has its official URL Shortening service, GIt.io. You can generate a shortened URL of a GitHub URL by sending an HTTP POST request to its API endpint, for example, through the command line:

$ curl -i http://git.io -F "url=http://github.com/..."

It will return a 201 Created response, with the shortened URL stored in the Location response header.

However, if you often need to shorten an URL on GitHub.com, it might be annoying typing the command manually each time.

I made a Chrome Extension to do that in a really easy way. When visiting a page on GitHub, you’ll see a small git.io icon at the end of address bar, click it, and the shortened URL will be generated. You can copy it to the clipboard by clicking on the shortened URL.

Git.io URL Shortener Demo

Get It Now!

It’s available on the Chrome Web Store (and the source code is on GitHub, too). Give it a try and see if it saves your time!

Limitations

No Custom Code

According to GIt.io’s documentation, we can specify code=yay to generate a shortened URL with preferred code, in this example, http://git.io/yay. But the purpose of this extension is to help you shorten URL with one click, and so far I have no idea on how to design an interface for the preferred code. If you have a good idea, please tell me.

GitHub Domains Only (Indeed)

Currently it only supports URLs with hostname equals to one of these:

  • github.com
  • gist.github.com
  • raw.github.com
  • developer.github.com
  • develop.github.com

By invoking the API endpoint http://git.io with a non-GitHub URL, the server will return a 422 Unprocessable Entity error response, along with the body text:

URL must match /^((gist|raw|develop(er)?)\.)?github\.com$/

That’s how I limit the supported domains.


Now I’d like to talk about 2 things about Ajax that I learned from this project.

Sending POST Request with XMLHttpRequest

Git.io is a HTTP-only API, even the shortened URL is stored in the Location header of response. As the source code of Git.io’s service presents, there is no JSON API for the servie, not to say a JSONP service. So we must call the service by directly sending POST HTTP request to the API endpoint.

Although we can include a jQuery library to deal with Ajax things, I don’t want to include such a big library witin an non-app extension. And because I’ve never programmed with XMLHttpRequest object directly before, I took some document-searching. The source code of background.js shows how I send a POST request to the remote server:

var xhr = new XMLHttpRequest(); // make a XMLHttpRequest object
var form_data = new FormData(); // make a FormData object for easy serialization

form_data.append("url", url); // add URL to the form data

// set the callback function for this XMLHttpRequest object
xhr.onload = function(e) { // Callback when it is loaded
  if (xhr.status === 201) { // Created
    var shortened_url = xhr.getResponseHeader("Location"); // get the shortened URL
    console.log(shortened_url); // or return the shortened_url with a callback
  }
};

xhr.open("POST", "http://git.io", true);
xhr.send(form_data);  // send form data

To send a POST request:

  1. Make a new XMLHttpRequest object for HTTP request.
  2. Make a FormData object for storing the form data.
  3. Append the data pairs you want to send with form_data.append(key, value) one by one.
  4. Add a callback to xhr.onload event. Check the status and perform further operations. (According to W3’s spec, load event is fired when loaded successfully, got an error, or aborted.)

For more XMLHttpRequest and FormData examples, check out:

Dealing with Same Origin Policy in a Chrome Extension

There is a limitaition of XMLHttpRequest: the Same Origin Policy. In short, you cannot send an Ajax request to different hosts, or differnet protocol (http v.s. https). The sample code above is not going to work because we’re sending a request to git.io from github.com, which violates the Same Origin Policy.

How to fix it? Well, Chrome Extension API provides a simple way to solve it, by requiring a permission to the domain you are going to send Ajax request to. For example, I added these lines to the manifest.json:

"permissions": [
  "http://git.io/"
],

Closing Up

Although I seldom need to generate shortened URL for a GitHub URL, whenever I need, I have to RT*M first, then fire up a terminal, then type the command, then copy it – that’s annoying. So I made this extension, and challenged myself making a Ajax-based Chrome Extension. I made it, and I learned a lot. That was good for me.

I think this meme represents what I have done precisely, so I’d like to close this article with it: