Узел и Экспресс: отправка 404 ответа при использовании обратного вызова

#javascript #node.js #express

#javascript #node.js #экспресс

Вопрос:

Извините за плохое название, но я не смог придумать ничего лучше. Сначала взгляните на следующий фрагмент кода:

 app.use(function(request, response){
    request.addListener('end', function() {
        parseUrl(request.url, function(urlInfo) {
            if (urlInfo.notFound)
                response.send(404);
            else if (urlInfo.extension == '.html') {
                response.render(
                    urlInfo.path, 
                    { 
                        file: urlInfo.filenameWithoutExtension, 
                        url: urlInfo.url, 
                        directory: urlInfo.directory
                    },
                    function(error, html) {
                        if (error) {
                            console.log("Error rendering view: "   error);
                            response.send(404);
                        }

                        response.send(html);
                    });
            }
            else
                file.serve(request, response);
        });
    }).resume();
});
  

Этот код выполняется нормально и обслуживает страницы. Для определенных запросов parseUrl выполнит вызов веб-службы. Результат этой службы определяет, следует ли нам отправлять ответ 404 клиенту или нет. Таким образом, когда необходимо вызвать службу, обратный вызов вызывается после веб-запроса, в противном случае обратный вызов вызывается просто встроенным.

Код выполняется нормально, но я получаю ответ 200. Просматривая файлы журнала, выясняется, что response.send(404) вызывается после отправки ответа 200. Итак, я предполагаю, что request.resume() вызывается во время выполнения веб-запроса. Это действительно имеет смысл.

Однако, что бы я ни делал, я не могу заставить это функционировать так, как я хочу. Я пытался:

  • Перемещение запроса.resume в конец обратного вызова
  • Удаление app.use и выполнение request.resume в конце обратного вызова.

Обычно, что бы я ни делал, я прерываю работу сервера, и либо истекает время ожидания, либо возникают ошибки.

Я просмотрел веб-страницы и нахожусь в недоумении. Если кто-нибудь сможет указать мне правильное направление, я был бы очень признателен. Очевидно, что мне здесь не хватает важной части знаний, я новичок в node и express, это мой первый проект.

Заранее спасибо.

Приветствую, Марк

ОБНОВЛЕНИЕ: просматриваем это еще раз и читаем https://github.com/joyent/node/blob/master/doc/api/stream.markdown . Кажется, мне нужно явно вызвать pause в конечном событии при использовании асинхронного обратного вызова, иначе поток закроется при возвращении. Я попробую это позже сегодня и отчитаюсь.

Комментарии:

1. попробуйте сказать return после этой строки response.send(404); .

2. Хотя я не думал, что это сработает, я просто попробовал, и это не имело никакого значения. Однако спасибо за ваш быстрый ответ.

3. Просто я думал, что эта response.send(html); строка будет вызываться каждый раз, даже если возникает ошибка. Так я и думал…

4. Mritunjay: Да, действительно, это ошибка, просто не та ошибка, которую я искал 🙂

Ответ №1:

Это был просто вопрос приостановки потока запросов на время выполнения асинхронного вызова. В итоге мой метод закончился так:

 app.use(function(request, response){
    request.on('end', function() {
        var parseStatus = parseUrl(request.url, function(urlInfo, status) {
            if (urlInfo.notFound)
                response.send(404);
            else if (urlInfo.extension == '.html') {
                response.render(
                    urlInfo.path,
                    {
                        file: urlInfo.filenameWithoutExtension,
                        url: urlInfo.url,
                        directory: urlInfo.directory
                    },
                    function(error, html) {
                        if (error) {
                            console.log("Error rendering view: "   error);
                            response.send(404);
                        }
                        else
                            response.send(html);
                    });
            } else
                file.serve(request, response);

            if (status.executedAsynchronously)
                request.resume();
        });

        if (parseStatus.executedAsynchronously)
            request.pause();

    }).resume();
});
  

Комментарии:

1. Не забудьте установить для ответа StatusCode = 404

2. Почему? Согласно документации по expressjs.org любое число, переданное в res.send(), будет интерпретироваться как код состояния.