1

Question: can I be certain that Base64 encoded URLs won't output '/' characters?

Background: Firebase uses a key/value structure, and its key names, per the docs,

"can include any unicode characters except for . $ # [ ] / and ASCII control characters 0-31 and 127"

I'd like to use URLs as a key for one of my collection, but obviously the '/' and '.' make raw strings a no-go.

My plan (to which I'm not married) is to convert the URLs into Base64, using either the browser's functions (atob() and btoa()) or a dedicated function/NPM module (as discussed here).

However, Base64 outputs can include '/', which breaks Firebase rules.

Would the characters a URL might contain ever produce a '/'?

If so, is there any reason I shouldn't just add a simple String.replace() to the front/back of the Base64 encoding function?

Community
  • 1
  • 1
Brandon
  • 7,736
  • 9
  • 47
  • 72

3 Answers3

0

Taking suggestions in OP comments (thanks ceejayoz, Derek), it looks something like this will work:

let rawUrl = "http://stackoverflow.com/questions/38679286/how-can-i-convert-urls-to-base64-without-outputting-characters?noredirect=1#comment64738129_38679286";

let key = btoa(encodeURIComponent(url)); 
let decodedUrl = decodeURIComponent(atob(key));

rawUrl == decodedUrl // True
Brandon
  • 7,736
  • 9
  • 47
  • 72
  • This may throw `URIError: malformed URI sequence` for some characters. And I think the output can still have `/`. – Oriol Jul 31 '16 at 00:07
0

You can always just replace those characters after base64 encoding them, and then replace again when decoding.

const fireBase64 = {
  encode: (str) => btoa(str).replace(/\//g, '_'),
  decode: (b64) => atob(b64.replace(/_/g, '/'))
}
idbehold
  • 16,833
  • 5
  • 47
  • 74
0

The possible characters in a base64 string are

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

If you don't want /, just replace it with another character not present in the list above, e.g. _.

var string = "ü";
var encoded = btoa(string).replace(/\//g, '_'); 
var decoded = atob(encoded.replace(/_/g, '/'));

console.log(btoa(string).indexOf('/') > -1); // true :(
console.log(encoded.indexOf('/') > -1); // false :)
console.log(string == decoded); // true :)
Oriol
  • 274,082
  • 63
  • 437
  • 513