1

Is there a function in Google App Engine to test if a string is valid 'string key' prior to calling memcache.get(key) without using db.get() or db.get_by_key_name() first?

In my case the key is being passed from the user's get request: obj = memcache.get(self.request.get("obj"))

Somehow I'd like to know if that string is a valid key string without calling the db first, which would defeat the purpose of using memcache.

user1961
  • 1,270
  • 2
  • 17
  • 27
  • What do you mean by a "valid" key? Do you mean "in the right format for a key string", or do you mean "refers to an actual object in the datastore"? – Daniel Roseman May 31 '13 at 18:12
  • I mean the right format for a key string to avoid the error `raise datastore_errors.BadKeyError('Invalid string key %s.' % encoded)`. Thanks for the help. – user1961 May 31 '13 at 18:19

3 Answers3

1

That is probably the most efficient (and practical) way to determine if the key string is valid. The code is obviously performing that test for you before it attempts to retrieve the entity from memcache/datastore. Even better, Google will update that code if necessary.

try:
    obj = memcache.get(self.request.get("obj"))
except BadKeyError:
    # give a friendly error message here

Also, consider switching to ndb. Performing a get() on a key automatically uses two levels of cache, local and memcache. You don't need to write separate code for memcache.

Brent Washburne
  • 12,904
  • 4
  • 60
  • 82
1

A db module key sent to a client should pass through str(the_key) which gives you an URL safe encoded key. Your templating environment etc.. will do this for you just by rendering the key into a template.

On passing the key back from a client, you should recreate the key with key = db.Key(encoded=self.request.get("obj"))

At this point it could fail with something like BadKeyError: Invalid string key "thebadkeystring"=.

If not you have a valid key

obj = memcache.get(self.request.get("obj")) won't actually raise BadKeyError because at that point you are just working with a string, and you just get None returned or a value.

So at that point all you know is you have a key missing.

However you need to use the memcache.get(self.request.get("obj")) to get the object from memcache, as a db.Key instance is not a valid memcache key.

So you will be constructing a key to validate the key string at this point. Of course if the memcache get fails then you can use the just created key to fetch the object with db.get(key)

Tim Hoffman
  • 12,976
  • 1
  • 17
  • 29
  • Thanks for the help - I'm worried about me not being able to control the inbound string, i.e. a user could manipulate it. I think the re-creation of key will work for these purposes. – user1961 Jun 01 '13 at 01:32
  • Key manipulation entirely possible. An authorization framework that validates if a particular principal (user, group) has permission to access the entity may be one strategy for addressing this risk. – Tim Hoffman Jun 01 '13 at 02:43
0

Any object is a valid key, provided that the object can be serialized using pickle. If pickle.dumps(key) succeeds, then you shouldn't get a BadKeyError.

Sniggerfardimungus
  • 11,583
  • 10
  • 52
  • 97