2013-03-15 4 views
39

Я пытаюсь обработать почтовый запрос, отправляемый на мой сервер node.js. Файл JavaScript с именем server.js отображает форму в браузере. Я хочу получить доступ к значениям формы после того, как они будут отправлены на сервер node.js.Как обращаться с запросом POST в 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/'); 
+12

Я бы настоятельно рекомендовал использовать (даже низкоуровневую) структуру для создания приложений с помощью Node. Я лично использую Express (http://expressjs.com/), однако есть другие варианты, если вы выберете. Помимо всего прочего, это позволит вам легко обрабатывать различные типы запросов и маршруты, а также статический контент. –

+0

См. Http://stackoverflow.com/questions/6158933/http-post-request-in-node-js – user568109

+0

Вы можете увидеть простой пример того, как обрабатывать HTTP POST с помощью Express.js в моем блоге http: // hectorcorrea .com/blog/introduction-to-node-js –

ответ

129

Я собираюсь использовать код при условии, и дать ответ более тщательно, чем покрыта в вашем вопросе для размещения людей в отдаленном будущем. Я также дам ответ, который использует «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 встроенный в «» строки запроса модуль для анализа фактических данных формы.

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» и «Рес», но это только мое предпочтение.)

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") { 

Здесь мы слушаем для входящих запросов, называемых «/ въездной», который - если вы поймали маленькую деталь выше - это «действие» нашего 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»). Конечно, вы можете делать все, что захотите, с этими данными (имея в виду цикл событий узла и асинхронный характер).

} 
    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 много лет назад, существует так много способов программирования программы, что легко увидеть, кто обманывает, делясь своей домашней работой.

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

+13

Почему не могу ли я увеличить этот показатель 10 раз?;) – Mixthos

+3

Это мысль, которая имеет значение. Благодаря! :) – L0j1k

+3

Ничего себе отличный ответ! Отлично для начала :) спасибо! – Martin

Смежные вопросы