Подтвердить что ты не робот

Как обращаться с запросом POST в node.js

Я пытаюсь обработать почтовый запрос, отправляемый на мой сервер node.js. Файл JavaScript с именем server.js отображает форму в браузере. Я хочу получить доступ к значениям формы после их публикации в бэкэнде node.js.

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

Код server.js:

var http = require('http');

http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<html><body>'
    + '<h1>XYZ Repository Commit Monitor</h1>'
    + '<form method="post" action="." enctype="application/x-www-form-urlencoded"><fieldset>'
    + '<div><label for="UserName">User Name:</label><input type="text" id="UserName" name="UserName" /></div>'
    + '<div><label for="Repository">Repository:</label><input type="text" id="Repository" name="Repository" /></div>'
    + '<div><label for="Branch">Branch:</label><input type="text" id="Branch" name="Branch" value="master" /></div>'
    + '<div><input id="ListCommits" type="submit" value="List Commits" /></div>'
    + '</fieldset></form>'
    + '</body></html>');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');
4b9b3361

Ответ 1

Я собираюсь использовать предоставленный вами код и дать более подробный ответ, чем тот, который рассмотрен в вашем вопросе, чтобы разместить людей в The Distant Future. Я также дам ответ, в котором используется "Vanilla JS" (http://www.vanilla-js.com/), потому что я думаю, что слишком много хипстеров говорят "использовать фреймворк", когда вы "пытаюсь понять, как это работает. Я думаю, что причина, по которой они это делают, заключается в том, что кто-то сказал им" использовать структуру ", когда они изучают, как это работает. Поскольку они не являются хакерами, они не хотели пытаться понять процесс, поэтому очень часто многие из них не понимают, как это сделать самостоятельно, без рамки (отсюда повсеместное использование" рамки"). Вы станете лучшим хакером, понимая, что происходит под капотом, и я надеюсь, что этот ответ поможет вам в этом отношении.

Теперь, когда вы хотите принять данные POST (формы) через форму, которую вы выводите, необходимо обеспечить механизм маршрутизации на вашем сервере. Это означает, что вы сообщите своему серверу о форме для людей, посещающих ваш сайт, но затем, если пользователь отправит форму, Node направит данные POST в небольшую функцию обработки. Сначала я дал полный ответ, а затем рассекретил его дальше, чтобы разместить людей, желающих учиться на коде.

var http = require('http');
var qs = require('querystring');
var formOutput = '<html><body>'
  + '<h1>XYZ Repository Commit Monitor</h1>'
  + '<form method="post" action="inbound" enctype="application/x-www-form-urlencoded"><fieldset>'
  + '<div><label for="UserName">User Name:</label><input type="text" id="UserName" name="UserName" /></div>'
  + '<div><label for="Repository">Repository:</label><input type="text" id="Repository" name="Repository" /></div>'
  + '<div><label for="Branch">Branch:</label><input type="text" id="Branch" name="Branch" value="master" /></div>'
  + '<div><input id="ListCommits" type="submit" value="List Commits" /></div></fieldset></form></body></html>';
var serverPort = 8124;
http.createServer(function (request, response) {
  if(request.method === "GET") {
    if (request.url === "/favicon.ico") {
      response.writeHead(404, {'Content-Type': 'text/html'});
      response.write('<!doctype html><html><head><title>404</title></head><body>404: Resource Not Found</body></html>');
      response.end();
    } else {
      response.writeHead(200, {'Content-Type': 'text/html'});
      response.end(formOutput);
    }
  } else if(request.method === "POST") {
    if (request.url === "/inbound") {
      var requestBody = '';
      request.on('data', function(data) {
        requestBody += data;
        if(requestBody.length > 1e7) {
          response.writeHead(413, 'Request Entity Too Large', {'Content-Type': 'text/html'});
          response.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
        }
      });
      request.on('end', function() {
        var formData = qs.parse(requestBody);
        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write('<!doctype html><html><head><title>response</title></head><body>');
        response.write('Thanks for the data!<br />User Name: '+formData.UserName);
        response.write('<br />Repository Name: '+formData.Repository);
        response.write('<br />Branch: '+formData.Branch);
        response.end('</body></html>');
      });
    } else {
      response.writeHead(404, 'Resource Not Found', {'Content-Type': 'text/html'});
      response.end('<!doctype html><html><head><title>404</title></head><body>404: Resource Not Found</body></html>');
    }
  } else {
    response.writeHead(405, 'Method Not Supported', {'Content-Type': 'text/html'});
    return response.end('<!doctype html><html><head><title>405</title></head><body>405: Method Not Supported</body></html>');
  }
}).listen(serverPort);
console.log('Server running at localhost:'+serverPort);

И теперь для разбивки, объясняющего, почему я сделал то, что сделал.

var http = require('http');
var qs = require('querystring');

Во-первых, вы собираетесь добавить Node встроенный модуль "querystring" для анализа фактических данных формы.

var formOutput = '<html><body>'
  + '<h1>XYZ Repository Commit Monitor</h1>'
  + '<form method="post" action="/inbound" enctype="application/x-www-form-urlencoded"><fieldset>'
  + '<div><label for="UserName">User Name:</label><input type="text" id="UserName" name="UserName" /></div>'
  + '<div><label for="Repository">Repository:</label><input type="text" id="Repository" name="Repository" /></div>'
  + '<div><label for="Branch">Branch:</label><input type="text" id="Branch" name="Branch" value="master" /></div>'
  + '<div><input id="ListCommits" type="submit" value="List Commits" /></div></fieldset></form></body></html>';
var serverPort = 8124;

Я переместил вывод формы над нашим механизмом управления сервером/маршрутизацией/формой, потому что тогда логику гораздо легче читать. Я также переместил информацию о порте прослушивания сервера здесь, потому что вам нужно только изменить его в одном месте, а не на многих ниже.

http.createServer(function (request, response) {

(Я обычно сокращаю параметры этой функции до "req" и ​​ "res", но это только мои предпочтения.)

  if(request.method === "GET") {
    if (request.url === "/favicon.ico") {
      response.writeHead(404, {'Content-Type': 'text/html'});
      response.write(notFound);
      response.end();

Здесь я включил простой пример маршрутизации. В этом случае у нас есть сервер, который слушает запросы на "favicon.ico" - запрос, сделанный вместе со всеми начальными запросами на веб-страницу всеми основными браузерами. Этот файл - это маленький значок, который вы можете увидеть на вкладках каждой веб-страницы, которую вы посещаете. Для наших целей нам не нужно обслуживать значки, но мы будем обрабатывать входящие запросы, чтобы он показывал некоторые основные механизмы маршрутизации.

    } else {
      response.writeHead(200, {'Content-Type': 'text/html'});
      response.end(formOutput);
    }

Если ваши посетители указывают на свой браузер на ЛЮБОЙ другой ресурс на вашем сервере с помощью метода GET по умолчанию (помимо "favicon.ico", который мы только что обработали выше), мы будем обслуживать их форму.

  } else if(request.method === "POST") {

В противном случае, если ваши посетители указывают POST на вашем сервере, скорее всего, они отправили форму, которую они получили с предыдущим запросом GET.

    if (request.url === "/inbound") {

Здесь мы слушаем входящие запросы, называемые "/inbound", которые - если вы поймали небольшую деталь выше - это "действие" нашей HTML-формы. Как вы знаете, "действие" формы сообщает браузеру, куда отправить данные формы.

      var requestBody = '';
      request.on('data', function(data) {
        requestBody += data;
        if(requestBody.length > 1e7) {
          response.writeHead(413, 'Request Entity Too Large', {'Content-Type': 'text/html'});
          response.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
        }
      });
      request.on('end', function() {
        var formData = qs.parse(requestBody);

Это может показаться немного запутанным, но я этого не обещаю. Запросы POST могут быть отправлены как многочастные сообщения из клиентского браузера. С чем-то размером с несколько переменных в форме вы вряд ли когда-либо увидите это, но по мере того, как вы масштабируете объем данных, которые вы обрабатываете, вы увидите это. Если вы наблюдательны, вы также увидите оператор if() с вопросом о длине данных POST. Злоумышленник может убить ваш сервер, загрузив бесконечный файл, но не если мы примем меры. Это ограничивает тело данных POST до десяти мегабайт, но вы должны соответствующим образом отрегулировать его. Знание об этих вещах предотвращает будущую головную боль, и я не хочу, чтобы у вас была головная боль.

        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write('<!doctype html><html><head><title>response</title></head><body>');
        response.write('Thanks for the data!<br />User Name: '+formData.UserName);
        response.write('<br />Repository Name: '+formData.Repository);
        response.write('<br />Branch: '+formData.Branch);
        response.end('</body></html>');
      });

И здесь мы используем данные формы. Из-за характера Javascript эти имена переменных являются CASE SENSITIVE (например, "UserName" вместо "username" ). Конечно, вы можете делать все, что захотите, с этими данными (имея в виду Node цикл событий и асинхронный характер).

    }
    response.writeHead(404, 'Resource Not Found', {'Content-Type': 'text/html'});
    return response.end('<!doctype html><html><head><title>404</title></head><body>413: Request Entity Too Large</body></html>');

Чтобы продолжить наш пример маршрутизации, то, что мы здесь сделали, включает в себя все, что содержится под оператором if(), который отправляет клиенту общий запрос "Не найден" 404 на любой запрос POST, который мы еще не обработали.

  } else {
    response.writeHead(405, 'Method Not Supported', {'Content-Type': 'text/html'});
    return response.end('<!doctype html><html><head><title>405</title></head><body>405: Method Not Supported</body></html>');
  }
}).listen(serverPort);
console.log('Server running at localhost:'+serverPort);

И теперь мы только что закончили код, включая немного кода для обработки запросов со странными методами. Есть несколько вещей, которые я не рассматривал (структура функции, данные пустой формы и т.д.), Но есть действительно много способов достижения ваших целей. Как сказал один из моих профессоров CS много лет назад, существует так много способов программирования программы, что легко увидеть, кто обманывает, делясь своей домашней работой.

Я надеюсь, что вы (и кто-либо еще) увидите, что это не какой-то эзотерический или даже слегка сложный процесс, чтобы делать что-то в Node с помощью встроенных модулей вместо того, чтобы полагаться на внешние сторонние библиотеки, такие как Express. Эти библиотеки имеют свое место в мире, но не следуют за стадом: сделайте обоснованное решение о своем коде, потому что в конце дня вы отвечаете за него (а не некоторые люди в переполнении стека).