def raw_exercise_contents(exercise_file):
    if templatetags.use_compressed_packages():
        exercises_dir = "../khan-exercises/exercises-packed"
        safe_to_cache = True
    else:
        exercises_dir = "../khan-exercises/exercises"
        safe_to_cache = False

    path = os.path.join(os.path.dirname(__file__),
                        "%s/%s" % (exercises_dir, exercise_file))

    f = None
    contents = ""

    try:
        f = open(path)
        contents = f.read()
    except:
        raise MissingExerciseException(
                "Missing exercise file for exid '%s'" % exercise_file)
    finally:
        if f:
            f.close()

    if not len(contents):
        raise MissingExerciseException(
                "Missing exercise content for exid '%s'" % exercise_file)

    if safe_to_cache:
        return contents
    else:
        # we are displaying an unpacked exercise, either locally or in prod
        # with a querystring override. It's unsafe to cache this.
        return layer_cache.UncachedResult(contents)
def get_profile_from_cookie_key_value(cookie_key, cookie_value):
    """ Communicate with Facebook to get a FB profile associated with
    the specific cookie value.

    Because this talks to Facebook via an HTTP request, this is cached 
    in memcache to avoid constant communication while a FB user is
    browsing the site. If we encounter an error or fail to load
    a Facebook profile, the results are not cached in memcache.

    However, we also cache in request_cache because if we fail to load
    a Facebook profile, we only want to do that once per request.
    """

    fb_auth_dict = facebook.get_user_from_cookie_patched(
        {cookie_key: cookie_value}, App.facebook_app_id,
        App.facebook_app_secret)

    if fb_auth_dict:
        profile = _get_profile_from_fb_token(fb_auth_dict["access_token"])

        if profile:
            return profile

    # Don't cache any missing results in memcache
    return layer_cache.UncachedResult(None)
Beispiel #3
0
class ImageCache(blobstore_handlers.BlobstoreDownloadHandler):
    """ ImageCache is a little utility used to cache images at other URLs
    in our blobstore with our own aggressive caching headers for client-side perf.

    Example: youtube_url = ImageCache.url_for("http://youtube.com/some/thumbnail")
    """

    @staticmethod
    def url_for(source_url, fallback_url = None):
        if fallback_url:
            return "/image_cache/%s?fallback=%s" % (urllib.quote(source_url), urllib.quote(fallback_url))
        else:
            return "/image_cache/%s" % urllib.quote(source_url)

    def get(self, source_url):

        blob_key = self.image_cache_blob_key(source_url)

        fallback_url = self.request.get("fallback")
        if fallback_url and not blob_key:
            blob_key = self.image_cache_blob_key(fallback_url)

        if not blob_key:
            # If we failed to grab something outta the blob store, just try a redirect.
            # ...but log the error, cuz we don't like this.
            logging.error("Failed to load image cache for source url, redirecting: %s" % source_url)
            self.redirect(source_url)
            return

        self.response.cache_control.max_age = CACHE_EXPIRATION
        self.response.cache_control.no_cache = None
        self.response.cache_control.public = True

        self.send_blob(blob_key)

    @layer_cache.cache_with_key_fxn(
            lambda self, source_url: "image_cache:%s" % source_url, 
            layer=layer_cache.Layers.Datastore,
            persist_across_app_versions=True)
    def image_cache_blob_key(self, source_url):

        tries = 0
        max_tries = 3

        while tries < max_tries:

            response = None

            try:
                response = urlfetch.fetch(url = source_url, headers = self.request.headers, deadline=10)
            except Exception, e:
                logging.info("Failed to load image cache source url %s due to %s" % (source_url, e))

            if response and response.status_code == 200:
                return blob_key_for_data(response.headers.get("Content-Type"), response.content)
            else:
                tries += 1

        return layer_cache.UncachedResult(None)
def exercise_sha1(exercise):
    sha1 = None

    try:
        contents = raw_exercise_contents("%s.html" % exercise.name)
        sha1 = hashlib.sha1(contents).hexdigest()
    except MissingExerciseException:
        pass

    if templatetags.use_compressed_packages():
        return sha1
    else:
        return layer_cache.UncachedResult(sha1)
Beispiel #5
0
def get_facebook_nickname(user_id):

    id = user_id.replace(FACEBOOK_ID_PREFIX, "")
    graph = facebook.GraphAPI()

    try:
        profile = graph.get_object(id)
        # Workaround http://code.google.com/p/googleappengine/issues/detail?id=573
        # Bug fixed, utf-8 and nonascii is okay
        return unicodedata.normalize('NFKD', profile["name"]).encode('utf-8', 'ignore')
    except (facebook.GraphAPIError, urlfetch.DownloadError, AttributeError,
            httplib.HTTPException):
        # In the event of an FB error, don't cache the result.
        return layer_cache.UncachedResult(user_id)
Beispiel #6
0
def get_profile_from_cookie_key_value(cookie_key, cookie_value):

    fb_auth_dict = facebook.get_user_from_cookie_patched(
        {cookie_key: cookie_value}, App.facebook_app_id,
        App.facebook_app_secret)

    if fb_auth_dict:
        profile = get_profile_from_fb_token(fb_auth_dict["access_token"])

        if profile:
            return profile

    # Don't cache any missing results
    return layer_cache.UncachedResult(None)
def exercise_sha1(exercise):
    sha1 = None

    try:
        file_name = exercise.file_name
        # TODO(eater): remove this after adding the filename to all existing
        # exercise entities
        if not file_name or file_name == "":
            file_name = exercise.name + ".html"
        contents = raw_exercise_contents(file_name)
        sha1 = hashlib.sha1(contents).hexdigest()
    except MissingExerciseException:
        pass

    if templatetags.use_compressed_packages():
        return sha1
    else:
        return layer_cache.UncachedResult(sha1)