Meteor: попытка отдать статический файл за пределами /public

TLDR; Как можно передать статический файл через железный маршрутизатор? Если я помещаю файл в /public, он обходит все хуки, которые я мог бы использовать в железном маршрутизаторе.

Длинная версия: мне нужно регистрировать все запросы к файлу изображения. В частности, я хотел бы сохранить в Mongodb строку запроса в каждом запросе, таком как «a=1&b=2» из http://domain.com/cat.png?a=1&b=2.

Я не вижу способа сделать это в Метеоре. Но я мог бы использовать железные хуки маршрутизатора, такие как params.query . За исключением того, что любые статические файлы в /public обслуживаются обработчиком Meteor и обходят железный маршрутизатор.

(Я хочу использовать последнюю версию API. Здесь много сообщений до метеора 1.0 и до Ironrouter)


person LPG    schedule 30.06.2015    source источник


Ответы (2)


Конечно, это возможно. У вас есть полный доступ к объектам запроса и ответа HTTP-запроса, и вы даже можете подключить произвольное промежуточное ПО соединения.

Вот мое решение с использованием последнего из каталога /tmp:

var serveStatic = Meteor.npmRequire('serve-static');

if (Meteor.isClient) {
}

if (Meteor.isServer) {
    var serve = serveStatic('/tmp');
    // NOTE: this has to be an absolute path, since the relative
    // project directories change upon bundling/production

    Router.onBeforeAction(serve, {where: 'server'});

    Router.route('/:file', function () {
        this.next();
    }, {where: 'server'});
}

Для выполнения этой работы вам также понадобится пакет npm:

meteor add meteorhacks:npm

И вам нужно будет добавить serve-static в ваш файл packages.json:

{
    "serve-static": "1.10.0"
}

После этого любой файл /tmp/x.xyz будет доступен по вашему /x.xyz URL-адресу.

person Christian Fritz    schedule 30.06.2015
comment
Да, я вижу, как это будет работать. Но я не понимаю, как параметры строки запроса, которые я упомянул, могли бы чисто попасть в коллекцию монго. - person LPG; 12.07.2015
comment
Ваш вопрос был о попытке обслуживать статический файл за пределами /public. Если есть отдельный вопрос, то, возможно, лучше было бы и о stackoverflow задать отдельный вопрос? - person Christian Fritz; 12.07.2015

Вы можете использовать fs для сервера любого файла:

Router.route('/static/:filename', function (){
  var fs = Npm.require('fs'),
      path = '/tmp/' + this.params.filename; // make sure to validate input here

  // read the file
  var chunk = fs.createReadStream(path);

  // prepare HTTP headers
  var headers = {}, // add Content-type, Content-Lenght etc. if you need
      statusCode = 200; // everything is OK, also could be 404, 500 etc.

  // out content of the file to the output stream
  this.response.writeHead(statusCode, headers);
  chunk.pipe(this.response);
});
person romaroma    schedule 30.06.2015
comment
Я получаю сообщение об ошибке: Ошибка: ENOENT, нет такого файла или каталога '/tmp/cat.png', хотя файл существует. Где fs ищет /tmp/ ? - person LPG; 12.07.2015
comment
@LPG, вы можете убедиться, что у вас есть права на чтение файла? Вы можете попробовать установить полный доступ к файлу с помощью chmod 666 /tmp/cat.png. fs ищет '/tmp/' в текущем корневом каталоге, который в большинстве случаев является '/', однако может отличаться на общих хостингах. - person romaroma; 13.07.2015
comment
Та же ошибка :( Я пробовал каждое изменение уровня ОС. Есть некоторые другие хаки, использующие node.path , но я чувствую, что это не нужно делать (кстати, я на OSX yosemite) - person LPG; 13.07.2015
comment
@LPG, может быть, в OSX все по-другому? Что, если мы попытаемся выяснить, какой текущий каталог и какие файлы доступны для скрипта? Можете ли вы перечислить файлы, которые находятся в текущем каталоге, чтобы узнать, что является текущим каталогом, или, может быть, попробовать список файлов «/» или «/ tmp»? nodejs.org/api/fs.html#fs_fs_readdir_path_callback - person romaroma; 15.07.2015