, которая создаёт такой обратный вызов.
Вот обработчик запросов >PUT
:
>methods.PUT = function(path, respond, request) {
> var outStream = fs.createWriteStream(path);
> outStream.on("error", function(error) {
> respond(500, error.toString());
> });
> outStream.on("finish", function() {
> respond(204);
> });
> request.pipe(outStream);
>};
Здесь нам не нужно проверять существование файла – если он есть, мы его просто перезапишем. Опять мы используем >pipe
для передачи данных из читаемого потока в записываемый, в нашем случае – из запроса в файл. Если создать поток не удаётся, создаётся событие >“error”
, о чём мы сообщаем в ответе. Когда данные переданы успешно, >pipe
закроет оба потока, что приведёт к запуску события >“finish”
. А после этого мы можем отчитаться об успехе с кодом 204.
Полный скрипт сервера лежит тут: eloquentjavascript.net/code/file_server.js. Его можно скачать и запустить через Node. Конечно, его можно менять и дополнять для решения упражнений или экспериментов.
Утилита командной строки >curl
, общедоступная на unix-системах, может использоваться для создания HTTP запросов. Следующий фрагмент тестирует наш сервер. >–X
используется для задания метода запроса, а >–d
для включения тела запроса.
>$ curl http://localhost:8000/file.txt
>File not found
>$ curl -X PUT -d hello http://localhost:8000/file.txt
>$ curl http://localhost:8000/file.txt
>hello
>$ curl -X DELETE http://localhost:8000/file.txt
>$ curl http://localhost:8000/file.txt
>File not found
Первый запрос к >file.txt
завершается с ошибкой, поскольку файла ещё нет. Запрос >PUT
создаёт файл, и глядите-ка – следующий запрос его успешно получает. После его удаления через >DELETE
файл снова отсутствует.
В коде файлового сервера есть шесть мест, где мы перенаправляем исключения, когда мы не знаем, как обрабатывать ошибки. Поскольку исключения не передаются автоматически в функции обратного вызова, но передаются им как аргументы, их надо каждый раз обрабатывать персонально. Это сводит на нет преимущество обработки исключений, а именно, возможность централизованно обрабатывать ошибки.
Что будет, когда что-то реально выбросит исключение в системе? Мы не используем блоки >try
, потому оно будет передано на самый верх стека вызовов. В Node это приводит к прекращению выполнения программы и выводу информации об исключении (вместе с отслеживанием стека) на стандартный вывод.
Поэтому наш сервер будет падать при возникновении проблем в коде – в отличие от проблем с асинхронностью, которые будут переданы как аргументы в функции вызова. Если нам надо обрабатывать все исключения, возникающие при обработке запроса, чтобы мы точно отправили ответ, нам надо добавлять блоки