Ejemplo n.º 1
0
def oembed(request):
    """
    A view that adheres to `OEmbed Spec <http://oembed.com>`_ of what a provider
    endpoint should do. Any :class:`monocle.providers.Provider` that is configured
    to be exposed can be provided via this view.

    Both ``maxwidth`` and ``maxheight`` are honored, but no other URL parameter is.
    This implies that all responses are delivered as JSON (i.e. ``format=json``).
    XML is not supported. If a request specifies ``format=xml`` or some other unknown
    format other than JSON, a 501 response is returned.

    If no provider is found, or a provider is not exposed, a 404 is returned.
    If no resource can be retrieved from the found provider, or it is invalid, a 404
    is also returned. Else the resource is returned as JSON.
    """
    url = request.GET.get('url')
    format = request.GET.get('format', 'json').lower()

    if not url:
        return HttpResponseBadRequest('Paramater URL is missing')

    # TODO: Support xml
    if format != 'json':
        return HttpResponseNotImplemented('OEmbed format %s not implemented' % format)

    # Get optional and trim None
    params = {
        'maxwidth': request.GET.get('maxwidth'),
        'maxheight': request.GET.get('maxheight')
    }

    # Filter nones and non-numbers
    for k, v in params.items():
        if not v:
            del params[k]
        else:
            # Coerce
            try:
                params[k] = int(v)
            except ValueError:
                del params[k]

    provider = registry.match(url)

    # 404 on resource not found on non-exposed endpoint
    if not provider or not provider.expose:
        return HttpResponseNotFound('OEmbed for this URL not available')

    resource = provider.get_resource(url, **params)

    if resource.is_valid:
        callback = request.GET.get('callback')
        if callback:
            return HttpResponse('%s(%s);' % (callback, resource.json), mimetype='application/json')
        return HttpResponse(resource.json, mimetype='application/json')
    else:
        return HttpResponseNotFound('OEmbed resource is invalid or unavailable')
Ejemplo n.º 2
0
    def enrich(self, content, maxwidth=None, maxheight=None):
        """
        Returns an enriched version of content that replaces all URLs that
        have a provider with valid resource data. By default, all providers
        are considered for possible replacement. However, if the consumer's
        ``skip_internal`` attribute is True and internal provider responses
        are not configured to be cached, no matched URL that is an internal
        provider will be rendered. This is useful if any prefetching is to
        occur where rendering internal providers may be wasted effort.

        :param string content: Content to enrich
        :param integer maxwidth: Maximum width of resource
        :param integer maxheight: Maximum height of resource
        :returns: A version of specific content with matched URLs replaced with
                  rendered resources
        """
        for url in self.url_regex.findall(content):
            provider = registry.match(url)

            if not provider:
                logger.debug('No provider match for %s' % url)
                continue

            # Bypass internal providers if they aren't cached
            if (self.skip_internal and isinstance(provider, InternalProvider) and
                    not settings.CACHE_INTERNAL_PROVIDERS):
                logger.debug('Skipping uncached internal provider')
                continue

            # This is generally a safeguard against bad provider implementations
            try:
                resource = provider.get_resource(url, maxwidth=maxwidth, maxheight=maxheight)
            except:
                logger.exception('Failed to get resource from provider %s' % provider)
            else:
                if not resource.is_valid:
                    logger.warning('Provider %s returned a bad resource' % provider)

                logger.debug('Embedding %s for url %s' % (resource, url))
                content = content.replace(url, resource.render())
        return content