Search code examples
pythondjangoamazon-s3botodjango-storage

Inconsistent SignatureDoesNotMatch Amazon S3 with django-pipeline, s3boto and storages


I have 2 files compiled by django-pipeline along with s3boto: master.css and master.js. They are set to "Public" in my buckets. However, when I access them, sometimes master.css is served, sometimes it errs with SignatureDoesNotMatch. The same with master.js. This doesn't happen on Chrome. What could I be missing?

EDIT: It now happens on Chrome too.


Solution

  • Happened to me too... Took a few hours to find, but I figured it out eventually. Turns out that if the right signature is :

    ssCNsAOxLf5vA80ldAI3M0CU2%2Bw=

    Then AWS will NOT accept:

    ssCNsAOxLf5vA80ldAI3M0CU2+w=

    Where the only difference is the translation of %2B to '+'.

    S3BotoStorage actually yields it correctly but the encoding happens on CachedFilesMixin in the final line of the url method (return unquote(final_url)). To fix it, I derived a new CachedFilesMixin to undo the "damage" (I should mention that I don't know why this unquote exists in the first place, so undoing it might cause other problems)

    class MyCachedFilesMixin(CachedFilesMixin):
    def url(self, *a, **kw):
        s = super(MyCachedFilesMixin, self).url(*a, **kw)
        if isinstance(s, unicode):
            s = s.encode('utf-8', 'ignore')
        scheme, netloc, path, qs, anchor = urlparse.urlsplit(s)
        path = urllib.quote(path, '/%')
        qs = urllib.quote_plus(qs, ':&=')
        return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))
    

    Where I used the code I found here.

    Hope this helps...