Задать вопрос
  • Почему при попытке открыть сайт по http с мобильного устройства выходит ошибка net::ERR_CONNECTION_REFUSED?

    @AlexVWill
    Открой 80, некоторые браузеры умеют или настроены сами менять соединение с 80 на 443, а некоторые нет, и им для соединения надо сначало подсоединиться по 80, а потом сервер им даст редирект.
    Ответ написан
    1 комментарий
  • Как написать Docker файл для связки Front+Back+DB?

    И вам привет.

    Docker-compose вам в помощь, для начала. Голыми командами докера оперировать достаточно муторно, да и не требуется в реальных условиях.

    Возможно ли это всё запихнуть в контейнер и связать вместе?


    В один контейнер все это дело запихнуть однозначно можно, но - не нужно. Как понять, из какого набора контейнеров будет состоять ваша платформа? Очень просто.

    есть проект состоящий из Front (JS+React) + Back (бинарник на Go + config files) + DB (PostgreSQL)


    Вот и определились. Ваше приложение - состоит из frontend, backend и database. Названия взяты исключительно ради примера, но я не думаю, что в реалиях разработки продуктовых систем - вашему тим лиду понравится название "binarnik_na_go" вместо названия "backend" на код-ревью.

    Нужно ли в этот Docker файл интегрировать саму среду PostgreSQL или можно только базу данных?


    В каждом контейнере - содержится только одно приложение. Каждый контейнер - выполняет только одну команду. Если говорить о вашем бинарнике на Go, то команда, которую будет выполнять контейнер с backend - будет именем бинарника. Если это контейнер с БД, то в нем будет выполнятся только одна команда - запускающая сервер PostgreSQL. Для фронта - это будет команда pm2, или другая, с помощью которой вы запускаете сервер frontend.

    Бинарник бэка запускается на определённом порту, будет ли доступ к этому бинарнику по порту из-вне?


    Когда вы напишите конфигурацию своих сервисов в docker-compose.yml - и сделаете docker-compose up, docker-compose создаст виртуальную сеть. Сеть будет называться в формате <наименование директории, где лежит ваш docker-compose.yml>_default. Внутри этой сети, все сервисы будут иметь доступ друг к другу по имени сервиса и порту, указанному в EXPOSE в Dockerfile сервиса. Соответственно, ваш backend будет доступен по имени backend и порту, который вы укажите при сборке образа. Например, http://backend:8080. При этом, вы не сможете обратиться к этому имени/порту за пределами виртуальной сети. Чтобы вытащить порт "наружу", потребуется настроить биндинг портов от контейнера с backend на локальный хост, делается это с помощью директивы ports в описании сервиса в файле docker-compose.yml.

    Спрашиваю потому, что если запущу несколько подобных контейнеров не будут ли они конфликтовать за порты?


    Внутри сети - конфликтов не будет. Т.к. запустить несколько контейнеров с одинаковым именем их сервиса - не возможно. Но, можно скалировать контейнеры - с помощью определенных команд, о которых на данном этапе говорить нет смысла. На локальный хост, соответственно, вытащить два и более сервиса на один и тот же порт не получится, по понятным причинам.

    Или каждый образ надо кофигурировать под отдельный порт?


    Конфигурировать разные порты не требуется, т.к. каждый сервис имеет свое уникальное имя внутри сети контейнеров.

    К практике.

    Dockerfile для backend-а на Go может выглядеть так:

    # Тут берем официальный образ Golang для компиляции бинарника
    # В нем есть все для сборки, за редким исключением
    FROM golang:stretch as builder
    
    # Устанавливаем рабочую директорию внутри образа сборки бинарника
    WORKDIR /app
    
    # Копируем содержимое директории с вашим проектом в образ для сборки
    COPY . .
    
    # Скачиваем зависимости
    RUN go get -d -v
    
    # Собираем бинарник в директорию /app/bin
    RUN GOOS=linux GOARCH=amd64 go build -i -o bin/backend main.go
    
    # А теперь берем минимальный образ для запуска бинарника
    FROM scratch
    
    # Из образа для сборки, копируем готовый бинарник backend-а
    COPY --from=builder /app/bin/backend /app/bin/backend
    
    # Назначаем полученный бинарник точкой входа в контейнер
    ENTRYPOINT ["/app/bin/backend"]


    Теперь, если зайти в директорию с проектом backend и выполнить:

    docker build -t backend:latest .

    У вас соберется image с именем backend и тегом latest. Можно запускать, собственно.

    Образ для frontend собирите своими силами, зато разберетесь. Там суть таже, первым этапом можно взять image с node-js, собрать в нем frontend, а для запуска - использовать image c pm2 - скопировав директорию с приложением из этапа сборки.

    Как будет выглядеть ваш docker-compose.yml:

    version: "3.7"
    
    volumes:
      database:
    
    services:
    
      # Postgres. Берем готовый официальный образ
      database:
        image: postgres:12-alpine
        # Вот собственно тут и указывается, какие порты будут видны на вашей локали
        ports:
          - 5432:5432
        # Там выше в volumes указывали набор volumes. Используем вольюм database, чтобы хранить БД
        volumes:
          - database:/var/lib/postgresql/data
        restart: always
    
      # Backend. Берем образ, что собрали выше
      backend:
        image: backend:latest
        # В Dockerfile мы для гибкости не указывали порт backend-a. Укажем его тут. 
        expose: 
          - 8080
        ports:
          - 8080:8080
        restart: always
    
      # Frontend
      frontend:
        image: frontend:latest
        expose: 
          - 80
        ports:
          - 80:80
        restart: always


    Собственно и все. Остается поправить синтаксические ошибки и запустить, командой docker-compose up. Кстати, в интернетах есть очень много примеров проектов с кучами сервисов, с отдельными сетями для backend/frontend, с проксированием api через nginx/traefik и прочими фишками.

    Удачи.
    Ответ написан
    Комментировать
  • ERR_CERT_AUTHORITY_INVALID. Как обойти?

    CityCat4
    @CityCat4 Куратор тега Цифровые сертификаты
    //COPY01 EXEC PGM=IEBGENER
    п. 1 Внести сертификат издателя в список доверенных CA.
    п. 2 Если сертификат самозаверенный - создать СA и выпустить в нем сертификат, потом см. п. 1 :)

    Можно купить сертификат
    Можно попробовать получить его на LE
    Можно дать юзеру инструкцию, как продолжить работу :)

    Все зависит от того, насколько Вы готовы потратиться (временем, деньгами etc.). "Обойти" здесь никак не получится - выполняется все это у пользователя. Он подключается к ресурсу, получает его сертификат. Проверяет сертификат на валидность - в число проверок входит и тот факт, что сертификат должен быть выпущен CA, известным ему как корневое. Если это не так - сертификат недоверен и как раз возникает ERR_CERT_AUTHORITY_INVALID.
    Ответ написан
    Комментировать
  • Как подключить вконтакте на сайт чтобы слать юзеру в вк уведомления или сообщения?

    @GrigoryMorozov
    Судя по документации и FAQ, вы не можете использовать полученный токен для того, чтобы разрешить сообществу отправлять сообщения пользователю (метод messages.allowMessagesFromGroup доступен только для standalone-приложений и требует одобрения со стороны ВК).

    Доступные вам варианты — явно запросить согласие на отправку сообщений через виджет или мини-приложение.
    Ответ написан
  • Как лучше хранить много изображений для веб-приложения?

    @denizkino_mesto
    Все комментаторы выше далеки от реальности, хочешь в базе, хочешь в папках на дисковой подсистеме, хочешь в матрицах любых размерностей в оперативной памяти храни, как больше нравится и удобнее тебе. Производительность всей хурмы зависит только от реализации её, храниш на диске, складывай по папкам, которые будут служить разделами(индексами) расположения нужного файла с привязкой к чему-то удобному тебе, что быстро и без заморочек ты всегда понимал, как обратится к нужным данным, хранишь в базе, используй таблицу связей, храня в ней разделы, либо используй разделы прям в основной одной таблице, при выборке всегда добавляй связь с разделами для минимизации результатов выборки, используй при поиске ограничения топ, оффсет и прочую хурму, тоже и в оперативке. Файлы на дисковой подсистеме это та же база данных, только на уровне операционной системы и ее приложений, та же индексация, разбивка, долгий поиск и обращения к нужным данным при отсутствии структурированных индексов, для быстрого поиска рекомендую маркировать файлы самостоятельно тегами по которым можно их искать, как пример изображение с цветком, теги цвет, красный цветок, роза, ваза, цветок в вазе, лето, маша, ну суть думаю ясна. Файл dota2.exe теги игруха, дота, pvp, игры, игры на пк, компьютерные игры и т.д.
    Ответ написан
    Комментировать
  • Не могу установить Linux на ноутбук?

    @bakerman3020
    Всем привет, короче говоря, решение состоит в том, чтобы установить параметр ядра nvme_core.default_ps_max_latency_us = 5500 при загрузке. Тогда установка любого линукса (проверял на Ubuntu, Mint) работает "из коробки".
    Ноутбук acer aspire 3 a315-23

    Решение данной проблемы нашёл здесь: https://askubuntu.ru/questions/478272/problemy-s-u...

    Предыдущий источник ссылается на следующий англоязычный: https://community.wd.com/t/linux-support-for-wd-bl...

    В в меню загрузки GRUB нажмите e, чтобы изменить параметр запуска. Добавьте nvme_core.default_ps_max_latency_us=5500 после окончания, на одной строке с «тихой заставки» (quiet splash), после -- должен быть пробел, а потом уже сам параметр.
    Ctrl-x для загрузки, установщик должен обнаружить этот диск в разделе step.
    После завершения установки нажмите shift при включенном питании, чтобы снова войти в GRUB, добавьте тот же параметр ядра nvme_core.default_ps_max_latency_us = 5500 , Ctrl-x для загрузки.
    Вы увидите, что Ubuntu загружается успешно, отредактируйте / etc / default / grub , добавьте параметр nvme_core .default_ps_max_latency_us = 5500 снова, выполнить sudo update-grub , чтобы каждый раз при загрузке содержал этот параметр в личинке автоматически, ручное редактирование больше не требуется.
    Ответ написан
    Комментировать
  • Как именно устроены session и cookies?

    1. Кукисы пересылаются вместе с каждым запросом через заголовок Cookie. При изменении их на клиенте до ближайшего запроса ничего не будет.
    2. Или в зашифрованной куке, или в файле на сервере, или в базе данных, или где еще. Если не первый вариант, то используется кука с id сессии.
    3. Когда как, см. п. 2
    Ответ написан
    4 комментария
  • Как именно устроены session и cookies?

    @deliro
    1. Нет никакой синхронизации. Сервер может только указать клиенту, что ему нужно установить куку X в значение Y хэдером Set-Cookie и считать с пришедшего на сервер запроса куки (все куки отправляются в каждом запросе на сервер).
    2. Сессии могут храниться на клиенте (signed cookie session). При этом используется подпись куки с помощью HMAC, чтобы данные сессии не могли быть свободно изменены клиентом. Но обычно сессии хранятся на сервере. Тут выбор огромный: от баз данных и key-value хранилищ (Redis, например) до простых файлов. При этом, клиенту посылается кука ID сессии (так сервер идентифицирует юзера), которую злоумышленник может стащить. Таким кукам, дабы защитить юзеров от XSS, ставится флаг HttpOnly, который советует браузеру не давать эту куку скриптам вроде JS. В этом случае, стащить куку получится только завладев браузером, файловой системой юзера или через багу браузера.
    3. Смотри второй ответ. В некоторых случаях - да. Но редко.
    4. Можно передавать значение session id в строке URL (GET - параметром), вроде такого: example.com/some/page/?session_id=2af26905dcf31a1d... Некоторые сервисы используют это, как fallback вариант, однако, он очень небезопасен, т.к. любой XSS или простой безобидный JS вроде Яндекс.Метрика видит весь URL. Так что, посылаем юзера включать куки.
    Ответ написан
    4 комментария
  • Как сделать put экшена в колбеке с помощью redux saga и если нужно event channel?

    @Bone
    Была похожая проблема. Я решил, что самым простым способом будет дёргать store.dispatch напрямую, а не через put.

    1. Передаем store.dispatch в корневую сагу:

    const sagaMiddleware = createSagaMiddleware();
    const store = configureStore({
        reducer: {
            app: VkAppReducer,
        },
        middleware: [
            sagaMiddleware,
        ],
    });
    sagaMiddleware.run(rootSaga, store.dispatch);


    2. Из корневой саги, передаем dispatch в дочерние

    function* rootSaga(dispatch) {
        yield spawn(ChildSaga, dispatch);
    }


    3. В дочерней саге можем использовать dispatch в коллбеке:
    const params: MethodParams = {
                group_id: 1,
                access_token: access_token,
                onProgress: (s: string) => {
                    dispatch(setProgress(s));
                },
            };
    Ответ написан
    2 комментария
  • Почему не работает VK.Auth.login в Chrome?

    Oegir
    @Oegir Автор вопроса
    Web-программист
    Почему-то была включена галка "Блокировать данные и файлы cookie сторонних сайтов". Вроде бы по умолчанию она должна быть выключена.
    Ответ написан
    Комментировать
  • Как отловить событие закрытия страницы react.js?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    componentDidMount() {
      window.addEventListener('beforeunload', this.handleWindowBeforeUnload);
    }
    
    handleWindowBeforeUnload = e => {
      // e - целевое событие
    };
    Ответ написан
    2 комментария
  • Как правильно работать с изображениями на фронте react JS и на беке express js?

    inoise
    @inoise Куратор тега Amazon Web Services
    Solution Architect, AWS Certified, Serverless
    Отвечу по части AWS:
    1. Использовать S3 это хорошая идея, как и любое другое хранилище
    2. Проблема с недоступностью изображения может быть только в одном из двух случаев:
    - перезапись объекта при версионировании (тут работает eventual consistency model)
    - попытка запросить адрес до загрузки (может закэшироваться)

    В нормальный условиях работает strong consistency и все должно работать адекватно
    3. Мои рекомендации:
    - включить S3 Transfer acceleration для более быстрой загрузки или же AWS CloudFront (местный CDN)
    - делать одноразовые ссылки для загрузки изображений из соображений безопасности (S3 signed url)
    - наверняка захочется делать ресайз и обработку картинок "на лету", поэтому посмотреть сюда
    - вам наверняка захочется это где-то сохранять, пускать туда пользователей, поэтому для аутентификации взять Auth0 или Cognito, а для "бэка" взять AWS API Gateway + lambda. Хранить все можно в DynamoDB.
    - ExpressJS может не понадобиться, само приложение можно постить статикой на том же S3
    - Иногда AWS становится сложно для новичков и можно взять Firebase
    Ответ написан
    1 комментарий
  • В чем ошибка сборки webpack?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Замените babel на babel-loader:
    module: {
        loaders: [
          {
            test: /\.jsx?$/,
            loader: 'babel-loader?presets[]=es2015,presets[]=react,presets[]=stage-0'
          },
          ... 
        ]
      }

    Ну а по-хорошему перепишите конфиг по-современному:
    module: {
        rules: [
          {
            test: /\.js$/,
            exclude: /\/node_modules\//,
            use: [
              {
              loader: 'babel-loader',
              options: {
                presets: ['es2015', 'stage-0', 'react']
              }
            }]
          },
          ...
      ]
    }
    Ответ написан
  • Как работает метод render() в React?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    return возращает в скобках html код

    return не возвращает html код. JSX это лишь синтаксический сахар над JavaScript.

    JSX вида:
    render() {
      return (
        <h1 className="greeting">
          Hello, world!
        </h1>
      );
    }

    транслируется в JS вида:
    render() {
      return React.createElement(
        'h1',
        { className: 'greeting' },
        'Hello, world!'
      );
    }

    результат выполнения render в этом случае будет следующий:
    {
      $$typeof: Symbol(react.element),
      key: null,
      props: { className: "greeting", children: "Hello, world!" },
      ref: null,
      type: "h1",
      _owner: null,
      _store: { validated: false },
      _self: null,
      _source: null,
      __proto__: Object,
    }

    Возвращаемый объект это Virtual DOM Node. По ней библиотека создает элемент в реальном DOM.


    React компилятор перед сборкой парсит данные в файлах компонентов...
    ...Я понимаю что реакт собирает все в ES2015...

    React ничего не собирает. Никаких компиляторов библиотека не имеет. Процесс преобразования JSX в JS называется не компиляцией, а транспиляцией. Транспиляцию JSX в JS выполняют с помощью babel/TypeScript, а сборку обычно осуществляют с помощью библиотеки webpack.

    или же это нормально для ES6

    Нет. JSX не входит в спецификацию ECMAScript 2015
    Ответ написан
    3 комментария
  • Какой порядок работы с git?

    @aol-nnov
    смартгит в стороночку откладываешь, книжечку в руки https://git-scm.com/book/ru/v2
    практика командами гита, потом понимание процесса придет, а желание пользоваться смартгитом, скорее всего - уйдет.

    можно работать!
    Ответ написан
    Комментировать
  • Что такое call stack?

    Li4ik3
    @Li4ik3
    Стек вызовов или call stack — это список всех активных функций, которые вызывались, до текущей точки выполнения. В стеке вызовов отображается каждая вызываемая функция, а также строка, которая в данный момент выполняется в программе. Всякий раз, при вызове новой функции - она добавляется в самый top of call stack :) Как только выполнение текущей функции подходит к финишу, она удаляется из топа в стеке и контроль переходит к функции ниже (второй по счету). В общем источник, почитать о call stack можно здесь.
    Ответ написан
    1 комментарий