30 апреля — время отключить Node.js 14. Тимур Шемсединов выпустил отличный чеклист по миграции https://github.com/HowProgrammingWorks/Drop-Nodejs14 .
Добавлю про lockfileVersion: 2. На него имеет смысл переходить, если у вас CI крутится на node 14 и вы хотите переехать плавно. Если везде подняли npm до 8 и выше, то можно сразу на lockfileVersion: 3.
Добавлю про lockfileVersion: 2. На него имеет смысл переходить, если у вас CI крутится на node 14 и вы хотите переехать плавно. Если везде подняли npm до 8 и выше, то можно сразу на lockfileVersion: 3.
GitHub
GitHub - tshemsedinov/Drop-Nodejs14: Drop Node.js 14 support
Drop Node.js 14 support. Contribute to tshemsedinov/Drop-Nodejs14 development by creating an account on GitHub.
🔥13❤5👍3
Что не так с iframe
Довольно часто у бизнеса возникает желание запихнуть продукт в iframe и вставить так в чужой ресурс. Всё нормально до тех пор, пока не возникает вопрос аутентификации пользователя. Обычно мы сохраняем идентификатор сессии в куку, и вот тут проблема, что куки в данном случае становятся third-party, т.е. принадлежат не тому сайту, где установлен iframe, а третьей стороне.
Chrome и FF ещё можно обойти, если переставить аттрибут
ITP блокирует все third-party cookies по умолчанию. Обойти его можно двумя способами:
- Заставить пользователя в настройках снять галочку
- Воспользоваться Storage Access API, с помощью которого мы явно запросим у пользователя разрешения прочитать куки с третьей стороны
Storage Access API имеет достаточно жёсткие ограничения и задействует различную неоднозначную эвристику, пытаясь догадаться, действительно ли пользователь хотел разрешить доступ. А пользователь может и не захотеть. Но, самое важное, это API закрыто в Chrome за флагом. Почему же? Скорее всего, потому, что ломает рекламный бизнес Гугл :_)
Что же делать? Вы не должны встраивать ваши сервисы в iframe as is. Вам придётся провернуть какой нибудь трюк. Например, открыть встраиваемый сервис во втором, «честном» окне, пройти аутентификацию, получить временный токен и перекинуть этот токен через postMessage в окно со страницей со встраиваемым iframe. И вот там уже перезагрузить iframe передав ему токен как get-параметр. И никаких кук.
Это не значит, что вы должны отказывать продактам в их странных желаниях. Желания продиктованы бизнесом. Но продакт не должен просить iframe. Он должен просить возможности встраивания, а вот как оно будет сделано — зависит от того, что мы сможем сделать, как разработчики.
Довольно часто у бизнеса возникает желание запихнуть продукт в iframe и вставить так в чужой ресурс. Всё нормально до тех пор, пока не возникает вопрос аутентификации пользователя. Обычно мы сохраняем идентификатор сессии в куку, и вот тут проблема, что куки в данном случае становятся third-party, т.е. принадлежат не тому сайту, где установлен iframe, а третьей стороне.
Chrome и FF ещё можно обойти, если переставить аттрибут
SameSite в none (напомнию, что по дефолту там Lax, который так же не даст отправить куку в iframe). Конечно, вам придётся повоевать с безопасниками и защитить ваше решение понизить безопасность у сессионной куки. А вот в Safari уже несколько лет как включен Intelligent Tracking Prevention (ITP) который режет куки в любом случае. Кстати, режим инкогнито в Chrome так же режет все third-party куки.ITP блокирует все third-party cookies по умолчанию. Обойти его можно двумя способами:
- Заставить пользователя в настройках снять галочку
Prevent cross-site tracking, что повлияет на все сайты- Воспользоваться Storage Access API, с помощью которого мы явно запросим у пользователя разрешения прочитать куки с третьей стороны
Storage Access API имеет достаточно жёсткие ограничения и задействует различную неоднозначную эвристику, пытаясь догадаться, действительно ли пользователь хотел разрешить доступ. А пользователь может и не захотеть. Но, самое важное, это API закрыто в Chrome за флагом. Почему же? Скорее всего, потому, что ломает рекламный бизнес Гугл :_)
Что же делать? Вы не должны встраивать ваши сервисы в iframe as is. Вам придётся провернуть какой нибудь трюк. Например, открыть встраиваемый сервис во втором, «честном» окне, пройти аутентификацию, получить временный токен и перекинуть этот токен через postMessage в окно со страницей со встраиваемым iframe. И вот там уже перезагрузить iframe передав ему токен как get-параметр. И никаких кук.
Это не значит, что вы должны отказывать продактам в их странных желаниях. Желания продиктованы бизнесом. Но продакт не должен просить iframe. Он должен просить возможности встраивания, а вот как оно будет сделано — зависит от того, что мы сможем сделать, как разработчики.
WebKit
Intelligent Tracking Prevention
Note: Read about improvements to this technology in recent blog posts about Intelligent Tracking Prevention, and the Storage Access API.
👍43❤16
Не обновляйтесь на node.js 16
В этом нет большого смысла. Node.js 14 закончила свой срок жизни и лучшим выбором сейчас будет переехать сразу на v18. И v16 и v18 являются поддерживаемыми LTS-версиями, но жизнь v16 закончится гораздо раньше, чем могла бы быть в обычном релизном цикле — уже этой осенью, а именно 11 сентября. Связано это с тем, что 11 сентября прекратится поддержка OpenSSL 1.1.1, больше не будут выходить никакие патчи для него (да, там был вариант взять OpenSSL 1.1.1 из CentOS и протянуть ещё годик, но не сложилось).
Так получилось, что Node.js 16 не успела получить OpenSSL 3. Да да, тот самый из-за которого вам приходится писать
К счастью, все важные библиотеки уже успели обновить свой код и если у вам нет престарелых зависимостей, то скорее всего ключ
В этом нет большого смысла. Node.js 14 закончила свой срок жизни и лучшим выбором сейчас будет переехать сразу на v18. И v16 и v18 являются поддерживаемыми LTS-версиями, но жизнь v16 закончится гораздо раньше, чем могла бы быть в обычном релизном цикле — уже этой осенью, а именно 11 сентября. Связано это с тем, что 11 сентября прекратится поддержка OpenSSL 1.1.1, больше не будут выходить никакие патчи для него (да, там был вариант взять OpenSSL 1.1.1 из CentOS и протянуть ещё годик, но не сложилось).
Так получилось, что Node.js 16 не успела получить OpenSSL 3. Да да, тот самый из-за которого вам приходится писать
--openssl-legacy-provider чтобы обойти ошибку ERR_OSSL_EVP_UNSUPPORTED на Node.js 17+. Возникает она от того, что в коде библиотек задействованы устаревшие криптографические алгоритмы и, как шутят авторы, ключ `legacy` открывает вам двери в дом престарелых алгоритмов.К счастью, все важные библиотеки уже успели обновить свой код и если у вам нет престарелых зависимостей, то скорее всего ключ
--openssl-legacy-provider вам будет не нужен. Так что смело обновляемся на v18, там уже v20 на подходе.👍35❤6
Forwarded from Dilame Bowzee
Изучаю эту тему, и выяснил, что NodeJS с версии v16.15.0 помимо метода
А начиная с NodeJS 18.0.0 метод
🪄💫 Пруф
Спасибо за наводку, очень интересно:)
setNoDelay внедрила во многие сетевые конструкторы опцию noDelay (а также keepAlive and keepAliveInitialDelay). А так как почти все агенты прокидывают входящие опции ниже по течению, теперь есть возможность отключить delay из юзерленда даже в библиотеках, которые об этой опции не знают, и не нужен доступ к самому объекту сокета.А начиная с NodeJS 18.0.0 метод
http.createServer по умолчанию использует noDelay: true !!!🪄💫 Пруф
Спасибо за наводку, очень интересно:)
👍10❤2
С remote - SSH начинаю день с
UPD
В комментах подсказали, что причина может быть в nodemon, и решается явным пробросом сигналов
ps -aux | grep "node --inspect" | grep -v grep | awk '{print $2}' | xargs kill -9UPD
В комментах подсказали, что причина может быть в nodemon, и решается явным пробросом сигналов
nodemon --signal SIGHUP💯6🤨2🌚1🦄1
А я говорил (яжеговорил), что лямбды это дорого. Лямбды это способ гибко быстро масштабироваться при очень редких пиковых нагрузках, но держать на них большой проект — решение очень спорное.
А монолит.. Ну тут как с чиплетами, раз нужна скорость, значит придётся собирать всё вместе, поближе.
https://www.primevideotech.com/video-streaming/scaling-up-the-prime-video-audio-video-monitoring-service-and-reducing-costs-by-90
А монолит.. Ну тут как с чиплетами, раз нужна скорость, значит придётся собирать всё вместе, поближе.
https://www.primevideotech.com/video-streaming/scaling-up-the-prime-video-audio-video-monitoring-service-and-reducing-costs-by-90
About Amazon
Entertainment
We create and provide access to world-class entertainment through Amazon Originals, Prime Video, Audible, Amazon Games, Twitch, Amazon Music, Prime Gaming, and more. Amazon’s digital entertainment products enable customers to access the latest apps and games…
👍9❤1
melikhov.dev
А я говорил (яжеговорил), что лямбды это дорого. Лямбды это способ гибко быстро масштабироваться при очень редких пиковых нагрузках, но держать на них большой проект — решение очень спорное. А монолит.. Ну тут как с чиплетами, раз нужна скорость, значит придётся…
Продолжение от DHH https://world.hey.com/dhh/even-amazon-can-t-make-sense-of-serverless-or-microservices-59625580
Hey
Even Amazon can't make sense of serverless or microservices
The Prime Video team at Amazon has published a rather remarkable case study on their decision to dump their serverless, microservices architecture and replace it with a monolith instead. This move saved them a staggering 90%(!!) on operating costs, and simplified…
🗿10
В свежем выпуске подкаста напомнил соведущим, что
Как мы много узнали про ошибки и исключения в тот момент, когда TS 4.4 переключил
На самом деле V8 даёт несколько довольно интересных механизмов по работе с трейсами. Например, можно увеличить глубину стектрейса через
Ещё из интересного — так как остальные движки представляют стек просто как строку, то V8 решил не ломать это поведение, но даёт нам доступ к методу
Подробнее в блоге V8
error.stack это не стандарт. Тут же Лёша отыскал пропозал по Error.prototype.stack. TS вот согласен, поля stack в объекте Error может и не быть:
interface Error {
name: string;
message: string;
stack?: string;
}
Как мы много узнали про ошибки и исключения в тот момент, когда TS 4.4 переключил
catch(e) из any в unknown :) Пришлось разбираться и вспоминать, что в исключении может лететь не ошибка, а что угодно, например строка ( throw 'Oops' ). Набор полей там неизвестен, обработчики исключений необходимо писать, чтобы они сами не падали в исключения (а я встречал и такое).На самом деле V8 даёт несколько довольно интересных механизмов по работе с трейсами. Например, можно увеличить глубину стектрейса через
Error.stackTraceLimit или через флаг v8 --stack-trace-limit. Ещё из интересного — так как остальные движки представляют стек просто как строку, то V8 решил не ломать это поведение, но даёт нам доступ к методу
Error.prepareStackTrace(error, structuredStackTrace) который вызывается в момент обращения к свойству stack. И вот тут уже внутри метода можно работать с нормальным объектом structuredStackTrace и переписать весь вывод так, как нам нравится. Но опять же, напомню, что только в V8.Подробнее в блоге V8
👍22
Многопоточность (мультитрединг) в JS
Как мы знаем, JS это синхронный однопоточный язык. Многопоточность в нём невозможна бай дизайн. Ну нет никакой возможности создать потоки в том же контексте, пошарить память, забыть про синхронизацию, устроить гонку, всё сломать. Пишешь свой код с асинхронным вызовами и радуешь тому, что всё небыстро, но просто.
Да, у нас есть возможность порождать веб-воркеры и воркер-треды (одно в браузере, второе в node.js, соответственно). Можно соорудить воркер-пул и отбрасывать туда тяжёлые задачи, асинхронно забирая ответы. Многопоточность ли это? Скорее многопроцессность. Мы порождаем независимый процесс с полностью независимым контекстом (и независимым event loop) и общаемся с ним через сообщения с сериализованными данными или transferable objects (ArrayBuffer и ImageBitmap, например). Т.е. можно перебрасывать некоторый набор специальных объектов между контекстами (не шарить, а именно безопасно передавать из контекста в контекст).
Ещё круче, мы можем передать SharedArrayBuffer. Почти настоящая многопоточка! Да, несколько независимых контекстов обращаются к одной области памяти и могут устроить себе веселье. А чтобы веселья было поменьше нам даже завезли атомики. А так же завезли кучу ограничений безопасности, из-за чего пришлось откатывать SharedArrayBuffer и только буквально недавно он к нам вернулся. Но называть это мультитредингом язык не поворачивается всё равно.
Надо будет сделать отдельный пост про проблемы SharedArrayBuffer.
UPD
В комментах посоветовали эту книгу https://dmkpress.com/catalog/computer/programming/java/978-5-93700-129/ . Я сначала немного бомбанул на название, но авторы оказались честны «Надо признать, что, вопреки названию книги, сам язык не содержит никаких встроенных средств для создания потоков.»
Как мы знаем, JS это синхронный однопоточный язык. Многопоточность в нём невозможна бай дизайн. Ну нет никакой возможности создать потоки в том же контексте, пошарить память, забыть про синхронизацию, устроить гонку, всё сломать. Пишешь свой код с асинхронным вызовами и радуешь тому, что всё небыстро, но просто.
Да, у нас есть возможность порождать веб-воркеры и воркер-треды (одно в браузере, второе в node.js, соответственно). Можно соорудить воркер-пул и отбрасывать туда тяжёлые задачи, асинхронно забирая ответы. Многопоточность ли это? Скорее многопроцессность. Мы порождаем независимый процесс с полностью независимым контекстом (и независимым event loop) и общаемся с ним через сообщения с сериализованными данными или transferable objects (ArrayBuffer и ImageBitmap, например). Т.е. можно перебрасывать некоторый набор специальных объектов между контекстами (не шарить, а именно безопасно передавать из контекста в контекст).
Ещё круче, мы можем передать SharedArrayBuffer. Почти настоящая многопоточка! Да, несколько независимых контекстов обращаются к одной области памяти и могут устроить себе веселье. А чтобы веселья было поменьше нам даже завезли атомики. А так же завезли кучу ограничений безопасности, из-за чего пришлось откатывать SharedArrayBuffer и только буквально недавно он к нам вернулся. Но называть это мультитредингом язык не поворачивается всё равно.
Надо будет сделать отдельный пост про проблемы SharedArrayBuffer.
UPD
В комментах посоветовали эту книгу https://dmkpress.com/catalog/computer/programming/java/978-5-93700-129/ . Я сначала немного бомбанул на название, но авторы оказались честны «Надо признать, что, вопреки названию книги, сам язык не содержит никаких встроенных средств для создания потоков.»
👍35🔥12
Нет пароля — нет проблем?
В прошедшее воскресенье докладил про WebAuthn и прочие Passkeys. Не то, чтобы очень горел темой, но хотелось разобраться как оно работает, а что может быть лучше для разобраться, чем сделать доклад?
Тл;др: выводы печальные — работает всё очень не очень. Лонг стори шот.
Как-то раз собрались разные ребята из разных больших компаний и решили порешать проблему паролей. И назвались они FIDO Alliance. После нескольких итераций родился стандарт FIDO2, который состоит собственно из протокола CTAP2 и браузерной апихи WebAuthn. Протокол этот позволяет браузеру общаться с хардварными аутентификаторами, встроенными в наши телефоны/ноутбуки, либо переносимыми (YubiKey). Идея простая как палка — когда мы хотим где-то зарегистрироваться, то создаётся пара ключей: публичный и приватный. Публичный ключ уезжает на сайт, приватный загружается в вашу железку (почти как SSH-ключи, только никаких файлов на диске не валяется). Каждая такая пара ключей уникальна для каждого сайта. Красть с сервера теперь нечего — ваш публичный ключ никуда не подложить.
Когда вы хотите снова зайти на сайт, то к вам прилетает некая случайная строка, которую аутентификатор шифрует приватным ключом, ответ кидается обратно на сервер и там расшировывается публичным. И ура, вы на сайте.
Несмотря на то, что технология предполагалась для полной замены паролей, она, в основном, везде была внедрена как второй фактор (хотя сама по себе является двухфакторной, ваши ключики защищены биометрией или пин-кодом). Почему так? Да просто из-за излишней сложности для обычных нормальных людей. Ключи надо привязывать к аккаунтам во всём множестве, 1 устройство — 1 ключ. Т.е. на айфоне, и на макбуке и на айпаде надо создавать отдельные ключи (не копии). YubiKey немного спасает, но в него влазит мало ключей, потерять его легко, стоит дорого, а пользоваться неудобно.
Ну и год назад Apple на WWDC сказали, что вот, теперь у них готово решение, которое называется Passkeys. Что это такое? Это фактически те же самые WebAuthn ключи, но переносимые через облако. Вы создали 1 ключ на айфоне — теперь он доступен на всех Apple-устройствах. Google и Microsoft присоединились к этой идее переносимых через облако приватных ключей.
Стало ли лучше? И да и нет. Если вы живёте на экосистеме Apple, пользуетесь Safari и iCloud то всё у вас будет замечательно. С Chrome уже похуже (синхронизацию допиливают). С Firefox просто никак. В облаках Google и Microsoft тоже раздрай. В Linux нет и не планируется. Чужих облаков в этой системе пока нет (1Password обещает скоро запилить своё). Синхронизации между разными облаками тоже нет. Более того, переводя ключи в облако, Apple понизила безопасность WebAuthn убрав аттестацию аутентификатора. И, что ещё хуже, начиная с iOS 16 они отключили возможность хранить ключи локально в Secure Enclave телефона, обязательно требуется подключенный iCloud. Сволочи.
Отдельная печаль это вход через QR код. Придумано всё круто, связь между близкорасположенными устройствами только по Bluetooth, ничего не утекает, общение через relay-серверы владельцев экосистем. Ну вы понимаете, да. Некоторый такой лок.
Так что вот, решение какое-то есть, но вопросов к нему многовато.
В прошедшее воскресенье докладил про WebAuthn и прочие Passkeys. Не то, чтобы очень горел темой, но хотелось разобраться как оно работает, а что может быть лучше для разобраться, чем сделать доклад?
Тл;др: выводы печальные — работает всё очень не очень. Лонг стори шот.
Как-то раз собрались разные ребята из разных больших компаний и решили порешать проблему паролей. И назвались они FIDO Alliance. После нескольких итераций родился стандарт FIDO2, который состоит собственно из протокола CTAP2 и браузерной апихи WebAuthn. Протокол этот позволяет браузеру общаться с хардварными аутентификаторами, встроенными в наши телефоны/ноутбуки, либо переносимыми (YubiKey). Идея простая как палка — когда мы хотим где-то зарегистрироваться, то создаётся пара ключей: публичный и приватный. Публичный ключ уезжает на сайт, приватный загружается в вашу железку (почти как SSH-ключи, только никаких файлов на диске не валяется). Каждая такая пара ключей уникальна для каждого сайта. Красть с сервера теперь нечего — ваш публичный ключ никуда не подложить.
Когда вы хотите снова зайти на сайт, то к вам прилетает некая случайная строка, которую аутентификатор шифрует приватным ключом, ответ кидается обратно на сервер и там расшировывается публичным. И ура, вы на сайте.
Несмотря на то, что технология предполагалась для полной замены паролей, она, в основном, везде была внедрена как второй фактор (хотя сама по себе является двухфакторной, ваши ключики защищены биометрией или пин-кодом). Почему так? Да просто из-за излишней сложности для обычных нормальных людей. Ключи надо привязывать к аккаунтам во всём множестве, 1 устройство — 1 ключ. Т.е. на айфоне, и на макбуке и на айпаде надо создавать отдельные ключи (не копии). YubiKey немного спасает, но в него влазит мало ключей, потерять его легко, стоит дорого, а пользоваться неудобно.
Ну и год назад Apple на WWDC сказали, что вот, теперь у них готово решение, которое называется Passkeys. Что это такое? Это фактически те же самые WebAuthn ключи, но переносимые через облако. Вы создали 1 ключ на айфоне — теперь он доступен на всех Apple-устройствах. Google и Microsoft присоединились к этой идее переносимых через облако приватных ключей.
Стало ли лучше? И да и нет. Если вы живёте на экосистеме Apple, пользуетесь Safari и iCloud то всё у вас будет замечательно. С Chrome уже похуже (синхронизацию допиливают). С Firefox просто никак. В облаках Google и Microsoft тоже раздрай. В Linux нет и не планируется. Чужих облаков в этой системе пока нет (1Password обещает скоро запилить своё). Синхронизации между разными облаками тоже нет. Более того, переводя ключи в облако, Apple понизила безопасность WebAuthn убрав аттестацию аутентификатора. И, что ещё хуже, начиная с iOS 16 они отключили возможность хранить ключи локально в Secure Enclave телефона, обязательно требуется подключенный iCloud. Сволочи.
Отдельная печаль это вход через QR код. Придумано всё круто, связь между близкорасположенными устройствами только по Bluetooth, ничего не утекает, общение через relay-серверы владельцев экосистем. Ну вы понимаете, да. Некоторый такой лок.
Так что вот, решение какое-то есть, но вопросов к нему многовато.
👍52❤5
Взываю к помощи коллективного разума.
Смотрите, имеем node.js-процесс. Процесс спаунит чайл-процессы. Убийство родителя по
Так в чём здесь отличие
UPD коллективный разум нашёл ответ https://stackoverflow.com/questions/8398845/what-is-the-difference-between-ctrl-c-and-sigint/8406413#8406413
Баш сам пробрасывает SIGINT по всей группе процессов.
Смотрите, имеем node.js-процесс. Процесс спаунит чайл-процессы. Убийство родителя по
ctrl+c приводит и к смерти чайлд-процессов. Но почему отправка SIGINT не приводит к такому результату и чайлды не умирают? Ни SIGINT, ни SIGTERM ни злобный SIGKILL не трогают чайлдов. Так в чём здесь отличие
ctrl+c?UPD коллективный разум нашёл ответ https://stackoverflow.com/questions/8398845/what-is-the-difference-between-ctrl-c-and-sigint/8406413#8406413
Баш сам пробрасывает SIGINT по всей группе процессов.
Stack Overflow
What is the difference between Ctrl-C and SIGINT?
I have been debugging a Python program which segfaults after receiving a KeyboardInterrupt exception. This is normally done by pressing Ctrl+C from the shell. To test if a particular code change fi...
👍16🔥3
Опять Гугл всё сломал
В мае Гугл запустил новый домен первого уровня
Заметили подставу? А если бы вам не сказали, что в ссылке есть проблема?
Переход по такой ссылке направит нас на
А чтобы жизнь была ещё веселей, Гугл добавил TLD
Подробнее о проблеме и вариантах атак: https://medium.com/@bobbyrsec/the-dangers-of-googles-zip-tld-5e1e675e59a5
UPD
В фишинговой ссылке из примера используется два хака: символ @ и «другой» слеш ∕ (U+2215)
В мае Гугл запустил новый домен первого уровня
.zip и неплохо так насолил безопасникам. Дело в том, что браузеру тоже можно скормить урл с userinfo частью (<протокол>//<userinfo>@<домен>), а значит, можно подсунуть пользователю адрес вида https://github.com∕kubernetes∕kubernetes∕archive∕refs∕tags∕@v1.27.1.zip.
Заметили подставу? А если бы вам не сказали, что в ссылке есть проблема?
Переход по такой ссылке направит нас на
v1.27.1.zip. Более того, собачку в адресе можно скрыть в интерфейсе, уменьшив шрифт.
А чтобы жизнь была ещё веселей, Гугл добавил TLD
.mov. А мессенджеры превратили это в ссылки. Так и живём.Подробнее о проблеме и вариантах атак: https://medium.com/@bobbyrsec/the-dangers-of-googles-zip-tld-5e1e675e59a5
UPD
В фишинговой ссылке из примера используется два хака: символ @ и «другой» слеш ∕ (U+2215)
😁23🤯20😱4❤2🤬2👍1😢1
Каждый год перед запуском ctf мучительно ищу подходящий RSA-ключ чтобы настроить каждый сервер. 1Password сделал свой ssh-agent но только в облачной версии, на которую я по понятным причинам переходить не хочу. Хранить на юбиках? Ну так ещё проще потерять юбик, чем облако.
Вот и продолжаю хранить в файликах и подбирать подходящий. Ещё один вариант — сделать мастер пароль и спрятать его в 1Password, а при утере ключа — ну и фиг с ним, залить новый.
Эй, подписчики, а вы как храните свои ключи?
Вот и продолжаю хранить в файликах и подбирать подходящий. Ещё один вариант — сделать мастер пароль и спрятать его в 1Password, а при утере ключа — ну и фиг с ним, залить новый.
Эй, подписчики, а вы как храните свои ключи?
Кто поленился настроить UFW и выставил ctf портами наружу — тот я :) Спасибо Саше Шоронову, что посканировал порты и пришёл с багой. Сколько не ставь Basic Auth в nginx, если рядом нода слушает сеть, то ой. А делал бы на юникс сокетах — горя бы не знал, но что-то подвела привычка (когда писал первую ctf уже жил в парадигме, что в контейнере nginx не нужен, и нода сама слушает сеть, как бы это не странно звучало).
В общем, не будьте мной, не ленитесь в виртуалках прикрывать порты. А unix-сокеты так-то всё ещё хороши.
Если же nginx гонит трафик на node через unix-сокет, то даже при открытых портах снаружи через сеть туда уже будет не достучаться.
В общем, не будьте мной, не ленитесь в виртуалках прикрывать порты. А unix-сокеты так-то всё ещё хороши.
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
UPD
Тут просят пояснить, что за набор букв я написал. Смотрите, запущенный сервер на node.js слушает либо unix-сокет (который описывается как файл на файловой системе) либо сетевой порт. Какой-нибудь 3000, например. Перед нодой стоит какой-нибудь nginx, слушает порты 80 и 443 и закидывает трафик на 3000 порт локлхоста который и слушает node.js. Это называется «реверс-прокси». Если не закрыть порты фаерволом, оставив только 80, 443 и какой-нибудь 22 для ssh, то можно будет просканировать все порты снаружи, найти наш 3000 и постучаться на ноду в обход nginx, забив на все его правила. Если же nginx гонит трафик на node через unix-сокет, то даже при открытых портах снаружи через сеть туда уже будет не достучаться.
😱15❤11👍4
Вот загадка, почему на macOS не идёт в комплекте git. Каждый раз этот квест с установкой Xcode Command Line Tools или
Но мне же просто нужен бинарь гита в комплекте, работающий после любого апдейта. Вы же типа профессиональная ось, линукс с человеческим лицом. Положите в коробку тулзу, пусть лежит.
Вот SSH-клиент у нас же есть. Плохонький, но есть.
brew install git (который под капотом ставит Xcode Command Line Tools). Но мне же просто нужен бинарь гита в комплекте, работающий после любого апдейта. Вы же типа профессиональная ось, линукс с человеческим лицом. Положите в коробку тулзу, пусть лежит.
Вот SSH-клиент у нас же есть. Плохонький, но есть.
👍32
В поезде прочитал интересные размышления от François Zaninotto — Is React Having An Angular.js Moment?
Франсуа задаётся вопросом, не подошёл ли Реакт к той же точке, в которую однажды упёрся Ангуляр, когда вторая версия оказалась полностью переписанной с использованием других парадигм. В итоге, многие разработчики не стали переписывать свои приложения на новую версию, вместо этого просто сменив фреймворк.
И вот у нас React предлагает поменять парадигму и перейти на Server Components. И это опасное место.
Теперь наши компоненты уже не просто рисуют отображение по состоянию. Они становятся сложнее. Теперь прямо в компонентах мы можем использовать
Вообще
CSS-in-JS решения тоже пока не работают в серверных компонентах. (Тут я конечно немного радуюсь, что «классические» решения всё так же хороши).
С отладкой тоже пока не очень, но тут наверное допилят (должны допилить!).
Экосистемы для RSC просто нет. Знакомые нам либы не работают (react-query, swr, react-hook-form и т.д.). Короче, всё, что на хуках.
Если они нам нужны, то мы должны заворачивать всё в обёртки с
Почти всё сломано. А ещё и контекст отобрали, как теперь лёгкий DI пилить?
И запросы на сервер странные. Формат намеренно не документирован.
Разработчикам SPA всё это не нравится. Они обеспокоены. Для SSR они готовы брать другие решения. Почему Реакт отговаривает от SPA? Почему официальная документация рекомендует Next, а Next рекомендует RSC? Может быть это способ помочь Vercel заработать на React? Ведь для RSC нужен бэкенд, а бэкенд нужно где-то запускать.
Но отвечая на заглавный вопрос, проходит ли React свой «момент Angular», автор говорит — нет, не проходит. Потому что мы всё ещё можем писать «по-старому». Без Server Components.
Но в то же время пользователи теперь вынуждены выбирать между старым рабочим решением и новым сияющим активно рекламируемым. И это опасно. Между двух альтернатив выбора может возникнуть третья — иной фреймворк. И вот тут React вполне может нанести вред своему сообществу. Зачем мне RSC, с той же долей риска я могу перейти на Solid или ещё куда-нибудь.
В заключении Франсуа призывает команды React и Next одуматься и притушить рекламный поток для RSC. Не выпячивать это решение как противовес «классике» и единственное возможное будущее, чтобы не навредить экосистеме React.
Франсуа задаётся вопросом, не подошёл ли Реакт к той же точке, в которую однажды упёрся Ангуляр, когда вторая версия оказалась полностью переписанной с использованием других парадигм. В итоге, многие разработчики не стали переписывать свои приложения на новую версию, вместо этого просто сменив фреймворк.
И вот у нас React предлагает поменять парадигму и перейти на Server Components. И это опасное место.
Теперь наши компоненты уже не просто рисуют отображение по состоянию. Они становятся сложнее. Теперь прямо в компонентах мы можем использовать
fetch не заворачивая его useEffect. И это не браузерный fetch, это патченая его версия. Зачем патченая? Для того, чтобы бороться с лишним ре-фетчем данных и обложить всё кешами из коробки. А кешировать забрасывая данные в контекст мы больше не можем — нет в серверных компонентах контекста.Вообще
useState, useContext и useEffect — все они не работают. Мы можем их включить, используя use client, но это теперь не поведение по умолчанию. CSS-in-JS решения тоже пока не работают в серверных компонентах. (Тут я конечно немного радуюсь, что «классические» решения всё так же хороши).
С отладкой тоже пока не очень, но тут наверное допилят (должны допилить!).
Экосистемы для RSC просто нет. Знакомые нам либы не работают (react-query, swr, react-hook-form и т.д.). Короче, всё, что на хуках.
Если они нам нужны, то мы должны заворачивать всё в обёртки с
use client. Почти всё сломано. А ещё и контекст отобрали, как теперь лёгкий DI пилить?
И запросы на сервер странные. Формат намеренно не документирован.
Разработчикам SPA всё это не нравится. Они обеспокоены. Для SSR они готовы брать другие решения. Почему Реакт отговаривает от SPA? Почему официальная документация рекомендует Next, а Next рекомендует RSC? Может быть это способ помочь Vercel заработать на React? Ведь для RSC нужен бэкенд, а бэкенд нужно где-то запускать.
Но отвечая на заглавный вопрос, проходит ли React свой «момент Angular», автор говорит — нет, не проходит. Потому что мы всё ещё можем писать «по-старому». Без Server Components.
Но в то же время пользователи теперь вынуждены выбирать между старым рабочим решением и новым сияющим активно рекламируемым. И это опасно. Между двух альтернатив выбора может возникнуть третья — иной фреймворк. И вот тут React вполне может нанести вред своему сообществу. Зачем мне RSC, с той же долей риска я могу перейти на Solid или ещё куда-нибудь.
В заключении Франсуа призывает команды React и Next одуматься и притушить рекламный поток для RSC. Не выпячивать это решение как противовес «классике» и единственное возможное будущее, чтобы не навредить экосистеме React.
Marmelab
Is React Having An Angular.js Moment?
React Server Components, while innovative, risk causing division in the React community due to their potential to undermine Single-Page App architecture.
👍65❤8😱1💘1
Студент прислал вопрос — почему этот код тормозит?
Вот эта штука крутится почти две минуты. И даже убрать тело цикла в функцию, чтобы гарантированно попасть в кэши JIT никак не помогает. Неужели JIT настолько плох, что не может оптимизировать бесполезные вызовы?
Что же, открываем Deopt Explorer и ищем проблему. На самом деле, вот этот код будет тормозить точно так же:
Deopt Explorer сразу даёт нам причину деоптимизации —
Проверим?
А вот мы вышли за границы SMI:
Такой подход называется pointer tagging — за счёт отдельного бита мы можем точно сказать, что в данном случае у нас не указатель на heap, а непосредственно значение примитива. Т.е. брать значение прямо из стека, а не бегать за ним в кучу. Получается, что как только мы выходим за границу SMI мы уже начинаем работать с объектом в куче и теряем в производительности.
В итоге как обычно попали в ловушку синтетических тестов и протестировали не то, что хотели протестировать, но многое поняли :)
UPD
Бенчмарки для оригинального цикла: 1:35.161 (m:ss.mmm)
Для решения с вложенным циклом (чтобы указатели остались в smi): 48.156s
А если мы поможем JIT и вложенный цикл уберём в функцию, то: 32.325s
console.time ("answer time");
const max = 100000000000;
console.log(' max=', max);
let i = 0;
while(i < max) {
const y = Math.pow(2,100);
const z = Math.pow(15, 100000);
i++;
}
console.timeEnd("answer time");
Вот эта штука крутится почти две минуты. И даже убрать тело цикла в функцию, чтобы гарантированно попасть в кэши JIT никак не помогает. Неужели JIT настолько плох, что не может оптимизировать бесполезные вызовы?
Что же, открываем Deopt Explorer и ищем проблему. На самом деле, вот этот код будет тормозить точно так же:
const max = 100000000000;
let i = 0;
while(i < max) {
i++;
}
Deopt Explorer сразу даёт нам причину деоптимизации —
i++ (overflow). Что за дела, спросите вы? Это же далеко не Number.MAX_SAFE_INTEGER, запаса достаточно. Дело в том, что V8 (как и другие JS-движки) умеет эффективно работать со SMI (small integers). На 64-битных платформах это соответственно диапазон от -2³¹ до 2³¹-1.
Проверим?
%DebugPrint(2147483647);
DebugPrint: Smi: 0x7fffffff (2147483647)
А вот мы вышли за границы SMI:
%DebugPrint(2147483648);
DebugPrint: 2147483648.0
0x148993d415e9: [Map] in ReadOnlySpace
- type: HEAP_NUMBER_TYPE
- instance size: 16
- elements kind: HOLEY_ELEMENTS
- unused property fields: 0
- enum length: invalid
- stable_map
- back pointer: 0x148993d415b9 <undefined>
- prototype_validity cell: 0
- instance denoscriptors (own) #0: 0x148993d41269 <Other heap object (STRONG_DESCRIPTOR_ARRAY_TYPE)>
- prototype: 0x148993d41339 <null>
- constructor: 0x148993d41339 <null>
- dependent code: 0x148993d41251 <Other heap object (WEAK_ARRAY_LIST_TYPE)>
- construction counter: 0
Такой подход называется pointer tagging — за счёт отдельного бита мы можем точно сказать, что в данном случае у нас не указатель на heap, а непосредственно значение примитива. Т.е. брать значение прямо из стека, а не бегать за ним в кучу. Получается, что как только мы выходим за границу SMI мы уже начинаем работать с объектом в куче и теряем в производительности.
В итоге как обычно попали в ловушку синтетических тестов и протестировали не то, что хотели протестировать, но многое поняли :)
UPD
Бенчмарки для оригинального цикла: 1:35.161 (m:ss.mmm)
Для решения с вложенным циклом (чтобы указатели остались в smi): 48.156s
А если мы поможем JIT и вложенный цикл уберём в функцию, то: 32.325s
🔥58❤19🤯8👍6❤🔥1
Нашёл неплохую статью с подробным объяснением того, как JS работает с памятью
TL;DR:
All JavaScript values are allocated on the heap accessed by pointers no matter if they are objects, arrays, strings or numbers (except for small integers i.e. smi in V8 due to pointer tagging).
The stack only stores temporary, function-local and small variables (mostly pointers) and that's largely unrelated to JavaScript types.
https://www.zhenghao.io/posts/javanoscript-memory
TL;DR:
All JavaScript values are allocated on the heap accessed by pointers no matter if they are objects, arrays, strings or numbers (except for small integers i.e. smi in V8 due to pointer tagging).
The stack only stores temporary, function-local and small variables (mostly pointers) and that's largely unrelated to JavaScript types.
https://www.zhenghao.io/posts/javanoscript-memory
👍29❤1
Немного удивлён, что никто не обратил внимания на фразу «На 64-битных платформах диапазон значений для SMI от -2³¹ до 2³¹-1». А для 32-битных как? А почему?
32-битные системы хранят указатели и SMI вот так (речь про v8)
64-битные вот так:
Т.е. в 32-битных системах мы теряем один бит на то, чтобы запомнить (протегировать) — указатель у нас или SMI, в SMI влазит только int31. В 64-битных системах метка (тег) переезжает в «свободные» 32-бита и мы можем хранить int32.
Кстати, с этим связан один неприятный момент. Когда в V8 решили включить Pointer Compression (сжатие указателей), то оказалось, что да, мы можем хранить два 32-битных указателя в одном 64-битном слове (там применяется достаточно сложный алгоритм), но вот снова положить два int31 — это приводит к деградации производительности (1% на Octane). А два int32 не помещаются, негде хранить тег.
Так как производительность важнее, а SMI у нас не так много в коде, то оставили как есть, всё равно выигрыш по памяти получился приличный, потребление практически вернулось к значениям для 32-битных систем.
UPD
В комментах @cevek подсказал, что всё же включили компрессию для SMI, и в браузере в SMI будет именно int31, а не int32 «как раньше».
С нодой интереснее, в ноде компрессия указателей изначально не была включена из-за проблем совместимости с нативными аддонами, потому мы продолжаем видеть в SMI int32. Есть такое обсуждение.
32-битные системы хранят указатели и SMI вот так (речь про v8)
|----- 32 bits -----|
Pointer: |_____address_____w1|
Smi: |___int31_value____0|
64-битные вот так:
|----- 32 bits -----|----- 32 bits -----|
Pointer: |________________address______________w1|
Smi: |____int32_value____|0000000000000000000|
Т.е. в 32-битных системах мы теряем один бит на то, чтобы запомнить (протегировать) — указатель у нас или SMI, в SMI влазит только int31. В 64-битных системах метка (тег) переезжает в «свободные» 32-бита и мы можем хранить int32.
Кстати, с этим связан один неприятный момент. Когда в V8 решили включить Pointer Compression (сжатие указателей), то оказалось, что да, мы можем хранить два 32-битных указателя в одном 64-битном слове (там применяется достаточно сложный алгоритм), но вот снова положить два int31 — это приводит к деградации производительности (1% на Octane). А два int32 не помещаются, негде хранить тег.
UPD
В комментах @cevek подсказал, что всё же включили компрессию для SMI, и в браузере в SMI будет именно int31, а не int32 «как раньше».
%DebugPrint(2147483647)
DebugPrint: 2147483647.0
0x5f700000339: [Map] in ReadOnlySpace
С нодой интереснее, в ноде компрессия указателей изначально не была включена из-за проблем совместимости с нативными аддонами, потому мы продолжаем видеть в SMI int32. Есть такое обсуждение.
🔥14🤯6❤2👍1