Safari (13.0.2) doesn't seem to like sri=True
cunningjames opened this issue · 7 comments
I'm not sure whether this is properly an error in flask-moment. Apologies if this is the wrong place.
Using an extremely simple app, I can't seem to get dates to display properly in Safari (13.0.2) with flask-moment (0.9.0) unless I set sri to False in include_moment()
. Otherwise, moment.js fails to load and no dates display. In the JavaScript console I see errors related to Access-Control-Allow-Origin, but setting that header manually doesn't have any impact.
The errors I see:
[Error] Cross-origin redirection to http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js denied by Cross-Origin Resource Sharing policy: Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin.
[Error] Failed to load resource: Cross-origin redirection to http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js denied by Cross-Origin Resource Sharing policy: Origin http://localhost:5000 is not allowed by Access-Control-Allow-Origin. (moment-with-locales.min.js, line 0)
[Error] Cross-origin script load denied by Cross-Origin Resource Sharing policy.
[Error] ReferenceError: Can't find variable: moment
Global Code (localhost:15)
[Error] Cross-origin script load denied by Cross-Origin Resource Sharing policy.
[Error] ReferenceError: Can't find variable: moment
Global Code (localhost:49)
The code I used:
main.py:
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask import Flask, render_template, make_response
from datetime import datetime
app = Flask(__name__)
bootstrap = Bootstrap(app)
moment = Moment(app)
@app.route("/")
def index():
return render_template('index.html', current_time=datetime.utcnow())
if __name__ == '__main__':
app.run()
base.html:
{% extends "bootstrap/base.html" %}
{% block head %}
{{ super() }}
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
{% endblock %}
{% block content %}
{% block page_content %}
{% endblock %}
{% endblock %}
index.html:
{% extends 'base.html' %}
{% block page_content %}
Current time: {{ moment(current_time).format('LLL') }}.
{% endblock %}
Safari 12 works fine, so at this point this likely applies only to those who upgraded to Catalina.
Hi, i am running into the issue as exactly as @cunningjames described above!
I use macOS Mojave 10.14.5 and my Safari version is 12.1.1 (14607.2.6.1.1), i am using the same flask code same as @cunningjames does.
it could work get moment-with-locales.min.js
successfully in Chrome but failed in Safari.
[Error] Cross-origin redirection to https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js denied by Cross-Origin Resource Sharing policy: Origin http://127.0.0.1:5000 is not allowed by Access-Control-Allow-Origin.
[Error] Failed to load http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js resource: Cross-origin redirection to https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js denied by Cross-Origin Resource Sharing policy: Origin http://127.0.0.1:5000 is not allowed by Access-Control-Allow-Origin. (moment-with-locales.min.js, line 0)
[Error] Failed to load resource: the server responded with a status of 404 (NOT FOUND) (bootstrap.min.css.map, line 0)
[Error] Cross-origin script load denied by Cross-Origin Resource Sharing policy.
[Error] ReferenceError: Can't find variable: moment
@cunningjames @miguelgrinberg
Good news, finally i've found out the root cause, follow this stackoverflow post to disable "Cross-origin restrictions" would help.
I think I know what the problem is. When you change sri=None, the script tag defaults to have both integrity and crossorigin attributes.
The default_moment_sri SHA in flask_moment.py is also out of sync with cloudflare. When I take out crossorigin="anonymous"
, I get the following error:
Cannot load script http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment-with-locales.min.js. Failed integrity metadata check. Content length: 356021, Expected content length: -1, Expected metadata: sha384-WxkyfzCCre+H1hXpoMH2JOqSotIuNoiH5KQ4zCQxIxOSHo49PeKFlgftAkREuLTR
If I go to cloudflare's page, the script tag it gave is:
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js" integrity="sha512-QkuqGuFAgaPp3RTyTyJZnB1IuwbVAqpVGN58UJ93pwZel7NZ8wJOGmpO1zPxZGehX+0pc9/dpNG9QdL52aI4Cg==" crossorigin="anonymous"></script>
Now, if I take out integrity=
, and just have crossorigin="anonymous"
, I still get the same CORS redirect error. Interestingly, Chrome doesn't report either of these problems. So I don't know whether Safari is too strict, or if there is a bug. One of the things to consider is that when we're testing with localhost, it's HTTP, and because the generated script tag doesn't specify a protocol, so it picks up http. But when we hit cloudflare, it is redirected to HTTPS with a 302. (I suspect this redirect is a red herring, because it seems to fail on the initial http request.)
This might not address what is written in the title but it might help some other people.
I was able to get around it by using my own saved moment-with-locales.min.js and adding the a new js script (the accompying js script when using moment_include())
such as below
`
<script src="{{ url_for('static', filename='js/moment/moment-with-locales.min.js') }}"></script><script>
moment.locale("en");
function flask_moment_render(elem) {
timestamp = moment($(elem).data('timestamp'));
func = $(elem).data('function');
format = $(elem).data('format');
timestamp2 = $(elem).data('timestamp2');
no_suffix = $(elem).data('nosuffix');
args = [];
if (format)
args.push(format);
if (timestamp2)
args.push(moment(timestamp2));
if (no_suffix)
args.push(no_suffix);
$(elem).text(timestamp[func].apply(timestamp, args));
$(elem).removeClass('flask-moment').show();
}
function flask_moment_render_all() {
$('.flask-moment').each(function() {
flask_moment_render(this);
if ($(this).data('refresh')) {
(function(elem, interval) { setInterval(function() { flask_moment_render(elem) }, interval); })(this, $(this).data('refresh'));
}
})
}
$(document).ready(function() {
flask_moment_render_all();
});
</script>
`
This seems to work for safari on mac or iphone
using MacOS Catalina 10.15.6
safari Version 13.1.2 (15609.3.5.1.3)
iphone 7 plus
and it also work for firefox and chrome
Also
moment.include_moment(sri=False)
works, however, im not sure if you want to turn it off
This might not address what is written in the title but it might help some other people.
I was able to get around it by using my own saved moment-with-locales.min.js and adding the a new js script (the accompying js script when using moment_include())
such as below`
<script src="{{ url_for('static', filename='js/moment/moment-with-locales.min.js') }}"></script><script> moment.locale("en"); function flask_moment_render(elem) { timestamp = moment($(elem).data('timestamp')); func = $(elem).data('function'); format = $(elem).data('format'); timestamp2 = $(elem).data('timestamp2'); no_suffix = $(elem).data('nosuffix'); args = []; if (format) args.push(format); if (timestamp2) args.push(moment(timestamp2)); if (no_suffix) args.push(no_suffix); $(elem).text(timestamp[func].apply(timestamp, args)); $(elem).removeClass('flask-moment').show(); } function flask_moment_render_all() { $('.flask-moment').each(function() { flask_moment_render(this); if ($(this).data('refresh')) { (function(elem, interval) { setInterval(function() { flask_moment_render(elem) }, interval); })(this, $(this).data('refresh')); } }) } $(document).ready(function() { flask_moment_render_all(); }); </script>
`
This seems to work for safari on mac or iphone
using MacOS Catalina 10.15.6
safari Version 13.1.2 (15609.3.5.1.3)
iphone 7 plusand it also work for firefox and chrome
Also
moment.include_moment(sri=False)
works, however, im not sure if you want to turn it off
This works for me on macOS 10.15.7 with Safari 14.0 and on iPad with iPadOS 14.0.1
Thank you
Safari 14 does not appear to have an issue, so I'm closing.