Ошибка ссылки на код секретного сервера Meteor, переменная не определена

В разделе секретного кода сервера в документации Meteor (https://guide.meteor.com/security.html#secret-code) они, похоже, используют глобальную переменную, определенную только на сервере, поэтому код можно увидеть и получить доступ только на сервере. Кажется достаточно простым.

Но когда я сделаю

upload = { test: "my secret code" }

Внутри папки server/upload.js появляется ошибка

W20170726-10:04:59.843(2)? (STDERR) 
C:\Users\myuser\AppData\Local\.meteor\packages\meteor-tool\1.5.0\mt-os.windows.x86_32\dev_bundle\server-lib\node_modules\fibers\future.js:280
W20170726-10:04:59.844(2)? (STDERR)                                             throw(ex);
W20170726-10:04:59.846(2)? (STDERR)                                             ^
W20170726-10:04:59.847(2)? (STDERR)
W20170726-10:04:59.847(2)? (STDERR) ReferenceError: upload is not defined
W20170726-10:04:59.848(2)? (STDERR)     at meteorInstall.server.upload.upload.js (server/upload/upload.js:1:1)
W20170726-10:04:59.849(2)? (STDERR)     at fileEvaluate (packages\modules-runtime.js:333:9)
W20170726-10:04:59.850(2)? (STDERR)     at require (packages\modules-runtime.js:228:16)
W20170726-10:04:59.851(2)? (STDERR)     at C:\Users\myuser\Documents\projects\myproject\.meteor\local\build\programs\server\app\app.js:10417:1
W20170726-10:04:59.852(2)? (STDERR)     at C:\Users\myuser\Documents\projects\myproject\.meteor\local\build\programs\server\boot.js:338:34
W20170726-10:04:59.853(2)? (STDERR)     at Array.forEach (native)
W20170726-10:04:59.854(2)? (STDERR)     at Function._.each._.forEach (C:\Users\myuser\AppData\Local\.meteor\packages\meteor-tool\1.5.0\mt-os.windows.x86_32\dev_bundle\server-lib\node_modules\underscore\underscore.js:79:11)
W20170726-10:04:59.855(2)? (STDERR)     at C:\Users\myuser\Documents\projects\myproject\.meteor\local\build\programs\server\boot.js:158:5
W20170726-10:04:59.856(2)? (STDERR)     at C:\Users\myuser\Documents\projects\myproject\.meteor\local\build\programs\server\boot.js:387:5
W20170726-10:04:59.858(2)? (STDERR)     at Function.run (C:\Users\myuser\Documents\projects\myproject\.meteor\local\build\programs\server\profile.js:510:12)

Документы неправильные, или я просто делаю что-то странное? Я использую версию 1.5.0 Meteor, работает как в Windows, так и в Linux.


person Michael Rehn    schedule 26.07.2017    source источник


Ответы (2)


В документации указано, что

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

Это (к сожалению, просто) подразумевает, что код метеорных методов или проверенных методов также виртуально выполняется на клиенте (см. this.isSimulation) как часть оптимистичного пользовательского интерфейса и, таким образом, может раскрывать секреты, такие как ключи.

Использование global.myvariable = { ... } является не лучшим решением здесь.

Чтобы вам было понятнее, я немного расширяю пример из документации:

/server/mmr.js (загружается только вашим сервером)

export const MMR = {
  updateWithSecretAlgorithm(userId) {
    // your secret code here
  }
}

/both/updatemmr.js (загружается как сервером, так и клиентом)

if (Meteor.isServer) {
    //eslint will nag but it does not cause any error
    import {MMR} from '../server/mmr.js';
}

// In a file loaded on client and server
const Meteor.users.methods.updateMMR = new ValidatedMethod({
  name: 'Meteor.users.methods.updateMMR',
  validate: null,
  run() {
    if (this.isSimulation) {
      // Simulation code for the client (optional)
    } else {
      MMR.updateWithSecretAlgorithm(this.userId);
    }
  }
});

Meteor.isServer только гарантирует, что клиент не будет пытаться импортировать MMR, что могло бы вызвать ошибку при запуске. Пока вы загружаете файл mmr.js только на сервер, клиенту не будет предоставлен доступ к объекту MMR.

Надеюсь, это проясняет пример.

person Jankapunkt    schedule 26.07.2017
comment
Да, я действительно хотел попробовать что-то подобное, но я думал, что условный импорт был грязным (как вы упомянули, eslint будет ворчать), но, возможно, вы правы, что глобальные переменные действительно еще более беспорядочные. Однако я обнаружил, что вместо этого мы можем использовать require (guide.meteor.com/structure.html # using-require), который кажется рекомендуемым метеорным способом для условного импорта. - person Michael Rehn; 26.07.2017
comment
Да, использование require еще более экономно. Я использую явный импорт только из-за названного экспорта, и у меня никогда не возникало проблем с каким-либо кодом, отличным от верхнего уровня, даже не в продакшене. Также обратите внимание, что упомянутая проблема с динамическим требованием теперь решается динамический импорт - person Jankapunkt; 26.07.2017

Хорошо, по какой-то причине просто набрав myvariable = { ... }, он добавляется к глобальному объекту, поэтому я явно добавил i с помощью global.myvariable = { ... }. Вроде пока работает хорошо!

Редактировать

Как правильно указал Янкапункт, глобальные переменные действительно не приветствуются. Но вместо использования import внутри оператора if, как предлагал Jankapunkt, вы должны использовать синтаксис CommonJS вместо require, как рекомендовано в документации Meteor (https://guide.meteor.com/structure.html#using-require), например

let MMR;
if (Meteor.isServer) {
   MMR = require('../server/mmr.js').MMR;
}
person Michael Rehn    schedule 26.07.2017