Showing posts with label api. Show all posts
Showing posts with label api. Show all posts

Monday, February 8, 2016

Converting unix timestamps in Ruby

Unix timestamps are common to see in other languages, and also common to see in API responses. Converting a unix timestamp to DateTime in Ruby is dead simple:

unix_timestamp = Time.now.to_i
# => 1453667949
DateTime.strptime(unix_timestamp.to_s, "%s").to_s
# => "2016-01-24T20:39:09+00:00" 

Let’s say your unix timestamp includes milliseconds:

unix_timestamp = (Time.now.to_f * 1000).to_i
# => 1453667949151
DateTime.strptime(unix_timestamp.to_s, "%Q").to_s
# => "2016-01-24T20:39:09+00:00" 

DateTime.strptime will allow you convert just about any formatted time string, see the docs for examples.

Notice how both DateTime strings are the same? DateTime converted to string drops any millisecond data, but keep it as a DateTime object and you can run strftime and display it in any format you like:

DateTime.strptime(unix_timestamp.to_s, "%Q").strftime('%D %T:%L')
# => "01/24/16 20:39:09:151"

Monday, October 12, 2015

URL Encoding and Silly Safari

I have a web app that also acts as an API for an iOS, and I ran into a tricky situation. One of my models on the web app takes a URL as input, and it validates it using the validates_url gem. However, some URLs when visited from within the iOS app would give a Webkit error and show as invalid.

After some head scratching, it turned out that those URLs had encoding issues that were handled fine by all modern browsers except Safari, the default browser on iOS. For example, something with curly brackets like "http://www.example.com?ID={12345}" would work in most browser but not in Safari/iOS.

To get around this, in addition to using validates_url, I had to escape each URL during validation using URI.escape(url). The above URL would then become "http://www.example.com?ID={12345}". (Notice that the left curly bracket changed to %7B, the right turned to %7D - check out this HTML URL Encoding Reference for details)

But wait, there’s more!

It turns out that on subsequent saves, the URL would be escaped again, and it wouldn’t recognize the %7B and %7D as encoding, it would just see the % sign as an invalid character needing escape. So, on the second save, the same URL would be transformed again into "http://www.example.com?ID=%7B12345%7D". Notice the “25” inserted in there twice?

The fix ended up being something that reads very strange and seems unnecessary, but that works perfectly:

URI.escape(URI.unescape(url))

So, if a URL is already escaped, it unescapes it first, then re-escapes it. If the URL is not escaped, then unescaping it does nothing, then it gets escaped as it should.

If there’s a better way to do this, I haven’t found it, and am open to suggestions.

Thursday, July 16, 2015

Quick and easy HTTP headers with HTTParty

UPDATE: I changed the gem. It now follows redirects and maintains the HEAD request across all redirects.

I have a method that checks URLs submitted by the user to ensure they are valid. I don’t want to scrape the page to make sure any specific text is on there because the URLs can go almost anywhere, so I basically only care if the URL returns an HTTP 200 status.

I’m using the excellent HTTParty Ruby gem to make my external requests, and it offers a handy .head method that only returns the website headers for the request:

HTTPart.head(external_url)

However, I found out that if the requested site redirects, then subsequent requests get changed to GET, which isn’t ideal since the GET request will download the entire page’s content rather than just the headers, and is understandably slower.

Thankfully, there are a couple options that can be passed to the .head method which takes care of this:



HTTParty.head(external_url_with_redirects,
              maintain_method_across_redirects: true,
              follow_redirects: true)

Now, I get just the headers, and since all I care about is whether it was a successful request, I’m able to call .success? in my method and use the return value.

There are a few external HTTP gems out there - Net:HTTP (of which HTTParty is a wrapper), RestClient, etc - but HTTParty is my favorite so far, and easiest to work with. Check it out if you haven’t already.