Django/nginx на сервере не отдает sw.js
И так, есть странная проблема... Есть сайт Django на сервере, и решил я прикрутить уведомления. И, как известно, нужен сервис-воркер, который у меня есть и отлично работает локально, но когда я загрузил изменения на сервер, то я обнаружил, что сервер его не видит(в консоле браузера вижу ошибку "Uncaught (in promise) TypeError: Failed to register a ServiceWorker for scope ('https://my-domen/') with script ('https://my-domen/sw.js'): A bad HTTP response code (404) was received when fetching the script.", а так же "A bad HTTP response code (404) was received when fetching the script." Т.е. понятно, что registerSw.js ссылается на sw.js, но Django/nginx не видит его (вся статика подтягивается отлично(В дебаг режиме и нет), но только не sw.js). Вот код registerSw.js:
const registerSw = async () => {
if ('serviceWorker' in navigator) {
const reg = await navigator.serviceWorker.register('/sw.js');
initialiseState(reg)
} else {
showNotAllowed("You can't send push notifications ☹️?")
}
};
const initialiseState = (reg) => {
if (!reg.showNotification) {
showNotAllowed('Showing notifications isn\'t supported ☹️?');
return
}
if (Notification.permission === 'denied') {
showNotAllowed('You prevented us from showing notifications ☹️?');
return
}
if (!'PushManager' in window) {
showNotAllowed("Push isn't allowed in your browser ?");
return
}
subscribe(reg);
}
const showNotAllowed = (message) => {
const button = document.querySelector('form>button');
button.innerHTML = `${message}`;
button.setAttribute('disabled', 'true');
};
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
const outputData = outputArray.map((output, index) => rawData.charCodeAt(index));
return outputData;
}
const subscribe = async (reg) => {
const subscription = await reg.pushManager.getSubscription();
if (subscription) {
sendSubData(subscription);
return;
}
const vapidMeta = document.querySelector('meta[name="vapid-key"]');
const key = vapidMeta.content;
const options = {
userVisibleOnly: true,
// if key exists, create applicationServerKey property
...(key && {applicationServerKey: urlB64ToUint8Array(key)})
};
const sub = await reg.pushManager.subscribe(options);
sendSubData(sub)
};
const sendSubData = async (subscription) => {
const browser = navigator.userAgent.match(/(firefox|msie|chrome|safari|trident)/ig)[0].toLowerCase();
const data = {
status_type: 'subscribe',
subscription: subscription.toJSON(),
browser: browser,
};
const res = await fetch('/webpush/save_information', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'content-type': 'application/json'
},
credentials: "include"
});
handleResponse(res);
};
const handleResponse = (res) => {
console.log(res.status);
};
registerSw();
urls.py:
path('home/', home, name='home'),
path('sw.js', serve, {'path': 'my_project/js/sw.js'}),
sw.js находится в статике в папке js. Там же, где и registerSw.js Логи джанго с сервера: Django.log:
Not Found: /sw.js
Логи nginx:
2023/11/20 17:04:08 [error] 405653#405653: *2251 connect() failed (111: Unknown error) while connecting to upstream, client: (тут какойто ip, решил не показывать), server: my-site.ru, request: "GET /home/ HTTP/1.1", upstream: "http://127.0.0.1:8001/home/", host: "my-domen.ru"
2023/11/20 21:33:52 [error] 474557#474557: *11 connect() failed (111: Unknown error) while connecting to upstream, client: (тут какойто ip, решил не показывать), server: my-domen.ru, request: "GET /home/ HTTP/1.1", upstream: "http://127.0.0.1:8001/home/", host: "my-domen.ru"
Не уверен, что эти ошибки возникают, из-за sw.js. Проверил 8001 порт и понял, что он просто занят gunicornom, который и запускает сервер. (Права на św.js я проверял и там все отлично. collectstatic делал, кеш чистил. Единственное различие между локальными файлами и теми, которые на сервере в настройках: Локаль:
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
Сервер:
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
Помогите, пожалуйста, я не понимаю как мне решить эту проблему((9(
Ответы (1 шт):
Отвечаю на свой же вопрос. Нормальным способом решить это не удалось. (даже если подключать sw в html странице, то хром его видит, словно он начал раздаваться из статики, но nginx/django все равно на это, и они так же не могут найти его). Решение нашел только в том, чтобы явно указать nginx'y полный путь до sw.js. (Как по мне немного костыль, но работает ведь)) Если кому-то понадобится подробная инструкция, то держите путь решения:
Открыть конфиг nginx ("sudo nano /etc/nginx/sites-available/default" ну или как у вас там он называется)
Прописать в конфигурации сервера явный путь к вашему sw.js:
location /sw.js { alias /home/hostgeek/myapps/path/to/your/static/js/sw.js; }Перезапускайте nginx и радуетесь ("sudo service nginx restart")