1

I'm sure someone has created a great, terse, and effective Scala function for generating short non-sequential keys suitable for use in web links. I'd like the keys to be hard to guess sequentially... I don't want someone just "browsing" through the links – but, hitting on one randomly is not a big deal.

There are a few related posts (this one and this other one), but they don't really address the problem (and they are in the wrong languages). The idea is to make seemingly random, reasonably short URL keys. Something like Vimeo or Youtube short links would be fine, but not too short (http://watever.com/abc is too easy to guess/browse) and not too long (http://watever.com/de305d54-75b4-431b-adb2-eb6b9e546014 is just too long). A happy medium would be most desirable: http://watever.com/de8f43a3.

They keys will ultimately be stored in a relational database, so I have the option of checking for uniqueness, and retrying until I "get lucky."

Any ideas? Or hopefully a slick little algorithm?

Community
  • 1
  • 1
Zaphod
  • 1,387
  • 2
  • 17
  • 33
  • 2
    Is there any issue with taking one of the suggestions from the linked questions (e.g. hashing) and doing the equivalent in Scala? – Oliver Charlesworth Jun 28 '15 at 20:40
  • scala.util.Random.alphanumeric() should be a start. The rest is applying the format you want. I found that creating a large random string and the cutting out random pieces well into it gives the best randomized results for creating random passwords as good as online password generators. Here's my algo for that: util.Random.alphanumeric drop 47317 take 23 foreach print. The results for three runs are: LrOEyOAI0wyxqmu4pHIHCyJ, aJMef0B0GiJqItbJLHZ7HLq, DiYcIusrKO2pIZ05q9fO1tj. –  Jun 28 '15 at 20:56
  • @Oliver... The only problem with coding something up, is making sure I get it right. For instance, I was fiddling with base64 encoding the unique id from the database, but ultimately decided this didn't generate widely dispersed keys. And, several of the other links generate very long keys. Was hoping someone else has already struggled with this and found a solution. – Zaphod Jun 28 '15 at 22:47
  • @Tris, appreciate the pointers. This is getting closer to the mark, although I'm shooting for something even shorter (I hope). Eventually the keys will have to get larger, as the data set grows, though... – Zaphod Jun 28 '15 at 22:47
  • So instead of take 23 take 8 to start. –  Jun 28 '15 at 22:50

1 Answers1

0

Ended up with the following, which seems to work pretty well. It may generate duplicates, so I have to double check against pre-existing keys – but, I think the odds of getting a duplicate are low so it will be rare (and easy enough to retry):

def shortCode(id: Int): String = {
    val size = (log10(id) + 4).toInt
    Random.alphanumeric.take(Random.nextInt(size) + 1).mkString
}

In this case, I'm using the primary key as the id, so a small key (1) will get a 4-digit serial key. A larger key (1,000,000) will get an 11 digit key. Using a larger key size and an alphanumeric base will make it pretty hard to "browse" the URLs.

Zaphod
  • 1,387
  • 2
  • 17
  • 33